From fe62a0a175a4c2d5953e86926cd43823ff94a44c Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Thu, 29 Jun 2023 23:08:34 +0530 Subject: [PATCH 01/11] Retrofit generic implementation --- modules/build.gradle | 7 + .../java/app/lounge/networking/FetchError.kt | 50 +++++ .../app/lounge/networking/RetrofitConfig.kt | 29 +++ .../app/lounge/networking/RetrofitFetching.kt | 201 ++++++++++++++++++ .../networking/RetrofitRawResultProcessing.kt | 75 +++++++ 5 files changed, 362 insertions(+) create mode 100644 modules/src/main/java/app/lounge/networking/FetchError.kt create mode 100644 modules/src/main/java/app/lounge/networking/RetrofitConfig.kt create mode 100644 modules/src/main/java/app/lounge/networking/RetrofitFetching.kt create mode 100644 modules/src/main/java/app/lounge/networking/RetrofitRawResultProcessing.kt diff --git a/modules/build.gradle b/modules/build.gradle index 6ac8c12d8..849973854 100644 --- a/modules/build.gradle +++ b/modules/build.gradle @@ -9,6 +9,7 @@ ext { core_version = '1.10.1' gson_version = '2.9.0' kotlin_reflection = '1.8.10' + retrofit_version = '2.9.0' } android { @@ -44,6 +45,12 @@ dependencies { implementation "com.google.code.gson:gson:$gson_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_reflection" + // region Retrofit + implementation("com.squareup.retrofit2:retrofit:$retrofit_version") + implementation("com.squareup.retrofit2:converter-gson:$retrofit_version") + implementation("com.squareup.retrofit2:converter-scalars:$retrofit_version") + // endregion + testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/modules/src/main/java/app/lounge/networking/FetchError.kt b/modules/src/main/java/app/lounge/networking/FetchError.kt new file mode 100644 index 000000000..271b4ab3b --- /dev/null +++ b/modules/src/main/java/app/lounge/networking/FetchError.kt @@ -0,0 +1,50 @@ +package app.lounge.networking + + +//region Generic Network Error Types + +sealed interface FetchError { + data class Network(val underlyingError: AnyFetchError) : FetchError +} + +/** Supertype for network error types. */ +sealed interface AnyFetchError { + + var description: String + + enum class BadRequest(override var description: String) : AnyFetchError { + Encode("FIXME: Error encoding request! $dumpKeyWord"), + Decode("FIXME: Error decoding request! $dumpKeyWord"), + } + + enum class NotFound(override var description: String) : AnyFetchError { + MissingData("No data found! $dumpKeyWord"), + MissingNetwork("No network! $dumpKeyWord") + } + + data class BadStatusCode (val statusCode: Int, val rawResponse: Any) : AnyFetchError { + override var description: String = + "Bad status code: $statusCode. Raw response: $rawResponse" + } + + /** + * Represents a vague error case typically caused by `UnknownHostException`. + * This error case is encountered if and only if network status cannot be determined + * while the `UnknownHostException` is received. + */ + data class Unknown( + override var description: String = "Unknown Error! $dumpKeyWord" + ) : AnyFetchError + + companion object { + const val dumpKeyWord: String = "dump:-" + + fun make(error: AnyFetchError, addingDump: String) : AnyFetchError { + error.description = error.description + addingDump + return error + } + } + +} + +//endregion diff --git a/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt b/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt new file mode 100644 index 000000000..c4b89b6dc --- /dev/null +++ b/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt @@ -0,0 +1,29 @@ +package app.lounge.networking + +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import java.util.concurrent.TimeUnit + +/** + * Implement retrofit configuration + * 1. Try to use single instance of configuration + * 2. Generic way to handle success or failure + * 3. API parsing can be clean and testable + * + * NOTE: Try to use naming which define the action for the logic. + * */ + +internal fun Retrofit.Builder.appLounge( + baseURL: String, + shouldFollowRedirects: Boolean, + callTimeoutInSeconds: Long, +) : Retrofit { + return this.baseUrl(baseURL) + .client( + OkHttpClient.Builder() + .callTimeout(callTimeoutInSeconds, TimeUnit.SECONDS) + .followRedirects(shouldFollowRedirects) + .build() + ) + .build() +} \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/networking/RetrofitFetching.kt b/modules/src/main/java/app/lounge/networking/RetrofitFetching.kt new file mode 100644 index 000000000..6c38171a0 --- /dev/null +++ b/modules/src/main/java/app/lounge/networking/RetrofitFetching.kt @@ -0,0 +1,201 @@ +package app.lounge.networking + +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import java.lang.IllegalStateException +import java.net.UnknownHostException + + +//region Retrofit Asynchronous Networking +interface RetrofitFetching { + val executor: Executor get() = callEnqueue + + val checkNetwork: (() -> Boolean)? get() = null + + interface Executor { + fun fetchAndCallback(endpoint: Call, callback: Callback) + } + + /** + * An object that receives Retrofit `Callback` arguments and determines whether or not + * an error should be returned. Use to return specific error cases for a given network request. + */ + interface ResultProcessing { + /** + * Return `R` if possible to cast given object to `R` or return `null`. + * This lambda is required due to jvm's type-erasing for generic types. + */ + val tryCastResponseBody: (Any?) -> R? + + /** Return result, success/failure, for the received request response */ + val resultFromResponse: (call: Call, response: Response) -> RetrofitResult + + /** Return error object `E` for the given failed request. */ + val errorFromFailureResponse: (call: Call<*>, t: Throwable) -> E + + /** Return error object `E` that contains/represents the given `AnyFetchError` */ + val errorFromNetworkFailure: (AnyFetchError) -> E + + } + + companion object { + /** Creates and returns a network request executor using Retrofit `Call` enqueue. */ + val callEnqueue: Executor + get() { + return object : Executor { + override fun fetchAndCallback(endpoint: Call, callback: Callback) { + endpoint.enqueue(callback) + } + } + } + } +} + +/** + * Fetch for response type `R` and callback in `success` callback. Invokes failure with + * an error subtype of `AnyFetchError` upon failure. + * + * @param usingExecutor Network request executor (set to `this.executor` by default) + * @param endpoint The API endpoint that should be fetched + * @param success Success callback with the response `R` + * @param failure Failure callback with an error case from `AnyFetchError` subtypes + */ +inline fun RetrofitFetching.fetch( + usingExecutor: RetrofitFetching.Executor = executor, + endpoint: Call, + noinline success: (R) -> Unit, + noinline failure: (FetchError) -> Unit +) { + val resultProcessing = RetrofitResultProcessing( + errorFromNetworkFailure = { FetchError.Network(it) }, + hasNetwork = checkNetwork + ) + fetch(usingExecutor, endpoint, resultProcessing, success, failure) +} + +/** + * Fetch for response type `R` and callback in `success` callback. Invokes failure with + * an error subtype of `E : AnyFetchError` upon failure. + * + * @param usingExecutor Network request executor (set to `this.executor` by default) + * @param endpoint The API endpoint that should be fetched + * @param resultProcessing Processes response and finds corresponding error case (if needed) + * @param success Success callback with the response `R` + * @param failure Failure callback with an error case from given error subtype `E` + */ +fun RetrofitFetching.fetch( + usingExecutor: RetrofitFetching.Executor = executor, + endpoint: Call, + resultProcessing: RetrofitFetching.ResultProcessing, + success: (R) -> Unit, + failure: (E) -> Unit +) { + fetch(usingExecutor, endpoint, resultProcessing) { it.invoke(success, failure) } +} + +inline fun RetrofitResult.invoke(success: (R) -> Unit, failure: (E) -> Unit) { + return when (this) { + is RetrofitResult.Success -> success(this.result) + is RetrofitResult.Failure -> failure(this.error) + } +} + +sealed class RetrofitResult { + data class Success(val result: R) : RetrofitResult() + data class Failure(val error: E) : RetrofitResult() +} + +private fun fetch( + usingExecutor: RetrofitFetching.Executor, + endpoint: Call, + resultProcessing: RetrofitFetching.ResultProcessing, + callback: (RetrofitResult) -> Unit, +) { + usingExecutor.fetchAndCallback(endpoint, object : Callback { + override fun onFailure(call: Call, t: Throwable) { + callback(RetrofitResult.Failure(resultProcessing.errorFromFailureResponse(call, t))) + } + + override fun onResponse(call: Call, response: Response) { + callback(resultProcessing.resultFromResponse(call, response)) + } + }) +} + +//endregion + +//region Retrofit Standard Result Processing + +/** Returns result processing object for given response type `R` and error type `E` */ +open class RetrofitResultProcessing( + override val tryCastResponseBody: (Any?) -> R?, + override val errorFromNetworkFailure: (AnyFetchError) -> E, + hasNetwork: (() -> Boolean)? = null, +) : RetrofitFetching.ResultProcessing { + + companion object { + inline operator fun invoke( + noinline errorFromNetworkFailure: (AnyFetchError) -> E, + noinline hasNetwork: (() -> Boolean)? = null + ) : RetrofitResultProcessing { + return RetrofitResultProcessing( + tryCastResponseBody = { + if (it == null && R::class.java == Unit::class.java) { Unit as R } + else { it as? R } + }, + errorFromNetworkFailure = errorFromNetworkFailure, hasNetwork = hasNetwork + ) + } + } + + override var errorFromFailureResponse: (call: Call<*>, t: Throwable) -> E = { call, t -> + val error: AnyFetchError = when(t) { + is UnknownHostException -> errorForUnknownHostException + is IllegalStateException -> errorForIllegalStateException + + //TODO: Check other cases + else -> AnyFetchError.Unknown() + } + errorFromNetworkFailure( + AnyFetchError.make(error = error, addingDump = "(Throwable): $t\n(Call): $call") + ) + } + + override var resultFromResponse: + (Call, Response) -> RetrofitResult = { call, response -> + if (response.isSuccessful) { + tryCastResponseBody(response.body())?.let { body -> + RetrofitResult.Success(body) + } ?: RetrofitResult.Failure( + errorFromNetworkFailure( + AnyFetchError.make( + error = AnyFetchError.NotFound.MissingData, + addingDump = "(Response): $response\n(Call): $call" + ) + ) + ) + } else { + RetrofitResult.Failure( + errorFromNetworkFailure(AnyFetchError.BadStatusCode(response.code(), response)) + ) + } + } + + //region Exception to AnyFetchError mapping + + var errorForUnknownHostException: AnyFetchError = if (hasNetwork != null) { + if (hasNetwork()) AnyFetchError.BadRequest.Encode + else AnyFetchError.NotFound.MissingNetwork + } else { + // Cannot distinguish the error case from `MissingNetwork` and `Encode` error. + AnyFetchError.Unknown() + } + + var errorForIllegalStateException: AnyFetchError = AnyFetchError.BadRequest.Decode + + //endregion + +} + +//endregion \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/networking/RetrofitRawResultProcessing.kt b/modules/src/main/java/app/lounge/networking/RetrofitRawResultProcessing.kt new file mode 100644 index 000000000..f983bf653 --- /dev/null +++ b/modules/src/main/java/app/lounge/networking/RetrofitRawResultProcessing.kt @@ -0,0 +1,75 @@ +package app.lounge.networking + +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +interface RawResponseProcessing { + val onResponse: (Call, Response) -> RetrofitResult +} + + +fun RetrofitFetching.fetch( + usingExecutor: RetrofitFetching.Executor = executor, + endpoint: Call, + processing: Processing, + success: (R) -> Unit, + failure: (E) -> Unit +) where Processing : RawResponseProcessing, + Processing : RetrofitFetching.ResultProcessing { + fetch(usingExecutor, endpoint, processing) { it.invoke(success, failure) } +} + + +private fun fetch( + usingExecutor: RetrofitFetching.Executor, + endpoint: Call, + processing: Processing, + callback: (RetrofitResult) -> Unit, +) where Processing : RawResponseProcessing, + Processing : RetrofitFetching.ResultProcessing { + usingExecutor.fetchAndCallback(endpoint, object : Callback { + override fun onFailure(call: Call, t: Throwable) { + callback(RetrofitResult.Failure(processing.errorFromFailureResponse(call, t))) + } + + override fun onResponse(call: Call, response: Response) { + callback(processing.onResponse(call, response)) + } + }) +} + +class RetrofitRawResultProcessing( + override val onResponse: (Call<*>, Response<*>) -> RetrofitResult, + override val tryCastResponseBody: (Any?) -> R?, + override val errorFromNetworkFailure: (AnyFetchError) -> E, + hasNetwork: (() -> Boolean)? = null, +) : RetrofitResultProcessing(tryCastResponseBody, errorFromNetworkFailure, hasNetwork), + RawResponseProcessing { + + override var resultFromResponse: (Call, Response) -> RetrofitResult = { + call, response -> + when(val customResult = onResponse(call, response)) { + is RetrofitResult.Success -> customResult + is RetrofitResult.Failure -> super.resultFromResponse(call, response) + } + } + + companion object { + inline operator fun invoke( + noinline onResponse: (Call<*>, Response<*>) -> RetrofitResult, + noinline errorFromNetworkFailure: (AnyFetchError) -> E, + noinline hasNetwork: (() -> Boolean)? = null + ) : RetrofitRawResultProcessing { + return RetrofitRawResultProcessing( + onResponse = onResponse, + tryCastResponseBody = { + if (it == null && R::class.java == Unit::class.java) { Unit as R } + else { it as? R } + }, + errorFromNetworkFailure = errorFromNetworkFailure, hasNetwork = hasNetwork + ) + } + } + +} -- GitLab From 96956a3817de342f915c5037b4ded3a21eb9c593 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Thu, 29 Jun 2023 23:09:11 +0530 Subject: [PATCH 02/11] Added google and anonymous user structure --- .../src/main/java/app/lounge/users/Google.kt | 8 +++ .../src/main/java/app/lounge/users/Session.kt | 11 ++++ .../app/lounge/users/anonymous/Anonymous.kt | 35 +++++++++++ .../lounge/users/anonymous/AnonymousAPI.kt | 33 +++++++++++ .../users/anonymous/RetrofitAnonymousAPI.kt | 58 +++++++++++++++++++ 5 files changed, 145 insertions(+) create mode 100644 modules/src/main/java/app/lounge/users/Google.kt create mode 100644 modules/src/main/java/app/lounge/users/Session.kt create mode 100644 modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt create mode 100644 modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt create mode 100644 modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt diff --git a/modules/src/main/java/app/lounge/users/Google.kt b/modules/src/main/java/app/lounge/users/Google.kt new file mode 100644 index 000000000..48ce6c2dd --- /dev/null +++ b/modules/src/main/java/app/lounge/users/Google.kt @@ -0,0 +1,8 @@ +package app.lounge.users + +/** + * Implement API related to Google login flow only. + * 1. Login api for google users. + * 2. Parsing google user data. For now use typealias object, later we will refactor with generic type + * 3. Add unit test cases for the api functions. + * */ \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/users/Session.kt b/modules/src/main/java/app/lounge/users/Session.kt new file mode 100644 index 000000000..5885edea2 --- /dev/null +++ b/modules/src/main/java/app/lounge/users/Session.kt @@ -0,0 +1,11 @@ +package app.lounge.users + +/** + * Handle user login session in the file. + * This should be the only file which communicate with application regarding user data + * + * 1. Application facing api will be part of this file. + * 2. Manage user session for Anonymous, Google, PWA users. + * 3. In case of invalid user data, timeout etc. inform application about session failure. + * 4. If possible add session api testcases. + */ \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt b/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt new file mode 100644 index 000000000..8c888f012 --- /dev/null +++ b/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt @@ -0,0 +1,35 @@ +package app.lounge.users.anonymous + +/** + * Implement API related to Anonymous login flow only. + * 1. Login api for Anonymous users. + * 2. Parsing Anonymous user data. For now use typealias object, later we will refactor with generic type + * 3. Add unit test cases for the api functions. + * */ + +interface Anonymous { + + val api: AnonymousAPI + + companion object { + + fun anonymousRequestFor( + api: AnonymousAPI = AnonymousAPI.create() + ) : Anonymous { + return object : Anonymous { + override val api: AnonymousAPI = api + } + } + } + + // pass input from this function + fun login( + success : () -> Unit, + failure : () -> Unit + ) { + api.performLogin( + success = success, + failure = failure + ) + } +} \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt b/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt new file mode 100644 index 000000000..5ef1a8ae1 --- /dev/null +++ b/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt @@ -0,0 +1,33 @@ +package app.lounge.users.anonymous + +import app.lounge.BuildConfig + +interface AnonymousAPI { + + companion object { + private const val tokenBaseURL: String = "https://eu.gtoken.ecloud.global" + private const val loginBaseURL: String = "GooglePlayApi.URL_SYNC" + + fun create(baseURL: String = tokenBaseURL) : AnonymousAPI { + return RetrofitAnonymousAPI( + baseURL = baseURL, + anonymousUserEndpointFollowsRedirects = true, + callTimeoutInSeconds = 30 + ) + } + } + + fun performLogin( + success : () -> Unit, + failure : () -> Unit + ) + + object Header { + val authData: Map get() { + return mapOf( + Pair("User-Agent", BuildConfig.BUILD_TYPE), // CommonUtilsFunctions.getAppBuildInfo() + ) + } + } + +} \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt b/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt new file mode 100644 index 000000000..1b9b296f0 --- /dev/null +++ b/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt @@ -0,0 +1,58 @@ +package app.lounge.users.anonymous + +import app.lounge.networking.RetrofitFetching +import app.lounge.networking.RetrofitRawResultProcessing +import app.lounge.networking.RetrofitResult +import app.lounge.networking.appLounge +import app.lounge.networking.fetch +import okhttp3.RequestBody +import retrofit2.Call +import retrofit2.Retrofit +import retrofit2.http.Body +import retrofit2.http.HeaderMap +import retrofit2.http.POST + +internal class RetrofitAnonymousAPI( + baseURL: String, + anonymousUserEndpointFollowsRedirects: Boolean, + callTimeoutInSeconds: Long, +): AnonymousAPI, RetrofitFetching { + + private val anonymousUserEndPoint: AnonymousUserEndPointEndpoint = Retrofit.Builder().appLounge( + baseURL = baseURL, + shouldFollowRedirects = anonymousUserEndpointFollowsRedirects, + callTimeoutInSeconds = callTimeoutInSeconds + ).create(AnonymousUserEndPointEndpoint::class.java) + + interface AnonymousUserEndPointEndpoint { + + @POST + fun authDataRequest( + @HeaderMap headers: Map = AnonymousAPI.Header.authData, + @Body requestBody: RequestBody? + ): Call + } + + override fun performLogin(success: () -> Unit, failure: () -> Unit) { + /*fetch( + endpoint = anonymousUserEndPoint.authDataRequest(requestBody = null), + processing = , + )*/ + } + + + /*private val cardTerminalResultProcessing = RetrofitRawResultProcessing< + CardTerminalRetrofitCallRequestResponse, + CardTerminalRetrofitCallFailure, + CardTerminalRetrofitCallResponse>( + errorFromNetworkFailure = { CardTerminalRetrofitCallFailure.Network(it) }, + onResponse = { _, response -> + RetrofitResult.Success(CardTerminalRetrofitCallResponse("")) + } + )*/ + +} + +internal typealias CardTerminalRetrofitCallResponse = String +internal typealias CardTerminalRetrofitCallRequestResponse = String +internal typealias CardTerminalRetrofitCallFailure = String -- GitLab From 8d4b61adf8130e646fa9b03341d45d067df7dba0 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Fri, 30 Jun 2023 20:23:36 +0530 Subject: [PATCH 03/11] Clean up redundant code --- .../networking/RetrofitRawResultProcessing.kt | 75 ------------------- .../users/anonymous/RetrofitAnonymousAPI.kt | 18 ----- 2 files changed, 93 deletions(-) delete mode 100644 modules/src/main/java/app/lounge/networking/RetrofitRawResultProcessing.kt diff --git a/modules/src/main/java/app/lounge/networking/RetrofitRawResultProcessing.kt b/modules/src/main/java/app/lounge/networking/RetrofitRawResultProcessing.kt deleted file mode 100644 index f983bf653..000000000 --- a/modules/src/main/java/app/lounge/networking/RetrofitRawResultProcessing.kt +++ /dev/null @@ -1,75 +0,0 @@ -package app.lounge.networking - -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response - -interface RawResponseProcessing { - val onResponse: (Call, Response) -> RetrofitResult -} - - -fun RetrofitFetching.fetch( - usingExecutor: RetrofitFetching.Executor = executor, - endpoint: Call, - processing: Processing, - success: (R) -> Unit, - failure: (E) -> Unit -) where Processing : RawResponseProcessing, - Processing : RetrofitFetching.ResultProcessing { - fetch(usingExecutor, endpoint, processing) { it.invoke(success, failure) } -} - - -private fun fetch( - usingExecutor: RetrofitFetching.Executor, - endpoint: Call, - processing: Processing, - callback: (RetrofitResult) -> Unit, -) where Processing : RawResponseProcessing, - Processing : RetrofitFetching.ResultProcessing { - usingExecutor.fetchAndCallback(endpoint, object : Callback { - override fun onFailure(call: Call, t: Throwable) { - callback(RetrofitResult.Failure(processing.errorFromFailureResponse(call, t))) - } - - override fun onResponse(call: Call, response: Response) { - callback(processing.onResponse(call, response)) - } - }) -} - -class RetrofitRawResultProcessing( - override val onResponse: (Call<*>, Response<*>) -> RetrofitResult, - override val tryCastResponseBody: (Any?) -> R?, - override val errorFromNetworkFailure: (AnyFetchError) -> E, - hasNetwork: (() -> Boolean)? = null, -) : RetrofitResultProcessing(tryCastResponseBody, errorFromNetworkFailure, hasNetwork), - RawResponseProcessing { - - override var resultFromResponse: (Call, Response) -> RetrofitResult = { - call, response -> - when(val customResult = onResponse(call, response)) { - is RetrofitResult.Success -> customResult - is RetrofitResult.Failure -> super.resultFromResponse(call, response) - } - } - - companion object { - inline operator fun invoke( - noinline onResponse: (Call<*>, Response<*>) -> RetrofitResult, - noinline errorFromNetworkFailure: (AnyFetchError) -> E, - noinline hasNetwork: (() -> Boolean)? = null - ) : RetrofitRawResultProcessing { - return RetrofitRawResultProcessing( - onResponse = onResponse, - tryCastResponseBody = { - if (it == null && R::class.java == Unit::class.java) { Unit as R } - else { it as? R } - }, - errorFromNetworkFailure = errorFromNetworkFailure, hasNetwork = hasNetwork - ) - } - } - -} diff --git a/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt b/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt index 1b9b296f0..8fe81ae67 100644 --- a/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt +++ b/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt @@ -1,10 +1,7 @@ package app.lounge.users.anonymous import app.lounge.networking.RetrofitFetching -import app.lounge.networking.RetrofitRawResultProcessing -import app.lounge.networking.RetrofitResult import app.lounge.networking.appLounge -import app.lounge.networking.fetch import okhttp3.RequestBody import retrofit2.Call import retrofit2.Retrofit @@ -40,19 +37,4 @@ internal class RetrofitAnonymousAPI( )*/ } - - /*private val cardTerminalResultProcessing = RetrofitRawResultProcessing< - CardTerminalRetrofitCallRequestResponse, - CardTerminalRetrofitCallFailure, - CardTerminalRetrofitCallResponse>( - errorFromNetworkFailure = { CardTerminalRetrofitCallFailure.Network(it) }, - onResponse = { _, response -> - RetrofitResult.Success(CardTerminalRetrofitCallResponse("")) - } - )*/ - } - -internal typealias CardTerminalRetrofitCallResponse = String -internal typealias CardTerminalRetrofitCallRequestResponse = String -internal typealias CardTerminalRetrofitCallFailure = String -- GitLab From 344c0e46445114c60848d0a1924c6b6224e38d64 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Sun, 2 Jul 2023 22:54:34 +0530 Subject: [PATCH 04/11] Modify the Retrofit config for Anonymous User data --- modules/build.gradle | 2 + .../java/app/lounge/AnonymousUserAPITest.kt | 79 +++++++++++++++++++ modules/src/main/AndroidManifest.xml | 2 + .../java/app/lounge/extension/Extension.kt | 7 ++ .../app/lounge/networking/RetrofitConfig.kt | 11 +++ .../app/lounge/users/anonymous/Anonymous.kt | 12 ++- .../lounge/users/anonymous/AnonymousAPI.kt | 28 ++++--- .../users/anonymous/RetrofitAnonymousAPI.kt | 39 +++++++-- 8 files changed, 158 insertions(+), 22 deletions(-) create mode 100644 modules/src/androidTest/java/app/lounge/AnonymousUserAPITest.kt create mode 100644 modules/src/main/java/app/lounge/extension/Extension.kt diff --git a/modules/build.gradle b/modules/build.gradle index 849973854..68e0af9c5 100644 --- a/modules/build.gradle +++ b/modules/build.gradle @@ -10,6 +10,7 @@ ext { gson_version = '2.9.0' kotlin_reflection = '1.8.10' retrofit_version = '2.9.0' + retrofit_interceptor_version = '5.0.0-alpha.2' } android { @@ -49,6 +50,7 @@ dependencies { implementation("com.squareup.retrofit2:retrofit:$retrofit_version") implementation("com.squareup.retrofit2:converter-gson:$retrofit_version") implementation("com.squareup.retrofit2:converter-scalars:$retrofit_version") + implementation("com.squareup.okhttp3:logging-interceptor:$retrofit_interceptor_version") // endregion testImplementation 'junit:junit:4.13.2' diff --git a/modules/src/androidTest/java/app/lounge/AnonymousUserAPITest.kt b/modules/src/androidTest/java/app/lounge/AnonymousUserAPITest.kt new file mode 100644 index 000000000..916c6fce4 --- /dev/null +++ b/modules/src/androidTest/java/app/lounge/AnonymousUserAPITest.kt @@ -0,0 +1,79 @@ +package app.lounge + +import app.lounge.users.anonymous.AnonymousAPI +import app.lounge.users.anonymous.AnonymousAuthDataRequestBody +import org.junit.Assert +import org.junit.Test +import java.util.Properties + +class AnonymousUserAPITest { + + private val testAnonymousAPI = AnonymousAPI.create( + baseURL = AnonymousAPI.tokenBaseURL + ) + + private val userAgent: String = "{\"package\":\"foundation.e.apps.debug\",\"version\":\"2.5.5.debug\",\"device\":\"coral\",\"api\":32,\"os_version\":\"1.11-s-20230511288805-dev-coral\",\"build_id\":\"319e25cd.20230630224839\"}" + + private val systemProperties = Properties().apply { + setProperty("UserReadableName", "coral-default") + setProperty("Build.HARDWARE", "coral") + setProperty("Build.RADIO", "g8150-00123-220402-B-8399852") + setProperty("Build.FINGERPRINT","google/coral/coral:12/SQ3A.220705.003.A1/8672226:user/release-keys") + setProperty("Build.BRAND", "google") + setProperty("Build.DEVICE", "coral") + setProperty("Build.VERSION.SDK_INT", "32") + setProperty("Build.VERSION.RELEASE", "12") + setProperty("Build.MODEL", "Pixel 4 XL") + setProperty("Build.MANUFACTURER", "Google") + setProperty("Build.PRODUCT", "coral") + setProperty("Build.ID", "SQ3A.220705.004") + setProperty("Build.BOOTLOADER", "c2f2-0.4-8351033") + setProperty("TouchScreen", "3") + setProperty("Keyboard", "1") + setProperty("Navigation", "1") + setProperty("ScreenLayout", "2") + setProperty("HasHardKeyboard", "false") + setProperty("HasFiveWayNavigation", "false") + setProperty("Screen.Density", "560") + setProperty("Screen.Width", "1440") + setProperty("Screen.Height", "2984") + setProperty("Platforms", "arm64-v8a,armeabi-v7a,armeabi") + setProperty("Features", "android.hardware.sensor.proximity,com.verizon.hardware.telephony.lte,com.verizon.hardware.telephony.ehrpd,android.hardware.sensor.accelerometer,android.software.controls,android.hardware.faketouch,com.google.android.feature.D2D_CABLE_MIGRATION_FEATURE,android.hardware.telephony.euicc,android.hardware.reboot_escrow,android.hardware.usb.accessory,android.hardware.telephony.cdma,android.software.backup,android.hardware.touchscreen,android.hardware.touchscreen.multitouch,android.software.print,org.lineageos.weather,android.software.activities_on_secondary_displays,android.hardware.wifi.rtt,com.google.android.feature.PIXEL_2017_EXPERIENCE,android.software.voice_recognizers,android.software.picture_in_picture,android.hardware.sensor.gyroscope,android.hardware.audio.low_latency,android.software.vulkan.deqp.level,android.software.cant_save_state,com.google.android.feature.PIXEL_2018_EXPERIENCE,android.hardware.security.model.compatible,com.google.android.feature.PIXEL_2019_EXPERIENCE,android.hardware.opengles.aep,org.lineageos.livedisplay,org.lineageos.profiles,android.hardware.bluetooth,android.hardware.camera.autofocus,android.hardware.telephony.gsm,android.hardware.telephony.ims,android.software.incremental_delivery,android.software.sip.voip,android.hardware.se.omapi.ese,android.software.opengles.deqp.level,android.hardware.usb.host,android.hardware.audio.output,android.software.verified_boot,android.hardware.camera.flash,android.hardware.camera.front,android.hardware.sensor.hifi_sensors,com.google.android.apps.photos.PIXEL_2019_PRELOAD,android.hardware.se.omapi.uicc,android.hardware.strongbox_keystore,android.hardware.screen.portrait,android.hardware.nfc,com.google.android.feature.TURBO_PRELOAD,com.nxp.mifare,android.hardware.sensor.stepdetector,android.software.home_screen,android.hardware.context_hub,android.hardware.microphone,android.software.autofill,org.lineageos.hardware,org.lineageos.globalactions,android.software.securely_removes_users,com.google.android.feature.PIXEL_EXPERIENCE,android.hardware.bluetooth_le,android.hardware.sensor.compass,com.google.android.feature.GOOGLE_FI_BUNDLED,android.hardware.touchscreen.multitouch.jazzhand,android.hardware.sensor.barometer,android.software.app_widgets,android.hardware.telephony.carrierlock,android.software.input_methods,android.hardware.sensor.light,android.hardware.vulkan.version,android.software.companion_device_setup,android.software.device_admin,com.google.android.feature.WELLBEING,android.hardware.wifi.passpoint,android.hardware.camera,org.lineageos.trust,android.hardware.device_unique_attestation,android.hardware.screen.landscape,android.software.device_id_attestation,com.google.android.feature.AER_OPTIMIZED,android.hardware.ram.normal,org.lineageos.android,com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE,android.software.managed_users,android.software.webview,android.hardware.sensor.stepcounter,android.hardware.camera.capability.manual_post_processing,android.hardware.camera.any,android.hardware.camera.capability.raw,android.hardware.vulkan.compute,android.software.connectionservice,android.hardware.touchscreen.multitouch.distinct,android.hardware.location.network,android.software.cts,android.software.sip,android.hardware.camera.capability.manual_sensor,android.software.app_enumeration,android.hardware.camera.level.full,android.hardware.identity_credential,android.hardware.wifi.direct,android.software.live_wallpaper,android.software.ipsec_tunnels,org.lineageos.settings,android.hardware.sensor.assist,android.hardware.audio.pro,android.hardware.nfc.hcef,android.hardware.nfc.uicc,android.hardware.location.gps,android.sofware.nfc.beam,android.software.midi,android.hardware.nfc.any,android.hardware.nfc.ese,android.hardware.nfc.hce,android.hardware.wifi,android.hardware.location,android.hardware.vulkan.level,android.hardware.wifi.aware,android.software.secure_lock_screen,android.hardware.biometrics.face,android.hardware.telephony,android.software.file_based_encryption") + setProperty("Locales", "af,af_ZA,am,am_ET,ar,ar_EG,ar_XB,as,ast_ES,az,be,bg,bg_BG,bn,bs,ca,ca_ES,cs,cs_CZ,cy,da,da_DK,de,de_DE,el,el_GR,en,en_AU,en_CA,en_GB,en_IN,en_US,en_XA,en_XC,es,es_419,es_ES,es_US,et,eu,fa,fa_IR,fi,fi_FI,fil,fil_PH,fr,fr_CA,fr_FR,gd,gl,gu,hi,hi_IN,hr,hr_HR,hu,hu_HU,hy,in,in_ID,is,it,it_IT,iw,iw_IL,ja,ja_JP,ka,kk,km,kn,ko,ko_KR,ky,lo,lt,lt_LT,lv,lv_LV,mk,ml,mn,mr,ms,ms_MY,my,nb,nb_NO,ne,nl,nl_NL,or,pa,pl,pl_PL,pt,pt_BR,pt_PT,ro,ro_RO,ru,ru_RU,si,sk,sk_SK,sl,sl_SI,sq,sr,sr_Latn,sr_RS,sv,sv_SE,sw,sw_TZ,ta,te,th,th_TH,tr,tr_TR,uk,uk_UA,ur,uz,vi,vi_VN,zh_CN,zh_HK,zh_TW,zu,zu_ZA") + setProperty("SharedLibraries", "android.test.base,android.test.mock,com.vzw.apnlib,android.hidl.manager-V1.0-java,qti-telephony-hidl-wrapper,libfastcvopt.so,google-ril,qti-telephony-utils,com.android.omadm.radioconfig,libcdsprpc.so,android.hidl.base-V1.0-java,com.qualcomm.qmapbridge,libairbrush-pixel.so,com.google.android.camera.experimental2019,libOpenCL-pixel.so,libadsprpc.so,com.android.location.provider,android.net.ipsec.ike,com.android.future.usb.accessory,libsdsprpc.so,android.ext.shared,javax.obex,izat.xt.srv,com.google.android.gms,lib_aion_buffer.so,com.qualcomm.uimremoteclientlibrary,libqdMetaData.so,com.qualcomm.uimremoteserverlibrary,com.qualcomm.qcrilhook,android.test.runner,org.apache.http.legacy,com.google.android.camera.extensions,com.google.android.hardwareinfo,com.android.cts.ctsshim.shared_library,com.android.nfc_extras,com.android.media.remotedisplay,com.android.mediadrm.signer,com.qualcomm.qti.imscmservice-V2.0-java,qti-telephony-hidl-wrapper-prd,com.qualcomm.qti.imscmservice-V2.1-java,com.qualcomm.qti.imscmservice-V2.2-java") + setProperty("GL.Version", "196610") + setProperty("GL.Extensions", ",GL_AMD_compressed_ATC_texture,GL_AMD_performance_monitor,GL_ANDROID_extension_pack_es31a,GL_APPLE_texture_2D_limited_npot,GL_ARB_vertex_buffer_object,GL_ARM_shader_framebuffer_fetch_depth_stencil,GL_EXT_EGL_image_array,GL_EXT_EGL_image_external_wrap_modes,GL_EXT_EGL_image_storage,GL_EXT_YUV_target,GL_EXT_blend_func_extended,GL_EXT_blit_framebuffer_params,GL_EXT_buffer_storage,GL_EXT_clip_control,GL_EXT_clip_cull_distance,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_copy_image,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers_indexed,GL_EXT_external_buffer,GL_EXT_fragment_invocation_density,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_read_format_bgra,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_cube_map_array,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_format_sRGB_override,GL_EXT_texture_norm16,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_type_2_10_10_10_REV,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_debug,GL_KHR_no_error,GL_KHR_robust_buffer_access_behavior,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_NV_shader_noperspective_interpolation,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_EGL_sync,GL_OES_blend_equation_separate,GL_OES_blend_func_separate,GL_OES_blend_subtract,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_depth24,GL_OES_depth_texture,GL_OES_depth_texture_cube_map,GL_OES_draw_texture,GL_OES_element_index_uint,GL_OES_framebuffer_object,GL_OES_get_program_binary,GL_OES_matrix_palette,GL_OES_packed_depth_stencil,GL_OES_point_size_array,GL_OES_point_sprite,GL_OES_read_format,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_multisample_interpolation,GL_OES_standard_derivatives,GL_OES_stencil_wrap,GL_OES_surfaceless_context,GL_OES_texture_3D,GL_OES_texture_compression_astc,GL_OES_texture_cube_map,GL_OES_texture_env_crossbar,GL_OES_texture_float,GL_OES_texture_float_linear,GL_OES_texture_half_float,GL_OES_texture_half_float_linear,GL_OES_texture_mirrored_repeat,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_texture_view,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OVR_multiview,GL_OVR_multiview2,GL_OVR_multiview_multisampled_render_to_texture,GL_QCOM_YUV_texture_gather,GL_QCOM_alpha_test,GL_QCOM_extended_get,GL_QCOM_motion_estimation,GL_QCOM_shader_framebuffer_fetch_noncoherent,GL_QCOM_shader_framebuffer_fetch_rate,GL_QCOM_texture_foveated,GL_QCOM_texture_foveated_subsampled_layout,GL_QCOM_tiled_rendering,GL_QCOM_validate_shader_binary") + setProperty("Client", "android-google") + setProperty("GSF.version", "223616055") + setProperty("Vending.version", "82151710") + setProperty("Vending.versionString", "21.5.17-21 [0] [PR] 326734551") + setProperty("Roaming", "mobile-notroaming") + setProperty("TimeZone", "UTC-10") + setProperty("CellOperator", "310") + setProperty("SimOperator", "38") + } + + + private val requestBodyData = AnonymousAuthDataRequestBody( + properties = systemProperties, + userAgent = userAgent + ) + + @Test + fun testAPI() { + testAnonymousAPI.requestAuthData( + anonymousAuthDataRequestBody = requestBodyData, + success = { + print(it) + Assert.assertEquals("Hello", it) + }, + failure = { + print(it) + Assert.assertEquals("Hello", it.toString()) + } + ) + + Thread.sleep(30000) + } + +} \ No newline at end of file diff --git a/modules/src/main/AndroidManifest.xml b/modules/src/main/AndroidManifest.xml index a5918e68a..2a7393a69 100644 --- a/modules/src/main/AndroidManifest.xml +++ b/modules/src/main/AndroidManifest.xml @@ -1,4 +1,6 @@ + + \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/extension/Extension.kt b/modules/src/main/java/app/lounge/extension/Extension.kt new file mode 100644 index 000000000..133934a78 --- /dev/null +++ b/modules/src/main/java/app/lounge/extension/Extension.kt @@ -0,0 +1,7 @@ +package app.lounge.extension + +import com.google.gson.Gson +import java.util.Properties + +/** Convert Properties parameter to byte array*/ +fun Properties.toByteArray() = Gson().toJson(this).toByteArray() \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt b/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt index c4b89b6dc..fb6290cdf 100644 --- a/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt +++ b/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt @@ -1,7 +1,9 @@ package app.lounge.networking import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory import java.util.concurrent.TimeUnit /** @@ -19,11 +21,20 @@ internal fun Retrofit.Builder.appLounge( callTimeoutInSeconds: Long, ) : Retrofit { return this.baseUrl(baseURL) + .addConverterFactory(GsonConverterFactory.create()) .client( OkHttpClient.Builder() + .addNetworkInterceptor(interceptor) .callTimeout(callTimeoutInSeconds, TimeUnit.SECONDS) .followRedirects(shouldFollowRedirects) .build() ) .build() +} + +private val interceptor = run { + val httpLoggingInterceptor = HttpLoggingInterceptor() + httpLoggingInterceptor.apply { + httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY + } } \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt b/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt index 8c888f012..9ca6f9067 100644 --- a/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt +++ b/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt @@ -1,5 +1,7 @@ package app.lounge.users.anonymous +import app.lounge.networking.FetchError + /** * Implement API related to Anonymous login flow only. * 1. Login api for Anonymous users. @@ -23,11 +25,13 @@ interface Anonymous { } // pass input from this function - fun login( - success : () -> Unit, - failure : () -> Unit + fun requestAuthData( + anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody, + success : (LoginResponse) -> Unit, + failure : (FetchError) -> Unit ) { - api.performLogin( + api.requestAuthData( + anonymousAuthDataRequestBody = anonymousAuthDataRequestBody, success = success, failure = failure ) diff --git a/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt b/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt index 5ef1a8ae1..9da4d4368 100644 --- a/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt +++ b/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt @@ -1,12 +1,15 @@ package app.lounge.users.anonymous import app.lounge.BuildConfig +import app.lounge.networking.FetchError +import com.google.gson.Gson +import java.util.Properties interface AnonymousAPI { companion object { - private const val tokenBaseURL: String = "https://eu.gtoken.ecloud.global" - private const val loginBaseURL: String = "GooglePlayApi.URL_SYNC" + const val tokenBaseURL: String = "https://eu.gtoken.ecloud.global" + const val loginBaseURL: String = "GooglePlayApi.URL_SYNC" fun create(baseURL: String = tokenBaseURL) : AnonymousAPI { return RetrofitAnonymousAPI( @@ -17,17 +20,22 @@ interface AnonymousAPI { } } - fun performLogin( - success : () -> Unit, - failure : () -> Unit + fun requestAuthData( + anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody, + success : (LoginResponse) -> Unit, + failure : (FetchError) -> Unit ) object Header { - val authData: Map get() { - return mapOf( - Pair("User-Agent", BuildConfig.BUILD_TYPE), // CommonUtilsFunctions.getAppBuildInfo() - ) + val authData: (() -> String) -> Map = { + mapOf(Pair("User-Agent", it.invoke())) } } -} \ No newline at end of file +} + +/** AnonymousAuthDataRequestBody */ +data class AnonymousAuthDataRequestBody( + val properties: Properties, + val userAgent: String +) diff --git a/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt b/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt index 8fe81ae67..8b2d3f608 100644 --- a/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt +++ b/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt @@ -1,13 +1,18 @@ package app.lounge.users.anonymous +import app.lounge.extension.toByteArray +import app.lounge.networking.FetchError import app.lounge.networking.RetrofitFetching import app.lounge.networking.appLounge +import app.lounge.networking.fetch +import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody import retrofit2.Call import retrofit2.Retrofit import retrofit2.http.Body import retrofit2.http.HeaderMap import retrofit2.http.POST +import retrofit2.http.Url internal class RetrofitAnonymousAPI( baseURL: String, @@ -25,16 +30,34 @@ internal class RetrofitAnonymousAPI( @POST fun authDataRequest( - @HeaderMap headers: Map = AnonymousAPI.Header.authData, - @Body requestBody: RequestBody? - ): Call + @Url url: String = "https://eu.gtoken.ecloud.global", + @HeaderMap headers: Map, + @Body requestBody: RequestBody + ): Call } - override fun performLogin(success: () -> Unit, failure: () -> Unit) { - /*fetch( - endpoint = anonymousUserEndPoint.authDataRequest(requestBody = null), - processing = , - )*/ + override fun requestAuthData( + anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody, + success: (LoginResponse) -> Unit, + failure: (FetchError) -> Unit + ) { + val requestBody = RequestBody.create( + "application/json".toMediaTypeOrNull(), + anonymousAuthDataRequestBody.properties.toByteArray() + ) + + fetch( + endpoint = anonymousUserEndPoint.authDataRequest( + requestBody = requestBody, + headers = AnonymousAPI.Header.authData { + anonymousAuthDataRequestBody.userAgent + } + ), + success = success, + failure = failure + ) } } + +typealias LoginResponse = String -- GitLab From 8357ebe7fe25aa03da4030dee2d4820f3c6530cb Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Wed, 5 Jul 2023 23:48:55 +0530 Subject: [PATCH 05/11] AnonymousUserAPITest is handled in Anonymous Login Flow MR --- .../java/app/lounge/AnonymousUserAPITest.kt | 79 ------------------- 1 file changed, 79 deletions(-) delete mode 100644 modules/src/androidTest/java/app/lounge/AnonymousUserAPITest.kt diff --git a/modules/src/androidTest/java/app/lounge/AnonymousUserAPITest.kt b/modules/src/androidTest/java/app/lounge/AnonymousUserAPITest.kt deleted file mode 100644 index 916c6fce4..000000000 --- a/modules/src/androidTest/java/app/lounge/AnonymousUserAPITest.kt +++ /dev/null @@ -1,79 +0,0 @@ -package app.lounge - -import app.lounge.users.anonymous.AnonymousAPI -import app.lounge.users.anonymous.AnonymousAuthDataRequestBody -import org.junit.Assert -import org.junit.Test -import java.util.Properties - -class AnonymousUserAPITest { - - private val testAnonymousAPI = AnonymousAPI.create( - baseURL = AnonymousAPI.tokenBaseURL - ) - - private val userAgent: String = "{\"package\":\"foundation.e.apps.debug\",\"version\":\"2.5.5.debug\",\"device\":\"coral\",\"api\":32,\"os_version\":\"1.11-s-20230511288805-dev-coral\",\"build_id\":\"319e25cd.20230630224839\"}" - - private val systemProperties = Properties().apply { - setProperty("UserReadableName", "coral-default") - setProperty("Build.HARDWARE", "coral") - setProperty("Build.RADIO", "g8150-00123-220402-B-8399852") - setProperty("Build.FINGERPRINT","google/coral/coral:12/SQ3A.220705.003.A1/8672226:user/release-keys") - setProperty("Build.BRAND", "google") - setProperty("Build.DEVICE", "coral") - setProperty("Build.VERSION.SDK_INT", "32") - setProperty("Build.VERSION.RELEASE", "12") - setProperty("Build.MODEL", "Pixel 4 XL") - setProperty("Build.MANUFACTURER", "Google") - setProperty("Build.PRODUCT", "coral") - setProperty("Build.ID", "SQ3A.220705.004") - setProperty("Build.BOOTLOADER", "c2f2-0.4-8351033") - setProperty("TouchScreen", "3") - setProperty("Keyboard", "1") - setProperty("Navigation", "1") - setProperty("ScreenLayout", "2") - setProperty("HasHardKeyboard", "false") - setProperty("HasFiveWayNavigation", "false") - setProperty("Screen.Density", "560") - setProperty("Screen.Width", "1440") - setProperty("Screen.Height", "2984") - setProperty("Platforms", "arm64-v8a,armeabi-v7a,armeabi") - setProperty("Features", "android.hardware.sensor.proximity,com.verizon.hardware.telephony.lte,com.verizon.hardware.telephony.ehrpd,android.hardware.sensor.accelerometer,android.software.controls,android.hardware.faketouch,com.google.android.feature.D2D_CABLE_MIGRATION_FEATURE,android.hardware.telephony.euicc,android.hardware.reboot_escrow,android.hardware.usb.accessory,android.hardware.telephony.cdma,android.software.backup,android.hardware.touchscreen,android.hardware.touchscreen.multitouch,android.software.print,org.lineageos.weather,android.software.activities_on_secondary_displays,android.hardware.wifi.rtt,com.google.android.feature.PIXEL_2017_EXPERIENCE,android.software.voice_recognizers,android.software.picture_in_picture,android.hardware.sensor.gyroscope,android.hardware.audio.low_latency,android.software.vulkan.deqp.level,android.software.cant_save_state,com.google.android.feature.PIXEL_2018_EXPERIENCE,android.hardware.security.model.compatible,com.google.android.feature.PIXEL_2019_EXPERIENCE,android.hardware.opengles.aep,org.lineageos.livedisplay,org.lineageos.profiles,android.hardware.bluetooth,android.hardware.camera.autofocus,android.hardware.telephony.gsm,android.hardware.telephony.ims,android.software.incremental_delivery,android.software.sip.voip,android.hardware.se.omapi.ese,android.software.opengles.deqp.level,android.hardware.usb.host,android.hardware.audio.output,android.software.verified_boot,android.hardware.camera.flash,android.hardware.camera.front,android.hardware.sensor.hifi_sensors,com.google.android.apps.photos.PIXEL_2019_PRELOAD,android.hardware.se.omapi.uicc,android.hardware.strongbox_keystore,android.hardware.screen.portrait,android.hardware.nfc,com.google.android.feature.TURBO_PRELOAD,com.nxp.mifare,android.hardware.sensor.stepdetector,android.software.home_screen,android.hardware.context_hub,android.hardware.microphone,android.software.autofill,org.lineageos.hardware,org.lineageos.globalactions,android.software.securely_removes_users,com.google.android.feature.PIXEL_EXPERIENCE,android.hardware.bluetooth_le,android.hardware.sensor.compass,com.google.android.feature.GOOGLE_FI_BUNDLED,android.hardware.touchscreen.multitouch.jazzhand,android.hardware.sensor.barometer,android.software.app_widgets,android.hardware.telephony.carrierlock,android.software.input_methods,android.hardware.sensor.light,android.hardware.vulkan.version,android.software.companion_device_setup,android.software.device_admin,com.google.android.feature.WELLBEING,android.hardware.wifi.passpoint,android.hardware.camera,org.lineageos.trust,android.hardware.device_unique_attestation,android.hardware.screen.landscape,android.software.device_id_attestation,com.google.android.feature.AER_OPTIMIZED,android.hardware.ram.normal,org.lineageos.android,com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE,android.software.managed_users,android.software.webview,android.hardware.sensor.stepcounter,android.hardware.camera.capability.manual_post_processing,android.hardware.camera.any,android.hardware.camera.capability.raw,android.hardware.vulkan.compute,android.software.connectionservice,android.hardware.touchscreen.multitouch.distinct,android.hardware.location.network,android.software.cts,android.software.sip,android.hardware.camera.capability.manual_sensor,android.software.app_enumeration,android.hardware.camera.level.full,android.hardware.identity_credential,android.hardware.wifi.direct,android.software.live_wallpaper,android.software.ipsec_tunnels,org.lineageos.settings,android.hardware.sensor.assist,android.hardware.audio.pro,android.hardware.nfc.hcef,android.hardware.nfc.uicc,android.hardware.location.gps,android.sofware.nfc.beam,android.software.midi,android.hardware.nfc.any,android.hardware.nfc.ese,android.hardware.nfc.hce,android.hardware.wifi,android.hardware.location,android.hardware.vulkan.level,android.hardware.wifi.aware,android.software.secure_lock_screen,android.hardware.biometrics.face,android.hardware.telephony,android.software.file_based_encryption") - setProperty("Locales", "af,af_ZA,am,am_ET,ar,ar_EG,ar_XB,as,ast_ES,az,be,bg,bg_BG,bn,bs,ca,ca_ES,cs,cs_CZ,cy,da,da_DK,de,de_DE,el,el_GR,en,en_AU,en_CA,en_GB,en_IN,en_US,en_XA,en_XC,es,es_419,es_ES,es_US,et,eu,fa,fa_IR,fi,fi_FI,fil,fil_PH,fr,fr_CA,fr_FR,gd,gl,gu,hi,hi_IN,hr,hr_HR,hu,hu_HU,hy,in,in_ID,is,it,it_IT,iw,iw_IL,ja,ja_JP,ka,kk,km,kn,ko,ko_KR,ky,lo,lt,lt_LT,lv,lv_LV,mk,ml,mn,mr,ms,ms_MY,my,nb,nb_NO,ne,nl,nl_NL,or,pa,pl,pl_PL,pt,pt_BR,pt_PT,ro,ro_RO,ru,ru_RU,si,sk,sk_SK,sl,sl_SI,sq,sr,sr_Latn,sr_RS,sv,sv_SE,sw,sw_TZ,ta,te,th,th_TH,tr,tr_TR,uk,uk_UA,ur,uz,vi,vi_VN,zh_CN,zh_HK,zh_TW,zu,zu_ZA") - setProperty("SharedLibraries", "android.test.base,android.test.mock,com.vzw.apnlib,android.hidl.manager-V1.0-java,qti-telephony-hidl-wrapper,libfastcvopt.so,google-ril,qti-telephony-utils,com.android.omadm.radioconfig,libcdsprpc.so,android.hidl.base-V1.0-java,com.qualcomm.qmapbridge,libairbrush-pixel.so,com.google.android.camera.experimental2019,libOpenCL-pixel.so,libadsprpc.so,com.android.location.provider,android.net.ipsec.ike,com.android.future.usb.accessory,libsdsprpc.so,android.ext.shared,javax.obex,izat.xt.srv,com.google.android.gms,lib_aion_buffer.so,com.qualcomm.uimremoteclientlibrary,libqdMetaData.so,com.qualcomm.uimremoteserverlibrary,com.qualcomm.qcrilhook,android.test.runner,org.apache.http.legacy,com.google.android.camera.extensions,com.google.android.hardwareinfo,com.android.cts.ctsshim.shared_library,com.android.nfc_extras,com.android.media.remotedisplay,com.android.mediadrm.signer,com.qualcomm.qti.imscmservice-V2.0-java,qti-telephony-hidl-wrapper-prd,com.qualcomm.qti.imscmservice-V2.1-java,com.qualcomm.qti.imscmservice-V2.2-java") - setProperty("GL.Version", "196610") - setProperty("GL.Extensions", ",GL_AMD_compressed_ATC_texture,GL_AMD_performance_monitor,GL_ANDROID_extension_pack_es31a,GL_APPLE_texture_2D_limited_npot,GL_ARB_vertex_buffer_object,GL_ARM_shader_framebuffer_fetch_depth_stencil,GL_EXT_EGL_image_array,GL_EXT_EGL_image_external_wrap_modes,GL_EXT_EGL_image_storage,GL_EXT_YUV_target,GL_EXT_blend_func_extended,GL_EXT_blit_framebuffer_params,GL_EXT_buffer_storage,GL_EXT_clip_control,GL_EXT_clip_cull_distance,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_copy_image,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers_indexed,GL_EXT_external_buffer,GL_EXT_fragment_invocation_density,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_read_format_bgra,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_cube_map_array,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_format_sRGB_override,GL_EXT_texture_norm16,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_type_2_10_10_10_REV,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_debug,GL_KHR_no_error,GL_KHR_robust_buffer_access_behavior,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_NV_shader_noperspective_interpolation,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_EGL_sync,GL_OES_blend_equation_separate,GL_OES_blend_func_separate,GL_OES_blend_subtract,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_depth24,GL_OES_depth_texture,GL_OES_depth_texture_cube_map,GL_OES_draw_texture,GL_OES_element_index_uint,GL_OES_framebuffer_object,GL_OES_get_program_binary,GL_OES_matrix_palette,GL_OES_packed_depth_stencil,GL_OES_point_size_array,GL_OES_point_sprite,GL_OES_read_format,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_multisample_interpolation,GL_OES_standard_derivatives,GL_OES_stencil_wrap,GL_OES_surfaceless_context,GL_OES_texture_3D,GL_OES_texture_compression_astc,GL_OES_texture_cube_map,GL_OES_texture_env_crossbar,GL_OES_texture_float,GL_OES_texture_float_linear,GL_OES_texture_half_float,GL_OES_texture_half_float_linear,GL_OES_texture_mirrored_repeat,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_texture_view,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OVR_multiview,GL_OVR_multiview2,GL_OVR_multiview_multisampled_render_to_texture,GL_QCOM_YUV_texture_gather,GL_QCOM_alpha_test,GL_QCOM_extended_get,GL_QCOM_motion_estimation,GL_QCOM_shader_framebuffer_fetch_noncoherent,GL_QCOM_shader_framebuffer_fetch_rate,GL_QCOM_texture_foveated,GL_QCOM_texture_foveated_subsampled_layout,GL_QCOM_tiled_rendering,GL_QCOM_validate_shader_binary") - setProperty("Client", "android-google") - setProperty("GSF.version", "223616055") - setProperty("Vending.version", "82151710") - setProperty("Vending.versionString", "21.5.17-21 [0] [PR] 326734551") - setProperty("Roaming", "mobile-notroaming") - setProperty("TimeZone", "UTC-10") - setProperty("CellOperator", "310") - setProperty("SimOperator", "38") - } - - - private val requestBodyData = AnonymousAuthDataRequestBody( - properties = systemProperties, - userAgent = userAgent - ) - - @Test - fun testAPI() { - testAnonymousAPI.requestAuthData( - anonymousAuthDataRequestBody = requestBodyData, - success = { - print(it) - Assert.assertEquals("Hello", it) - }, - failure = { - print(it) - Assert.assertEquals("Hello", it.toString()) - } - ) - - Thread.sleep(30000) - } - -} \ No newline at end of file -- GitLab From 8c7bd53fb73456cf0531496ba18747bbe5da5b3e Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Thu, 6 Jul 2023 00:04:04 +0530 Subject: [PATCH 06/11] Update as per code review comment --- .../java/app/lounge/extension/Extension.kt | 5 ++++- ...{RetrofitFetching.kt => NetworkFetching.kt} | 18 +++++++++--------- .../users/anonymous/RetrofitAnonymousAPI.kt | 6 +++--- 3 files changed, 16 insertions(+), 13 deletions(-) rename modules/src/main/java/app/lounge/networking/{RetrofitFetching.kt => NetworkFetching.kt} (94%) diff --git a/modules/src/main/java/app/lounge/extension/Extension.kt b/modules/src/main/java/app/lounge/extension/Extension.kt index 133934a78..17a68e188 100644 --- a/modules/src/main/java/app/lounge/extension/Extension.kt +++ b/modules/src/main/java/app/lounge/extension/Extension.kt @@ -3,5 +3,8 @@ package app.lounge.extension import com.google.gson.Gson import java.util.Properties -/** Convert Properties parameter to byte array*/ +/** + * Convert Properties parameter to byte array + * @return Byte Array of Properties + * */ fun Properties.toByteArray() = Gson().toJson(this).toByteArray() \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/networking/RetrofitFetching.kt b/modules/src/main/java/app/lounge/networking/NetworkFetching.kt similarity index 94% rename from modules/src/main/java/app/lounge/networking/RetrofitFetching.kt rename to modules/src/main/java/app/lounge/networking/NetworkFetching.kt index 6c38171a0..a8493d686 100644 --- a/modules/src/main/java/app/lounge/networking/RetrofitFetching.kt +++ b/modules/src/main/java/app/lounge/networking/NetworkFetching.kt @@ -8,7 +8,7 @@ import java.net.UnknownHostException //region Retrofit Asynchronous Networking -interface RetrofitFetching { +interface NetworkFetching { val executor: Executor get() = callEnqueue val checkNetwork: (() -> Boolean)? get() = null @@ -61,8 +61,8 @@ interface RetrofitFetching { * @param success Success callback with the response `R` * @param failure Failure callback with an error case from `AnyFetchError` subtypes */ -inline fun RetrofitFetching.fetch( - usingExecutor: RetrofitFetching.Executor = executor, +inline fun NetworkFetching.fetch( + usingExecutor: NetworkFetching.Executor = executor, endpoint: Call, noinline success: (R) -> Unit, noinline failure: (FetchError) -> Unit @@ -84,10 +84,10 @@ inline fun RetrofitFetching.fetch( * @param success Success callback with the response `R` * @param failure Failure callback with an error case from given error subtype `E` */ -fun RetrofitFetching.fetch( - usingExecutor: RetrofitFetching.Executor = executor, +fun NetworkFetching.fetch( + usingExecutor: NetworkFetching.Executor = executor, endpoint: Call, - resultProcessing: RetrofitFetching.ResultProcessing, + resultProcessing: NetworkFetching.ResultProcessing, success: (R) -> Unit, failure: (E) -> Unit ) { @@ -107,9 +107,9 @@ sealed class RetrofitResult { } private fun fetch( - usingExecutor: RetrofitFetching.Executor, + usingExecutor: NetworkFetching.Executor, endpoint: Call, - resultProcessing: RetrofitFetching.ResultProcessing, + resultProcessing: NetworkFetching.ResultProcessing, callback: (RetrofitResult) -> Unit, ) { usingExecutor.fetchAndCallback(endpoint, object : Callback { @@ -132,7 +132,7 @@ open class RetrofitResultProcessing( override val tryCastResponseBody: (Any?) -> R?, override val errorFromNetworkFailure: (AnyFetchError) -> E, hasNetwork: (() -> Boolean)? = null, -) : RetrofitFetching.ResultProcessing { +) : NetworkFetching.ResultProcessing { companion object { inline operator fun invoke( diff --git a/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt b/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt index 8b2d3f608..68d90b84c 100644 --- a/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt +++ b/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt @@ -2,7 +2,7 @@ package app.lounge.users.anonymous import app.lounge.extension.toByteArray import app.lounge.networking.FetchError -import app.lounge.networking.RetrofitFetching +import app.lounge.networking.NetworkFetching import app.lounge.networking.appLounge import app.lounge.networking.fetch import okhttp3.MediaType.Companion.toMediaTypeOrNull @@ -18,7 +18,7 @@ internal class RetrofitAnonymousAPI( baseURL: String, anonymousUserEndpointFollowsRedirects: Boolean, callTimeoutInSeconds: Long, -): AnonymousAPI, RetrofitFetching { +): AnonymousAPI, NetworkFetching { private val anonymousUserEndPoint: AnonymousUserEndPointEndpoint = Retrofit.Builder().appLounge( baseURL = baseURL, @@ -30,7 +30,7 @@ internal class RetrofitAnonymousAPI( @POST fun authDataRequest( - @Url url: String = "https://eu.gtoken.ecloud.global", + @Url url: String = AnonymousAPI.tokenBaseURL, @HeaderMap headers: Map, @Body requestBody: RequestBody ): Call -- GitLab From dc40dc7f09e4acb316f53ea358acf02649f0a468 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Sun, 16 Jul 2023 21:16:39 +0530 Subject: [PATCH 07/11] Implement network api using coroutine --- app/build.gradle | 2 + modules/build.gradle | 20 +- .../java/app/lounge/NetworkFetchingAPITest.kt | 149 +++++++++++++ .../main/java/app/lounge/di/NetworkModule.kt | 59 +++++ .../src/main/java/app/lounge/model/Model.kt | 24 +++ .../java/app/lounge/networking/FetchError.kt | 50 ----- .../app/lounge/networking/NetworkFetching.kt | 204 +----------------- .../networking/NetworkFetchingRetrofitImpl.kt | 88 ++++++++ .../app/lounge/networking/RetrofitConfig.kt | 40 ---- .../src/main/java/app/lounge/users/Google.kt | 8 - .../src/main/java/app/lounge/users/Session.kt | 11 - .../app/lounge/users/anonymous/Anonymous.kt | 39 ---- .../lounge/users/anonymous/AnonymousAPI.kt | 41 ---- .../users/anonymous/RetrofitAnonymousAPI.kt | 63 ------ 14 files changed, 349 insertions(+), 449 deletions(-) create mode 100644 modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt create mode 100644 modules/src/main/java/app/lounge/di/NetworkModule.kt create mode 100644 modules/src/main/java/app/lounge/model/Model.kt delete mode 100644 modules/src/main/java/app/lounge/networking/FetchError.kt create mode 100644 modules/src/main/java/app/lounge/networking/NetworkFetchingRetrofitImpl.kt delete mode 100644 modules/src/main/java/app/lounge/networking/RetrofitConfig.kt delete mode 100644 modules/src/main/java/app/lounge/users/Google.kt delete mode 100644 modules/src/main/java/app/lounge/users/Session.kt delete mode 100644 modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt delete mode 100644 modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt delete mode 100644 modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt diff --git a/app/build.gradle b/app/build.gradle index 1d0b1c0d7..f0e0d5e26 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -147,6 +147,8 @@ allOpen { dependencies { + implementation project(path: ':modules') + // TODO: Add splitinstall-lib to a repo https://gitlab.e.foundation/e/os/backlog/-/issues/628 api files('libs/splitinstall-lib.jar') diff --git a/modules/build.gradle b/modules/build.gradle index 4ef71300d..d36cf010a 100644 --- a/modules/build.gradle +++ b/modules/build.gradle @@ -1,6 +1,8 @@ plugins { id 'com.android.library' id 'org.jetbrains.kotlin.android' + id 'kotlin-kapt' + id("com.google.dagger.hilt.android") } ext { @@ -8,9 +10,14 @@ ext { android_target_sdk_version = 33 core_version = '1.10.1' gson_version = '2.9.0' - kotlin_reflection = '1.8.10' + kotlin_reflection = '1.8.20' retrofit_version = '2.9.0' retrofit_interceptor_version = '5.0.0-alpha.2' + kotlin_coroutines_core = '1.7.2' + google_play_api = '3.0.1' + protobuf_java = '3.19.3' + javax_version = '1' + dagger_hilt_version = '2.46.1' } android { @@ -45,13 +52,20 @@ dependencies { implementation "androidx.core:core-ktx:$core_version" implementation "com.google.code.gson:gson:$gson_version" implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_reflection" + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_core") - // region Retrofit implementation("com.squareup.retrofit2:retrofit:$retrofit_version") implementation("com.squareup.retrofit2:converter-gson:$retrofit_version") implementation("com.squareup.retrofit2:converter-scalars:$retrofit_version") implementation("com.squareup.okhttp3:logging-interceptor:$retrofit_interceptor_version") - // endregion + + implementation("foundation.e:gplayapi:$google_play_api") + implementation("com.google.protobuf:protobuf-java:$protobuf_java") + + implementation("javax.inject:javax.inject:$javax_version") + + implementation("com.google.dagger:hilt-android:$dagger_hilt_version") + kapt("com.google.dagger:hilt-android-compiler:$dagger_hilt_version") testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' diff --git a/modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt b/modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt new file mode 100644 index 000000000..d2b92e219 --- /dev/null +++ b/modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt @@ -0,0 +1,149 @@ +package app.lounge + +import app.lounge.model.AnonymousAuthDataRequestBody +import app.lounge.model.AnonymousAuthDataValidationRequestBody +import app.lounge.model.AuthDataResponse +import app.lounge.model.AuthDataValidationResponse +import app.lounge.networking.NetworkFetching +import app.lounge.networking.NetworkFetchingRetrofitAPI +import app.lounge.networking.NetworkFetchingRetrofitImpl +import kotlinx.coroutines.runBlocking +import okhttp3.OkHttpClient +import org.junit.Test +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.io.InterruptedIOException +import java.util.Properties +import java.util.concurrent.TimeUnit + +class NetworkFetchingAPITest { + + private val networkFetchingToken: NetworkFetching = NetworkFetchingRetrofitImpl( + Retrofit.Builder() + .baseUrl(NetworkFetchingRetrofitAPI.tokenBaseURL) + .addConverterFactory(GsonConverterFactory.create()) + .client( + OkHttpClient.Builder() + .callTimeout(10, TimeUnit.SECONDS) + .build() + ) + .build() + ) + + private val networkFetchingGoogle: NetworkFetching = NetworkFetchingRetrofitImpl( + Retrofit.Builder() + .baseUrl(NetworkFetchingRetrofitAPI.googlePlayBaseURL) + .addConverterFactory(GsonConverterFactory.create()) + .client( + OkHttpClient.Builder() + .callTimeout(10, TimeUnit.SECONDS) + .build() + ) + .build() + ) + + private val networkFetchingTimeoutGoogle: NetworkFetching = NetworkFetchingRetrofitImpl( + Retrofit.Builder() + .baseUrl(NetworkFetchingRetrofitAPI.googlePlayBaseURL) + .addConverterFactory(GsonConverterFactory.create()) + .client( + OkHttpClient.Builder() + .callTimeout(10, TimeUnit.MILLISECONDS) + .build() + ) + .build() + ) + + private val requestBodyData = AnonymousAuthDataRequestBody( + properties = testSystemProperties, + userAgent = testUserAgent + ) + + companion object { + var authData: AuthDataResponse? = null + } + + @Test + fun test1OnSuccessReturnsAuthData() = runBlocking { + authData = networkFetchingToken.requestAuthData( + anonymousAuthDataRequestBody = requestBodyData, + ) + assert(authData is AuthDataResponse) { "Assert!! Success must return data" } + } + + @Test + fun test2OnSuccessReturnsLoginData() = runBlocking { + var result: AuthDataValidationResponse? = null + authData?.let { authData -> + authData.dfeCookie = "null" + + result = networkFetchingGoogle.requestAuthDataValidation( + anonymousAuthDataValidationRequestBody = AnonymousAuthDataValidationRequestBody( + authDataResponse = authData + ) + ) + } + + assert(authData is AuthDataResponse) { "Assert!! AuthData must be present" } + assert(result is AuthDataValidationResponse) { "Assert!! `response` must have data" } + } + + @Test + fun test3OnTimeoutFailureReturnsError(): Unit = runBlocking { + var failure: Exception = Exception("No Error") + authData?.let { authData -> + authData.dfeCookie = "null" + + try { + networkFetchingTimeoutGoogle.requestAuthDataValidation( + anonymousAuthDataValidationRequestBody = AnonymousAuthDataValidationRequestBody( + authDataResponse = authData + ) + ) + } catch (e: InterruptedIOException) { failure = e } + } + assert(authData is AuthDataResponse) { "Assert!! AuthData must be present" } + assert(failure is InterruptedIOException) { "Assert!! Timeout Failure callback must call" } + } +} + +private const val testUserAgent: String = "{\"package\":\"foundation.e.apps.debug\",\"version\":\"2.5.5.debug\",\"device\":\"coral\",\"api\":32,\"os_version\":\"1.11-s-20230511288805-dev-coral\",\"build_id\":\"319e25cd.20230630224839\"}" + +private val testSystemProperties = Properties().apply { + setProperty("UserReadableName", "coral-default") + setProperty("Build.HARDWARE", "coral") + setProperty("Build.RADIO", "g8150-00123-220402-B-8399852") + setProperty("Build.FINGERPRINT","google/coral/coral:12/SQ3A.220705.003.A1/8672226:user/release-keys") + setProperty("Build.BRAND", "google") + setProperty("Build.DEVICE", "coral") + setProperty("Build.VERSION.SDK_INT", "32") + setProperty("Build.VERSION.RELEASE", "12") + setProperty("Build.MODEL", "Pixel 4 XL") + setProperty("Build.MANUFACTURER", "Google") + setProperty("Build.PRODUCT", "coral") + setProperty("Build.ID", "SQ3A.220705.004") + setProperty("Build.BOOTLOADER", "c2f2-0.4-8351033") + setProperty("TouchScreen", "3") + setProperty("Keyboard", "1") + setProperty("Navigation", "1") + setProperty("ScreenLayout", "2") + setProperty("HasHardKeyboard", "false") + setProperty("HasFiveWayNavigation", "false") + setProperty("Screen.Density", "560") + setProperty("Screen.Width", "1440") + setProperty("Screen.Height", "2984") + setProperty("Platforms", "arm64-v8a,armeabi-v7a,armeabi") + setProperty("Features", "android.hardware.sensor.proximity,com.verizon.hardware.telephony.lte,com.verizon.hardware.telephony.ehrpd,android.hardware.sensor.accelerometer,android.software.controls,android.hardware.faketouch,com.google.android.feature.D2D_CABLE_MIGRATION_FEATURE,android.hardware.telephony.euicc,android.hardware.reboot_escrow,android.hardware.usb.accessory,android.hardware.telephony.cdma,android.software.backup,android.hardware.touchscreen,android.hardware.touchscreen.multitouch,android.software.print,org.lineageos.weather,android.software.activities_on_secondary_displays,android.hardware.wifi.rtt,com.google.android.feature.PIXEL_2017_EXPERIENCE,android.software.voice_recognizers,android.software.picture_in_picture,android.hardware.sensor.gyroscope,android.hardware.audio.low_latency,android.software.vulkan.deqp.level,android.software.cant_save_state,com.google.android.feature.PIXEL_2018_EXPERIENCE,android.hardware.security.model.compatible,com.google.android.feature.PIXEL_2019_EXPERIENCE,android.hardware.opengles.aep,org.lineageos.livedisplay,org.lineageos.profiles,android.hardware.bluetooth,android.hardware.camera.autofocus,android.hardware.telephony.gsm,android.hardware.telephony.ims,android.software.incremental_delivery,android.software.sip.voip,android.hardware.se.omapi.ese,android.software.opengles.deqp.level,android.hardware.usb.host,android.hardware.audio.output,android.software.verified_boot,android.hardware.camera.flash,android.hardware.camera.front,android.hardware.sensor.hifi_sensors,com.google.android.apps.photos.PIXEL_2019_PRELOAD,android.hardware.se.omapi.uicc,android.hardware.strongbox_keystore,android.hardware.screen.portrait,android.hardware.nfc,com.google.android.feature.TURBO_PRELOAD,com.nxp.mifare,android.hardware.sensor.stepdetector,android.software.home_screen,android.hardware.context_hub,android.hardware.microphone,android.software.autofill,org.lineageos.hardware,org.lineageos.globalactions,android.software.securely_removes_users,com.google.android.feature.PIXEL_EXPERIENCE,android.hardware.bluetooth_le,android.hardware.sensor.compass,com.google.android.feature.GOOGLE_FI_BUNDLED,android.hardware.touchscreen.multitouch.jazzhand,android.hardware.sensor.barometer,android.software.app_widgets,android.hardware.telephony.carrierlock,android.software.input_methods,android.hardware.sensor.light,android.hardware.vulkan.version,android.software.companion_device_setup,android.software.device_admin,com.google.android.feature.WELLBEING,android.hardware.wifi.passpoint,android.hardware.camera,org.lineageos.trust,android.hardware.device_unique_attestation,android.hardware.screen.landscape,android.software.device_id_attestation,com.google.android.feature.AER_OPTIMIZED,android.hardware.ram.normal,org.lineageos.android,com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE,android.software.managed_users,android.software.webview,android.hardware.sensor.stepcounter,android.hardware.camera.capability.manual_post_processing,android.hardware.camera.any,android.hardware.camera.capability.raw,android.hardware.vulkan.compute,android.software.connectionservice,android.hardware.touchscreen.multitouch.distinct,android.hardware.location.network,android.software.cts,android.software.sip,android.hardware.camera.capability.manual_sensor,android.software.app_enumeration,android.hardware.camera.level.full,android.hardware.identity_credential,android.hardware.wifi.direct,android.software.live_wallpaper,android.software.ipsec_tunnels,org.lineageos.settings,android.hardware.sensor.assist,android.hardware.audio.pro,android.hardware.nfc.hcef,android.hardware.nfc.uicc,android.hardware.location.gps,android.sofware.nfc.beam,android.software.midi,android.hardware.nfc.any,android.hardware.nfc.ese,android.hardware.nfc.hce,android.hardware.wifi,android.hardware.location,android.hardware.vulkan.level,android.hardware.wifi.aware,android.software.secure_lock_screen,android.hardware.biometrics.face,android.hardware.telephony,android.software.file_based_encryption") + setProperty("Locales", "af,af_ZA,am,am_ET,ar,ar_EG,ar_XB,as,ast_ES,az,be,bg,bg_BG,bn,bs,ca,ca_ES,cs,cs_CZ,cy,da,da_DK,de,de_DE,el,el_GR,en,en_AU,en_CA,en_GB,en_IN,en_US,en_XA,en_XC,es,es_419,es_ES,es_US,et,eu,fa,fa_IR,fi,fi_FI,fil,fil_PH,fr,fr_CA,fr_FR,gd,gl,gu,hi,hi_IN,hr,hr_HR,hu,hu_HU,hy,in,in_ID,is,it,it_IT,iw,iw_IL,ja,ja_JP,ka,kk,km,kn,ko,ko_KR,ky,lo,lt,lt_LT,lv,lv_LV,mk,ml,mn,mr,ms,ms_MY,my,nb,nb_NO,ne,nl,nl_NL,or,pa,pl,pl_PL,pt,pt_BR,pt_PT,ro,ro_RO,ru,ru_RU,si,sk,sk_SK,sl,sl_SI,sq,sr,sr_Latn,sr_RS,sv,sv_SE,sw,sw_TZ,ta,te,th,th_TH,tr,tr_TR,uk,uk_UA,ur,uz,vi,vi_VN,zh_CN,zh_HK,zh_TW,zu,zu_ZA") + setProperty("SharedLibraries", "android.test.base,android.test.mock,com.vzw.apnlib,android.hidl.manager-V1.0-java,qti-telephony-hidl-wrapper,libfastcvopt.so,google-ril,qti-telephony-utils,com.android.omadm.radioconfig,libcdsprpc.so,android.hidl.base-V1.0-java,com.qualcomm.qmapbridge,libairbrush-pixel.so,com.google.android.camera.experimental2019,libOpenCL-pixel.so,libadsprpc.so,com.android.location.provider,android.net.ipsec.ike,com.android.future.usb.accessory,libsdsprpc.so,android.ext.shared,javax.obex,izat.xt.srv,com.google.android.gms,lib_aion_buffer.so,com.qualcomm.uimremoteclientlibrary,libqdMetaData.so,com.qualcomm.uimremoteserverlibrary,com.qualcomm.qcrilhook,android.test.runner,org.apache.http.legacy,com.google.android.camera.extensions,com.google.android.hardwareinfo,com.android.cts.ctsshim.shared_library,com.android.nfc_extras,com.android.media.remotedisplay,com.android.mediadrm.signer,com.qualcomm.qti.imscmservice-V2.0-java,qti-telephony-hidl-wrapper-prd,com.qualcomm.qti.imscmservice-V2.1-java,com.qualcomm.qti.imscmservice-V2.2-java") + setProperty("GL.Version", "196610") + setProperty("GL.Extensions", ",GL_AMD_compressed_ATC_texture,GL_AMD_performance_monitor,GL_ANDROID_extension_pack_es31a,GL_APPLE_texture_2D_limited_npot,GL_ARB_vertex_buffer_object,GL_ARM_shader_framebuffer_fetch_depth_stencil,GL_EXT_EGL_image_array,GL_EXT_EGL_image_external_wrap_modes,GL_EXT_EGL_image_storage,GL_EXT_YUV_target,GL_EXT_blend_func_extended,GL_EXT_blit_framebuffer_params,GL_EXT_buffer_storage,GL_EXT_clip_control,GL_EXT_clip_cull_distance,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_copy_image,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers_indexed,GL_EXT_external_buffer,GL_EXT_fragment_invocation_density,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_read_format_bgra,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_cube_map_array,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_format_sRGB_override,GL_EXT_texture_norm16,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_type_2_10_10_10_REV,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_debug,GL_KHR_no_error,GL_KHR_robust_buffer_access_behavior,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_NV_shader_noperspective_interpolation,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_EGL_sync,GL_OES_blend_equation_separate,GL_OES_blend_func_separate,GL_OES_blend_subtract,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_depth24,GL_OES_depth_texture,GL_OES_depth_texture_cube_map,GL_OES_draw_texture,GL_OES_element_index_uint,GL_OES_framebuffer_object,GL_OES_get_program_binary,GL_OES_matrix_palette,GL_OES_packed_depth_stencil,GL_OES_point_size_array,GL_OES_point_sprite,GL_OES_read_format,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_multisample_interpolation,GL_OES_standard_derivatives,GL_OES_stencil_wrap,GL_OES_surfaceless_context,GL_OES_texture_3D,GL_OES_texture_compression_astc,GL_OES_texture_cube_map,GL_OES_texture_env_crossbar,GL_OES_texture_float,GL_OES_texture_float_linear,GL_OES_texture_half_float,GL_OES_texture_half_float_linear,GL_OES_texture_mirrored_repeat,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_texture_view,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OVR_multiview,GL_OVR_multiview2,GL_OVR_multiview_multisampled_render_to_texture,GL_QCOM_YUV_texture_gather,GL_QCOM_alpha_test,GL_QCOM_extended_get,GL_QCOM_motion_estimation,GL_QCOM_shader_framebuffer_fetch_noncoherent,GL_QCOM_shader_framebuffer_fetch_rate,GL_QCOM_texture_foveated,GL_QCOM_texture_foveated_subsampled_layout,GL_QCOM_tiled_rendering,GL_QCOM_validate_shader_binary") + setProperty("Client", "android-google") + setProperty("GSF.version", "223616055") + setProperty("Vending.version", "82151710") + setProperty("Vending.versionString", "21.5.17-21 [0] [PR] 326734551") + setProperty("Roaming", "mobile-notroaming") + setProperty("TimeZone", "UTC-10") + setProperty("CellOperator", "310") + setProperty("SimOperator", "38") +} diff --git a/modules/src/main/java/app/lounge/di/NetworkModule.kt b/modules/src/main/java/app/lounge/di/NetworkModule.kt new file mode 100644 index 000000000..1763676d2 --- /dev/null +++ b/modules/src/main/java/app/lounge/di/NetworkModule.kt @@ -0,0 +1,59 @@ +package app.lounge.di + +import app.lounge.networking.NetworkFetchingRetrofitAPI +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.util.concurrent.TimeUnit +import javax.inject.Named +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +internal object NetworkModule { + + private const val HTTP_TIMEOUT = 10L + + @Provides + @Singleton + internal fun providesRetrofit( + okHttpClient: OkHttpClient, + baseUrl: String = NetworkFetchingRetrofitAPI.tokenBaseURL + ) : Retrofit { + return Retrofit.Builder() + .baseUrl(baseUrl) + .addConverterFactory(GsonConverterFactory.create()) + .client(okHttpClient) + .build() + } + + @Provides + @Singleton + @Named("privateOkHttpClient") + internal fun providesOkHttpClient( + httpLogger: HttpLoggingInterceptor + ): OkHttpClient { + return OkHttpClient.Builder() + .addNetworkInterceptor(httpLogger) + .callTimeout(HTTP_TIMEOUT, TimeUnit.SECONDS) + .build() + } + + @Provides + @Singleton + internal fun providesHttpLogger() : HttpLoggingInterceptor { + return run { + val httpLoggingInterceptor = HttpLoggingInterceptor() + httpLoggingInterceptor.apply { + httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY + } + } + } + +} \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/model/Model.kt b/modules/src/main/java/app/lounge/model/Model.kt new file mode 100644 index 000000000..ba4263416 --- /dev/null +++ b/modules/src/main/java/app/lounge/model/Model.kt @@ -0,0 +1,24 @@ +package app.lounge.model + +import com.aurora.gplayapi.data.models.AuthData +import com.aurora.gplayapi.data.providers.HeaderProvider +import okhttp3.ResponseBody +import java.util.Properties + + +/** AnonymousAuthDataRequestBody */ +data class AnonymousAuthDataRequestBody( + val properties: Properties, + val userAgent: String +) + +/** AnonymousLoginRequestBody */ +data class AnonymousAuthDataValidationRequestBody( + val authDataResponse: AuthDataResponse, +) { + val header = HeaderProvider.getDefaultHeaders(authDataResponse) +} + +typealias AuthDataResponse = AuthData + +typealias AuthDataValidationResponse = ResponseBody \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/networking/FetchError.kt b/modules/src/main/java/app/lounge/networking/FetchError.kt deleted file mode 100644 index 271b4ab3b..000000000 --- a/modules/src/main/java/app/lounge/networking/FetchError.kt +++ /dev/null @@ -1,50 +0,0 @@ -package app.lounge.networking - - -//region Generic Network Error Types - -sealed interface FetchError { - data class Network(val underlyingError: AnyFetchError) : FetchError -} - -/** Supertype for network error types. */ -sealed interface AnyFetchError { - - var description: String - - enum class BadRequest(override var description: String) : AnyFetchError { - Encode("FIXME: Error encoding request! $dumpKeyWord"), - Decode("FIXME: Error decoding request! $dumpKeyWord"), - } - - enum class NotFound(override var description: String) : AnyFetchError { - MissingData("No data found! $dumpKeyWord"), - MissingNetwork("No network! $dumpKeyWord") - } - - data class BadStatusCode (val statusCode: Int, val rawResponse: Any) : AnyFetchError { - override var description: String = - "Bad status code: $statusCode. Raw response: $rawResponse" - } - - /** - * Represents a vague error case typically caused by `UnknownHostException`. - * This error case is encountered if and only if network status cannot be determined - * while the `UnknownHostException` is received. - */ - data class Unknown( - override var description: String = "Unknown Error! $dumpKeyWord" - ) : AnyFetchError - - companion object { - const val dumpKeyWord: String = "dump:-" - - fun make(error: AnyFetchError, addingDump: String) : AnyFetchError { - error.description = error.description + addingDump - return error - } - } - -} - -//endregion diff --git a/modules/src/main/java/app/lounge/networking/NetworkFetching.kt b/modules/src/main/java/app/lounge/networking/NetworkFetching.kt index a8493d686..c544c7aac 100644 --- a/modules/src/main/java/app/lounge/networking/NetworkFetching.kt +++ b/modules/src/main/java/app/lounge/networking/NetworkFetching.kt @@ -1,201 +1,17 @@ package app.lounge.networking -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response -import java.lang.IllegalStateException -import java.net.UnknownHostException +import app.lounge.model.AnonymousAuthDataRequestBody +import app.lounge.model.AnonymousAuthDataValidationRequestBody +import app.lounge.model.AuthDataResponse +import app.lounge.model.AuthDataValidationResponse - -//region Retrofit Asynchronous Networking interface NetworkFetching { - val executor: Executor get() = callEnqueue - - val checkNetwork: (() -> Boolean)? get() = null - - interface Executor { - fun fetchAndCallback(endpoint: Call, callback: Callback) - } - - /** - * An object that receives Retrofit `Callback` arguments and determines whether or not - * an error should be returned. Use to return specific error cases for a given network request. - */ - interface ResultProcessing { - /** - * Return `R` if possible to cast given object to `R` or return `null`. - * This lambda is required due to jvm's type-erasing for generic types. - */ - val tryCastResponseBody: (Any?) -> R? - - /** Return result, success/failure, for the received request response */ - val resultFromResponse: (call: Call, response: Response) -> RetrofitResult - - /** Return error object `E` for the given failed request. */ - val errorFromFailureResponse: (call: Call<*>, t: Throwable) -> E - - /** Return error object `E` that contains/represents the given `AnyFetchError` */ - val errorFromNetworkFailure: (AnyFetchError) -> E - - } - - companion object { - /** Creates and returns a network request executor using Retrofit `Call` enqueue. */ - val callEnqueue: Executor - get() { - return object : Executor { - override fun fetchAndCallback(endpoint: Call, callback: Callback) { - endpoint.enqueue(callback) - } - } - } - } -} - -/** - * Fetch for response type `R` and callback in `success` callback. Invokes failure with - * an error subtype of `AnyFetchError` upon failure. - * - * @param usingExecutor Network request executor (set to `this.executor` by default) - * @param endpoint The API endpoint that should be fetched - * @param success Success callback with the response `R` - * @param failure Failure callback with an error case from `AnyFetchError` subtypes - */ -inline fun NetworkFetching.fetch( - usingExecutor: NetworkFetching.Executor = executor, - endpoint: Call, - noinline success: (R) -> Unit, - noinline failure: (FetchError) -> Unit -) { - val resultProcessing = RetrofitResultProcessing( - errorFromNetworkFailure = { FetchError.Network(it) }, - hasNetwork = checkNetwork - ) - fetch(usingExecutor, endpoint, resultProcessing, success, failure) -} - -/** - * Fetch for response type `R` and callback in `success` callback. Invokes failure with - * an error subtype of `E : AnyFetchError` upon failure. - * - * @param usingExecutor Network request executor (set to `this.executor` by default) - * @param endpoint The API endpoint that should be fetched - * @param resultProcessing Processes response and finds corresponding error case (if needed) - * @param success Success callback with the response `R` - * @param failure Failure callback with an error case from given error subtype `E` - */ -fun NetworkFetching.fetch( - usingExecutor: NetworkFetching.Executor = executor, - endpoint: Call, - resultProcessing: NetworkFetching.ResultProcessing, - success: (R) -> Unit, - failure: (E) -> Unit -) { - fetch(usingExecutor, endpoint, resultProcessing) { it.invoke(success, failure) } -} - -inline fun RetrofitResult.invoke(success: (R) -> Unit, failure: (E) -> Unit) { - return when (this) { - is RetrofitResult.Success -> success(this.result) - is RetrofitResult.Failure -> failure(this.error) - } -} - -sealed class RetrofitResult { - data class Success(val result: R) : RetrofitResult() - data class Failure(val error: E) : RetrofitResult() -} - -private fun fetch( - usingExecutor: NetworkFetching.Executor, - endpoint: Call, - resultProcessing: NetworkFetching.ResultProcessing, - callback: (RetrofitResult) -> Unit, -) { - usingExecutor.fetchAndCallback(endpoint, object : Callback { - override fun onFailure(call: Call, t: Throwable) { - callback(RetrofitResult.Failure(resultProcessing.errorFromFailureResponse(call, t))) - } - - override fun onResponse(call: Call, response: Response) { - callback(resultProcessing.resultFromResponse(call, response)) - } - }) -} - -//endregion - -//region Retrofit Standard Result Processing - -/** Returns result processing object for given response type `R` and error type `E` */ -open class RetrofitResultProcessing( - override val tryCastResponseBody: (Any?) -> R?, - override val errorFromNetworkFailure: (AnyFetchError) -> E, - hasNetwork: (() -> Boolean)? = null, -) : NetworkFetching.ResultProcessing { - - companion object { - inline operator fun invoke( - noinline errorFromNetworkFailure: (AnyFetchError) -> E, - noinline hasNetwork: (() -> Boolean)? = null - ) : RetrofitResultProcessing { - return RetrofitResultProcessing( - tryCastResponseBody = { - if (it == null && R::class.java == Unit::class.java) { Unit as R } - else { it as? R } - }, - errorFromNetworkFailure = errorFromNetworkFailure, hasNetwork = hasNetwork - ) - } - } - - override var errorFromFailureResponse: (call: Call<*>, t: Throwable) -> E = { call, t -> - val error: AnyFetchError = when(t) { - is UnknownHostException -> errorForUnknownHostException - is IllegalStateException -> errorForIllegalStateException - - //TODO: Check other cases - else -> AnyFetchError.Unknown() - } - errorFromNetworkFailure( - AnyFetchError.make(error = error, addingDump = "(Throwable): $t\n(Call): $call") - ) - } - - override var resultFromResponse: - (Call, Response) -> RetrofitResult = { call, response -> - if (response.isSuccessful) { - tryCastResponseBody(response.body())?.let { body -> - RetrofitResult.Success(body) - } ?: RetrofitResult.Failure( - errorFromNetworkFailure( - AnyFetchError.make( - error = AnyFetchError.NotFound.MissingData, - addingDump = "(Response): $response\n(Call): $call" - ) - ) - ) - } else { - RetrofitResult.Failure( - errorFromNetworkFailure(AnyFetchError.BadStatusCode(response.code(), response)) - ) - } - } - - //region Exception to AnyFetchError mapping - - var errorForUnknownHostException: AnyFetchError = if (hasNetwork != null) { - if (hasNetwork()) AnyFetchError.BadRequest.Encode - else AnyFetchError.NotFound.MissingNetwork - } else { - // Cannot distinguish the error case from `MissingNetwork` and `Encode` error. - AnyFetchError.Unknown() - } - - var errorForIllegalStateException: AnyFetchError = AnyFetchError.BadRequest.Decode - - //endregion + suspend fun requestAuthData( + anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody + ) : AuthDataResponse + suspend fun requestAuthDataValidation( + anonymousAuthDataValidationRequestBody: AnonymousAuthDataValidationRequestBody + ) : AuthDataValidationResponse } -//endregion \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/networking/NetworkFetchingRetrofitImpl.kt b/modules/src/main/java/app/lounge/networking/NetworkFetchingRetrofitImpl.kt new file mode 100644 index 000000000..04d3ddd7c --- /dev/null +++ b/modules/src/main/java/app/lounge/networking/NetworkFetchingRetrofitImpl.kt @@ -0,0 +1,88 @@ +package app.lounge.networking + +import app.lounge.extension.toByteArray +import app.lounge.model.AnonymousAuthDataRequestBody +import app.lounge.model.AnonymousAuthDataValidationRequestBody +import app.lounge.model.AuthDataResponse +import app.lounge.model.AuthDataValidationResponse +import com.aurora.gplayapi.GooglePlayApi +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import retrofit2.Retrofit +import retrofit2.http.Body +import retrofit2.http.HeaderMap +import retrofit2.http.POST +import javax.inject.Inject +import javax.inject.Singleton + +interface NetworkFetchingRetrofitAPI { + + companion object { + const val tokenBaseURL: String = "https://eu.gtoken.ecloud.global" + const val googlePlayBaseURL: String = GooglePlayApi.URL_BASE + } + + @POST(Path.authData) + suspend fun authDataRequest( + @HeaderMap headers: Map, + @Body requestBody: RequestBody + ): AuthDataResponse + + @POST(Path.sync) + suspend fun validateAuthentication( + @HeaderMap headers: Map + ): AuthDataValidationResponse + + + + object Header { + val authData: (() -> String) -> Map = { + mapOf(Pair("User-Agent", it.invoke())) + } + } + + private object Path { + const val authData = "/" + const val sync = "/fdfe/apps/contentSync" + } + +} + +@Singleton +class NetworkFetchingRetrofitImpl @Inject constructor( + retrofit: Retrofit +) : NetworkFetching { + + private val networkFetchingRetrofitAPI = retrofit.create( + NetworkFetchingRetrofitAPI::class.java + ) + + override suspend fun requestAuthData( + anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody + ): AuthDataResponse { + val requestBody: RequestBody = + anonymousAuthDataRequestBody.properties.toByteArray().let { result -> + result.toRequestBody( + contentType = "application/json".toMediaTypeOrNull(), + offset = 0, + byteCount = result.size + ) + } + return networkFetchingRetrofitAPI.authDataRequest( + requestBody = requestBody, + headers = NetworkFetchingRetrofitAPI.Header.authData { + anonymousAuthDataRequestBody.userAgent + } + ) + } + + override suspend fun requestAuthDataValidation( + anonymousAuthDataValidationRequestBody: AnonymousAuthDataValidationRequestBody + ): AuthDataValidationResponse { + return networkFetchingRetrofitAPI.validateAuthentication( + headers = anonymousAuthDataValidationRequestBody.header + ) + } + +} \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt b/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt deleted file mode 100644 index fb6290cdf..000000000 --- a/modules/src/main/java/app/lounge/networking/RetrofitConfig.kt +++ /dev/null @@ -1,40 +0,0 @@ -package app.lounge.networking - -import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor -import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory -import java.util.concurrent.TimeUnit - -/** - * Implement retrofit configuration - * 1. Try to use single instance of configuration - * 2. Generic way to handle success or failure - * 3. API parsing can be clean and testable - * - * NOTE: Try to use naming which define the action for the logic. - * */ - -internal fun Retrofit.Builder.appLounge( - baseURL: String, - shouldFollowRedirects: Boolean, - callTimeoutInSeconds: Long, -) : Retrofit { - return this.baseUrl(baseURL) - .addConverterFactory(GsonConverterFactory.create()) - .client( - OkHttpClient.Builder() - .addNetworkInterceptor(interceptor) - .callTimeout(callTimeoutInSeconds, TimeUnit.SECONDS) - .followRedirects(shouldFollowRedirects) - .build() - ) - .build() -} - -private val interceptor = run { - val httpLoggingInterceptor = HttpLoggingInterceptor() - httpLoggingInterceptor.apply { - httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY - } -} \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/users/Google.kt b/modules/src/main/java/app/lounge/users/Google.kt deleted file mode 100644 index 48ce6c2dd..000000000 --- a/modules/src/main/java/app/lounge/users/Google.kt +++ /dev/null @@ -1,8 +0,0 @@ -package app.lounge.users - -/** - * Implement API related to Google login flow only. - * 1. Login api for google users. - * 2. Parsing google user data. For now use typealias object, later we will refactor with generic type - * 3. Add unit test cases for the api functions. - * */ \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/users/Session.kt b/modules/src/main/java/app/lounge/users/Session.kt deleted file mode 100644 index 5885edea2..000000000 --- a/modules/src/main/java/app/lounge/users/Session.kt +++ /dev/null @@ -1,11 +0,0 @@ -package app.lounge.users - -/** - * Handle user login session in the file. - * This should be the only file which communicate with application regarding user data - * - * 1. Application facing api will be part of this file. - * 2. Manage user session for Anonymous, Google, PWA users. - * 3. In case of invalid user data, timeout etc. inform application about session failure. - * 4. If possible add session api testcases. - */ \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt b/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt deleted file mode 100644 index 9ca6f9067..000000000 --- a/modules/src/main/java/app/lounge/users/anonymous/Anonymous.kt +++ /dev/null @@ -1,39 +0,0 @@ -package app.lounge.users.anonymous - -import app.lounge.networking.FetchError - -/** - * Implement API related to Anonymous login flow only. - * 1. Login api for Anonymous users. - * 2. Parsing Anonymous user data. For now use typealias object, later we will refactor with generic type - * 3. Add unit test cases for the api functions. - * */ - -interface Anonymous { - - val api: AnonymousAPI - - companion object { - - fun anonymousRequestFor( - api: AnonymousAPI = AnonymousAPI.create() - ) : Anonymous { - return object : Anonymous { - override val api: AnonymousAPI = api - } - } - } - - // pass input from this function - fun requestAuthData( - anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody, - success : (LoginResponse) -> Unit, - failure : (FetchError) -> Unit - ) { - api.requestAuthData( - anonymousAuthDataRequestBody = anonymousAuthDataRequestBody, - success = success, - failure = failure - ) - } -} \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt b/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt deleted file mode 100644 index 9da4d4368..000000000 --- a/modules/src/main/java/app/lounge/users/anonymous/AnonymousAPI.kt +++ /dev/null @@ -1,41 +0,0 @@ -package app.lounge.users.anonymous - -import app.lounge.BuildConfig -import app.lounge.networking.FetchError -import com.google.gson.Gson -import java.util.Properties - -interface AnonymousAPI { - - companion object { - const val tokenBaseURL: String = "https://eu.gtoken.ecloud.global" - const val loginBaseURL: String = "GooglePlayApi.URL_SYNC" - - fun create(baseURL: String = tokenBaseURL) : AnonymousAPI { - return RetrofitAnonymousAPI( - baseURL = baseURL, - anonymousUserEndpointFollowsRedirects = true, - callTimeoutInSeconds = 30 - ) - } - } - - fun requestAuthData( - anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody, - success : (LoginResponse) -> Unit, - failure : (FetchError) -> Unit - ) - - object Header { - val authData: (() -> String) -> Map = { - mapOf(Pair("User-Agent", it.invoke())) - } - } - -} - -/** AnonymousAuthDataRequestBody */ -data class AnonymousAuthDataRequestBody( - val properties: Properties, - val userAgent: String -) diff --git a/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt b/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt deleted file mode 100644 index 68d90b84c..000000000 --- a/modules/src/main/java/app/lounge/users/anonymous/RetrofitAnonymousAPI.kt +++ /dev/null @@ -1,63 +0,0 @@ -package app.lounge.users.anonymous - -import app.lounge.extension.toByteArray -import app.lounge.networking.FetchError -import app.lounge.networking.NetworkFetching -import app.lounge.networking.appLounge -import app.lounge.networking.fetch -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.RequestBody -import retrofit2.Call -import retrofit2.Retrofit -import retrofit2.http.Body -import retrofit2.http.HeaderMap -import retrofit2.http.POST -import retrofit2.http.Url - -internal class RetrofitAnonymousAPI( - baseURL: String, - anonymousUserEndpointFollowsRedirects: Boolean, - callTimeoutInSeconds: Long, -): AnonymousAPI, NetworkFetching { - - private val anonymousUserEndPoint: AnonymousUserEndPointEndpoint = Retrofit.Builder().appLounge( - baseURL = baseURL, - shouldFollowRedirects = anonymousUserEndpointFollowsRedirects, - callTimeoutInSeconds = callTimeoutInSeconds - ).create(AnonymousUserEndPointEndpoint::class.java) - - interface AnonymousUserEndPointEndpoint { - - @POST - fun authDataRequest( - @Url url: String = AnonymousAPI.tokenBaseURL, - @HeaderMap headers: Map, - @Body requestBody: RequestBody - ): Call - } - - override fun requestAuthData( - anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody, - success: (LoginResponse) -> Unit, - failure: (FetchError) -> Unit - ) { - val requestBody = RequestBody.create( - "application/json".toMediaTypeOrNull(), - anonymousAuthDataRequestBody.properties.toByteArray() - ) - - fetch( - endpoint = anonymousUserEndPoint.authDataRequest( - requestBody = requestBody, - headers = AnonymousAPI.Header.authData { - anonymousAuthDataRequestBody.userAgent - } - ), - success = success, - failure = failure - ) - } - -} - -typealias LoginResponse = String -- GitLab From a6b83e0bf08fe5f3d5657c516aa5d2fb58215fe2 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Mon, 24 Jul 2023 22:58:00 +0530 Subject: [PATCH 08/11] Update the code as per review comment --- ...PITest.kt => UserAuthenticationAPITest.kt} | 43 +++++++++++++------ .../main/java/app/lounge/di/NetworkModule.kt | 5 +-- .../app/lounge/networking/RetrofitHandler.kt | 35 +++++++++++++++ ...tworkFetching.kt => UserAuthentication.kt} | 6 +-- ...l.kt => UserAuthenticationRetrofitImpl.kt} | 41 ++++++++++-------- 5 files changed, 92 insertions(+), 38 deletions(-) rename modules/src/androidTest/java/app/lounge/{NetworkFetchingAPITest.kt => UserAuthenticationAPITest.kt} (90%) create mode 100644 modules/src/main/java/app/lounge/networking/RetrofitHandler.kt rename modules/src/main/java/app/lounge/networking/{NetworkFetching.kt => UserAuthentication.kt} (79%) rename modules/src/main/java/app/lounge/networking/{NetworkFetchingRetrofitImpl.kt => UserAuthenticationRetrofitImpl.kt} (68%) diff --git a/modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt b/modules/src/androidTest/java/app/lounge/UserAuthenticationAPITest.kt similarity index 90% rename from modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt rename to modules/src/androidTest/java/app/lounge/UserAuthenticationAPITest.kt index d2b92e219..b5fc794cb 100644 --- a/modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt +++ b/modules/src/androidTest/java/app/lounge/UserAuthenticationAPITest.kt @@ -4,9 +4,10 @@ import app.lounge.model.AnonymousAuthDataRequestBody import app.lounge.model.AnonymousAuthDataValidationRequestBody import app.lounge.model.AuthDataResponse import app.lounge.model.AuthDataValidationResponse -import app.lounge.networking.NetworkFetching -import app.lounge.networking.NetworkFetchingRetrofitAPI -import app.lounge.networking.NetworkFetchingRetrofitImpl +import app.lounge.networking.NetworkResult +import app.lounge.networking.UserAuthentication +import app.lounge.networking.UserAuthenticationRetrofitAPI +import app.lounge.networking.UserAuthenticationRetrofitImpl import kotlinx.coroutines.runBlocking import okhttp3.OkHttpClient import org.junit.Test @@ -16,11 +17,11 @@ import java.io.InterruptedIOException import java.util.Properties import java.util.concurrent.TimeUnit -class NetworkFetchingAPITest { +class UserAuthenticationAPITest { - private val networkFetchingToken: NetworkFetching = NetworkFetchingRetrofitImpl( + private val userAuthenticationToken: UserAuthentication = UserAuthenticationRetrofitImpl( Retrofit.Builder() - .baseUrl(NetworkFetchingRetrofitAPI.tokenBaseURL) + .baseUrl(UserAuthenticationRetrofitAPI.tokenBaseURL) .addConverterFactory(GsonConverterFactory.create()) .client( OkHttpClient.Builder() @@ -30,9 +31,9 @@ class NetworkFetchingAPITest { .build() ) - private val networkFetchingGoogle: NetworkFetching = NetworkFetchingRetrofitImpl( + private val userAuthenticationGoogle: UserAuthentication = UserAuthenticationRetrofitImpl( Retrofit.Builder() - .baseUrl(NetworkFetchingRetrofitAPI.googlePlayBaseURL) + .baseUrl(UserAuthenticationRetrofitAPI.googlePlayBaseURL) .addConverterFactory(GsonConverterFactory.create()) .client( OkHttpClient.Builder() @@ -42,9 +43,9 @@ class NetworkFetchingAPITest { .build() ) - private val networkFetchingTimeoutGoogle: NetworkFetching = NetworkFetchingRetrofitImpl( + private val userAuthenticationTimeoutGoogle: UserAuthentication = UserAuthenticationRetrofitImpl( Retrofit.Builder() - .baseUrl(NetworkFetchingRetrofitAPI.googlePlayBaseURL) + .baseUrl(UserAuthenticationRetrofitAPI.googlePlayBaseURL) .addConverterFactory(GsonConverterFactory.create()) .client( OkHttpClient.Builder() @@ -65,9 +66,14 @@ class NetworkFetchingAPITest { @Test fun test1OnSuccessReturnsAuthData() = runBlocking { - authData = networkFetchingToken.requestAuthData( + val response = userAuthenticationToken.requestAuthData( anonymousAuthDataRequestBody = requestBodyData, ) + when(response){ + is NetworkResult.Success -> authData = response.data + else -> {} + } + assert(authData is AuthDataResponse) { "Assert!! Success must return data" } } @@ -77,11 +83,15 @@ class NetworkFetchingAPITest { authData?.let { authData -> authData.dfeCookie = "null" - result = networkFetchingGoogle.requestAuthDataValidation( + val response = userAuthenticationGoogle.requestAuthDataValidation( anonymousAuthDataValidationRequestBody = AnonymousAuthDataValidationRequestBody( authDataResponse = authData ) ) + when(response){ + is NetworkResult.Success -> result = response.data + else -> {} + } } assert(authData is AuthDataResponse) { "Assert!! AuthData must be present" } @@ -90,16 +100,21 @@ class NetworkFetchingAPITest { @Test fun test3OnTimeoutFailureReturnsError(): Unit = runBlocking { - var failure: Exception = Exception("No Error") + var failure: Throwable = Exception("No Error") authData?.let { authData -> authData.dfeCookie = "null" try { - networkFetchingTimeoutGoogle.requestAuthDataValidation( + val response = userAuthenticationTimeoutGoogle.requestAuthDataValidation( anonymousAuthDataValidationRequestBody = AnonymousAuthDataValidationRequestBody( authDataResponse = authData ) ) + + when(response){ + is NetworkResult.Error -> failure = response.exception + else -> {} + } } catch (e: InterruptedIOException) { failure = e } } assert(authData is AuthDataResponse) { "Assert!! AuthData must be present" } diff --git a/modules/src/main/java/app/lounge/di/NetworkModule.kt b/modules/src/main/java/app/lounge/di/NetworkModule.kt index 1763676d2..52667088e 100644 --- a/modules/src/main/java/app/lounge/di/NetworkModule.kt +++ b/modules/src/main/java/app/lounge/di/NetworkModule.kt @@ -1,7 +1,6 @@ package app.lounge.di -import app.lounge.networking.NetworkFetchingRetrofitAPI -import dagger.Binds +import app.lounge.networking.UserAuthenticationRetrofitAPI import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -24,7 +23,7 @@ internal object NetworkModule { @Singleton internal fun providesRetrofit( okHttpClient: OkHttpClient, - baseUrl: String = NetworkFetchingRetrofitAPI.tokenBaseURL + baseUrl: String = UserAuthenticationRetrofitAPI.tokenBaseURL ) : Retrofit { return Retrofit.Builder() .baseUrl(baseUrl) diff --git a/modules/src/main/java/app/lounge/networking/RetrofitHandler.kt b/modules/src/main/java/app/lounge/networking/RetrofitHandler.kt new file mode 100644 index 000000000..804dc542e --- /dev/null +++ b/modules/src/main/java/app/lounge/networking/RetrofitHandler.kt @@ -0,0 +1,35 @@ +package app.lounge.networking + +import retrofit2.Response + +sealed interface NetworkResult { + data class Success(val data: T) : NetworkResult + data class Error( + val exception: Throwable, + val code: Int, + val errorMessage: String, + ) : NetworkResult +} + +suspend fun fetch(call: suspend () -> Response): NetworkResult { + try { + val response = call() + if (response.isSuccessful) { + response.body()?.let { result -> + return NetworkResult.Success(result) + } + } + + return NetworkResult.Error( + exception = Exception(response.message()), + code = response.code(), + errorMessage = " ${response.code()} ${response.message()}" + ) + } catch (exception: Exception) { + return NetworkResult.Error( + exception = exception, + code = exception.hashCode(), + errorMessage = exception.toString() + ) + } +} diff --git a/modules/src/main/java/app/lounge/networking/NetworkFetching.kt b/modules/src/main/java/app/lounge/networking/UserAuthentication.kt similarity index 79% rename from modules/src/main/java/app/lounge/networking/NetworkFetching.kt rename to modules/src/main/java/app/lounge/networking/UserAuthentication.kt index c544c7aac..2eeed0f13 100644 --- a/modules/src/main/java/app/lounge/networking/NetworkFetching.kt +++ b/modules/src/main/java/app/lounge/networking/UserAuthentication.kt @@ -5,13 +5,13 @@ import app.lounge.model.AnonymousAuthDataValidationRequestBody import app.lounge.model.AuthDataResponse import app.lounge.model.AuthDataValidationResponse -interface NetworkFetching { +interface UserAuthentication { suspend fun requestAuthData( anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody - ) : AuthDataResponse + ) : NetworkResult suspend fun requestAuthDataValidation( anonymousAuthDataValidationRequestBody: AnonymousAuthDataValidationRequestBody - ) : AuthDataValidationResponse + ) : NetworkResult } diff --git a/modules/src/main/java/app/lounge/networking/NetworkFetchingRetrofitImpl.kt b/modules/src/main/java/app/lounge/networking/UserAuthenticationRetrofitImpl.kt similarity index 68% rename from modules/src/main/java/app/lounge/networking/NetworkFetchingRetrofitImpl.kt rename to modules/src/main/java/app/lounge/networking/UserAuthenticationRetrofitImpl.kt index 04d3ddd7c..ae87eaded 100644 --- a/modules/src/main/java/app/lounge/networking/NetworkFetchingRetrofitImpl.kt +++ b/modules/src/main/java/app/lounge/networking/UserAuthenticationRetrofitImpl.kt @@ -9,6 +9,7 @@ import com.aurora.gplayapi.GooglePlayApi import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody +import retrofit2.Response import retrofit2.Retrofit import retrofit2.http.Body import retrofit2.http.HeaderMap @@ -16,7 +17,7 @@ import retrofit2.http.POST import javax.inject.Inject import javax.inject.Singleton -interface NetworkFetchingRetrofitAPI { +interface UserAuthenticationRetrofitAPI { companion object { const val tokenBaseURL: String = "https://eu.gtoken.ecloud.global" @@ -27,12 +28,12 @@ interface NetworkFetchingRetrofitAPI { suspend fun authDataRequest( @HeaderMap headers: Map, @Body requestBody: RequestBody - ): AuthDataResponse + ): Response @POST(Path.sync) suspend fun validateAuthentication( @HeaderMap headers: Map - ): AuthDataValidationResponse + ): Response @@ -50,17 +51,17 @@ interface NetworkFetchingRetrofitAPI { } @Singleton -class NetworkFetchingRetrofitImpl @Inject constructor( +class UserAuthenticationRetrofitImpl @Inject constructor( retrofit: Retrofit -) : NetworkFetching { +) : UserAuthentication { - private val networkFetchingRetrofitAPI = retrofit.create( - NetworkFetchingRetrofitAPI::class.java + private val userAuthenticationRetrofitAPI = retrofit.create( + UserAuthenticationRetrofitAPI::class.java ) override suspend fun requestAuthData( anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody - ): AuthDataResponse { + ): NetworkResult { val requestBody: RequestBody = anonymousAuthDataRequestBody.properties.toByteArray().let { result -> result.toRequestBody( @@ -69,20 +70,24 @@ class NetworkFetchingRetrofitImpl @Inject constructor( byteCount = result.size ) } - return networkFetchingRetrofitAPI.authDataRequest( - requestBody = requestBody, - headers = NetworkFetchingRetrofitAPI.Header.authData { - anonymousAuthDataRequestBody.userAgent - } - ) + return fetch { + userAuthenticationRetrofitAPI.authDataRequest( + requestBody = requestBody, + headers = UserAuthenticationRetrofitAPI.Header.authData { + anonymousAuthDataRequestBody.userAgent + } + ) + } } override suspend fun requestAuthDataValidation( anonymousAuthDataValidationRequestBody: AnonymousAuthDataValidationRequestBody - ): AuthDataValidationResponse { - return networkFetchingRetrofitAPI.validateAuthentication( - headers = anonymousAuthDataValidationRequestBody.header - ) + ): NetworkResult { + return fetch { + userAuthenticationRetrofitAPI.validateAuthentication( + headers = anonymousAuthDataValidationRequestBody.header + ) + } } } \ No newline at end of file -- GitLab From de0ae7a019395ce60a82a5d6413daede15556c2c Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Thu, 27 Jul 2023 13:09:34 +0530 Subject: [PATCH 09/11] Remove redundant code --- .../app/lounge/UserAuthenticationAPITest.kt | 164 ------------------ .../main/java/app/lounge/di/NetworkModule.kt | 3 +- .../java/app/lounge/extension/Extension.kt | 10 -- .../src/main/java/app/lounge/model/Model.kt | 24 --- .../lounge/networking/UserAuthentication.kt | 17 -- .../UserAuthenticationRetrofitImpl.kt | 93 ---------- 6 files changed, 1 insertion(+), 310 deletions(-) delete mode 100644 modules/src/androidTest/java/app/lounge/UserAuthenticationAPITest.kt delete mode 100644 modules/src/main/java/app/lounge/extension/Extension.kt delete mode 100644 modules/src/main/java/app/lounge/model/Model.kt delete mode 100644 modules/src/main/java/app/lounge/networking/UserAuthentication.kt delete mode 100644 modules/src/main/java/app/lounge/networking/UserAuthenticationRetrofitImpl.kt diff --git a/modules/src/androidTest/java/app/lounge/UserAuthenticationAPITest.kt b/modules/src/androidTest/java/app/lounge/UserAuthenticationAPITest.kt deleted file mode 100644 index b5fc794cb..000000000 --- a/modules/src/androidTest/java/app/lounge/UserAuthenticationAPITest.kt +++ /dev/null @@ -1,164 +0,0 @@ -package app.lounge - -import app.lounge.model.AnonymousAuthDataRequestBody -import app.lounge.model.AnonymousAuthDataValidationRequestBody -import app.lounge.model.AuthDataResponse -import app.lounge.model.AuthDataValidationResponse -import app.lounge.networking.NetworkResult -import app.lounge.networking.UserAuthentication -import app.lounge.networking.UserAuthenticationRetrofitAPI -import app.lounge.networking.UserAuthenticationRetrofitImpl -import kotlinx.coroutines.runBlocking -import okhttp3.OkHttpClient -import org.junit.Test -import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory -import java.io.InterruptedIOException -import java.util.Properties -import java.util.concurrent.TimeUnit - -class UserAuthenticationAPITest { - - private val userAuthenticationToken: UserAuthentication = UserAuthenticationRetrofitImpl( - Retrofit.Builder() - .baseUrl(UserAuthenticationRetrofitAPI.tokenBaseURL) - .addConverterFactory(GsonConverterFactory.create()) - .client( - OkHttpClient.Builder() - .callTimeout(10, TimeUnit.SECONDS) - .build() - ) - .build() - ) - - private val userAuthenticationGoogle: UserAuthentication = UserAuthenticationRetrofitImpl( - Retrofit.Builder() - .baseUrl(UserAuthenticationRetrofitAPI.googlePlayBaseURL) - .addConverterFactory(GsonConverterFactory.create()) - .client( - OkHttpClient.Builder() - .callTimeout(10, TimeUnit.SECONDS) - .build() - ) - .build() - ) - - private val userAuthenticationTimeoutGoogle: UserAuthentication = UserAuthenticationRetrofitImpl( - Retrofit.Builder() - .baseUrl(UserAuthenticationRetrofitAPI.googlePlayBaseURL) - .addConverterFactory(GsonConverterFactory.create()) - .client( - OkHttpClient.Builder() - .callTimeout(10, TimeUnit.MILLISECONDS) - .build() - ) - .build() - ) - - private val requestBodyData = AnonymousAuthDataRequestBody( - properties = testSystemProperties, - userAgent = testUserAgent - ) - - companion object { - var authData: AuthDataResponse? = null - } - - @Test - fun test1OnSuccessReturnsAuthData() = runBlocking { - val response = userAuthenticationToken.requestAuthData( - anonymousAuthDataRequestBody = requestBodyData, - ) - when(response){ - is NetworkResult.Success -> authData = response.data - else -> {} - } - - assert(authData is AuthDataResponse) { "Assert!! Success must return data" } - } - - @Test - fun test2OnSuccessReturnsLoginData() = runBlocking { - var result: AuthDataValidationResponse? = null - authData?.let { authData -> - authData.dfeCookie = "null" - - val response = userAuthenticationGoogle.requestAuthDataValidation( - anonymousAuthDataValidationRequestBody = AnonymousAuthDataValidationRequestBody( - authDataResponse = authData - ) - ) - when(response){ - is NetworkResult.Success -> result = response.data - else -> {} - } - } - - assert(authData is AuthDataResponse) { "Assert!! AuthData must be present" } - assert(result is AuthDataValidationResponse) { "Assert!! `response` must have data" } - } - - @Test - fun test3OnTimeoutFailureReturnsError(): Unit = runBlocking { - var failure: Throwable = Exception("No Error") - authData?.let { authData -> - authData.dfeCookie = "null" - - try { - val response = userAuthenticationTimeoutGoogle.requestAuthDataValidation( - anonymousAuthDataValidationRequestBody = AnonymousAuthDataValidationRequestBody( - authDataResponse = authData - ) - ) - - when(response){ - is NetworkResult.Error -> failure = response.exception - else -> {} - } - } catch (e: InterruptedIOException) { failure = e } - } - assert(authData is AuthDataResponse) { "Assert!! AuthData must be present" } - assert(failure is InterruptedIOException) { "Assert!! Timeout Failure callback must call" } - } -} - -private const val testUserAgent: String = "{\"package\":\"foundation.e.apps.debug\",\"version\":\"2.5.5.debug\",\"device\":\"coral\",\"api\":32,\"os_version\":\"1.11-s-20230511288805-dev-coral\",\"build_id\":\"319e25cd.20230630224839\"}" - -private val testSystemProperties = Properties().apply { - setProperty("UserReadableName", "coral-default") - setProperty("Build.HARDWARE", "coral") - setProperty("Build.RADIO", "g8150-00123-220402-B-8399852") - setProperty("Build.FINGERPRINT","google/coral/coral:12/SQ3A.220705.003.A1/8672226:user/release-keys") - setProperty("Build.BRAND", "google") - setProperty("Build.DEVICE", "coral") - setProperty("Build.VERSION.SDK_INT", "32") - setProperty("Build.VERSION.RELEASE", "12") - setProperty("Build.MODEL", "Pixel 4 XL") - setProperty("Build.MANUFACTURER", "Google") - setProperty("Build.PRODUCT", "coral") - setProperty("Build.ID", "SQ3A.220705.004") - setProperty("Build.BOOTLOADER", "c2f2-0.4-8351033") - setProperty("TouchScreen", "3") - setProperty("Keyboard", "1") - setProperty("Navigation", "1") - setProperty("ScreenLayout", "2") - setProperty("HasHardKeyboard", "false") - setProperty("HasFiveWayNavigation", "false") - setProperty("Screen.Density", "560") - setProperty("Screen.Width", "1440") - setProperty("Screen.Height", "2984") - setProperty("Platforms", "arm64-v8a,armeabi-v7a,armeabi") - setProperty("Features", "android.hardware.sensor.proximity,com.verizon.hardware.telephony.lte,com.verizon.hardware.telephony.ehrpd,android.hardware.sensor.accelerometer,android.software.controls,android.hardware.faketouch,com.google.android.feature.D2D_CABLE_MIGRATION_FEATURE,android.hardware.telephony.euicc,android.hardware.reboot_escrow,android.hardware.usb.accessory,android.hardware.telephony.cdma,android.software.backup,android.hardware.touchscreen,android.hardware.touchscreen.multitouch,android.software.print,org.lineageos.weather,android.software.activities_on_secondary_displays,android.hardware.wifi.rtt,com.google.android.feature.PIXEL_2017_EXPERIENCE,android.software.voice_recognizers,android.software.picture_in_picture,android.hardware.sensor.gyroscope,android.hardware.audio.low_latency,android.software.vulkan.deqp.level,android.software.cant_save_state,com.google.android.feature.PIXEL_2018_EXPERIENCE,android.hardware.security.model.compatible,com.google.android.feature.PIXEL_2019_EXPERIENCE,android.hardware.opengles.aep,org.lineageos.livedisplay,org.lineageos.profiles,android.hardware.bluetooth,android.hardware.camera.autofocus,android.hardware.telephony.gsm,android.hardware.telephony.ims,android.software.incremental_delivery,android.software.sip.voip,android.hardware.se.omapi.ese,android.software.opengles.deqp.level,android.hardware.usb.host,android.hardware.audio.output,android.software.verified_boot,android.hardware.camera.flash,android.hardware.camera.front,android.hardware.sensor.hifi_sensors,com.google.android.apps.photos.PIXEL_2019_PRELOAD,android.hardware.se.omapi.uicc,android.hardware.strongbox_keystore,android.hardware.screen.portrait,android.hardware.nfc,com.google.android.feature.TURBO_PRELOAD,com.nxp.mifare,android.hardware.sensor.stepdetector,android.software.home_screen,android.hardware.context_hub,android.hardware.microphone,android.software.autofill,org.lineageos.hardware,org.lineageos.globalactions,android.software.securely_removes_users,com.google.android.feature.PIXEL_EXPERIENCE,android.hardware.bluetooth_le,android.hardware.sensor.compass,com.google.android.feature.GOOGLE_FI_BUNDLED,android.hardware.touchscreen.multitouch.jazzhand,android.hardware.sensor.barometer,android.software.app_widgets,android.hardware.telephony.carrierlock,android.software.input_methods,android.hardware.sensor.light,android.hardware.vulkan.version,android.software.companion_device_setup,android.software.device_admin,com.google.android.feature.WELLBEING,android.hardware.wifi.passpoint,android.hardware.camera,org.lineageos.trust,android.hardware.device_unique_attestation,android.hardware.screen.landscape,android.software.device_id_attestation,com.google.android.feature.AER_OPTIMIZED,android.hardware.ram.normal,org.lineageos.android,com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE,android.software.managed_users,android.software.webview,android.hardware.sensor.stepcounter,android.hardware.camera.capability.manual_post_processing,android.hardware.camera.any,android.hardware.camera.capability.raw,android.hardware.vulkan.compute,android.software.connectionservice,android.hardware.touchscreen.multitouch.distinct,android.hardware.location.network,android.software.cts,android.software.sip,android.hardware.camera.capability.manual_sensor,android.software.app_enumeration,android.hardware.camera.level.full,android.hardware.identity_credential,android.hardware.wifi.direct,android.software.live_wallpaper,android.software.ipsec_tunnels,org.lineageos.settings,android.hardware.sensor.assist,android.hardware.audio.pro,android.hardware.nfc.hcef,android.hardware.nfc.uicc,android.hardware.location.gps,android.sofware.nfc.beam,android.software.midi,android.hardware.nfc.any,android.hardware.nfc.ese,android.hardware.nfc.hce,android.hardware.wifi,android.hardware.location,android.hardware.vulkan.level,android.hardware.wifi.aware,android.software.secure_lock_screen,android.hardware.biometrics.face,android.hardware.telephony,android.software.file_based_encryption") - setProperty("Locales", "af,af_ZA,am,am_ET,ar,ar_EG,ar_XB,as,ast_ES,az,be,bg,bg_BG,bn,bs,ca,ca_ES,cs,cs_CZ,cy,da,da_DK,de,de_DE,el,el_GR,en,en_AU,en_CA,en_GB,en_IN,en_US,en_XA,en_XC,es,es_419,es_ES,es_US,et,eu,fa,fa_IR,fi,fi_FI,fil,fil_PH,fr,fr_CA,fr_FR,gd,gl,gu,hi,hi_IN,hr,hr_HR,hu,hu_HU,hy,in,in_ID,is,it,it_IT,iw,iw_IL,ja,ja_JP,ka,kk,km,kn,ko,ko_KR,ky,lo,lt,lt_LT,lv,lv_LV,mk,ml,mn,mr,ms,ms_MY,my,nb,nb_NO,ne,nl,nl_NL,or,pa,pl,pl_PL,pt,pt_BR,pt_PT,ro,ro_RO,ru,ru_RU,si,sk,sk_SK,sl,sl_SI,sq,sr,sr_Latn,sr_RS,sv,sv_SE,sw,sw_TZ,ta,te,th,th_TH,tr,tr_TR,uk,uk_UA,ur,uz,vi,vi_VN,zh_CN,zh_HK,zh_TW,zu,zu_ZA") - setProperty("SharedLibraries", "android.test.base,android.test.mock,com.vzw.apnlib,android.hidl.manager-V1.0-java,qti-telephony-hidl-wrapper,libfastcvopt.so,google-ril,qti-telephony-utils,com.android.omadm.radioconfig,libcdsprpc.so,android.hidl.base-V1.0-java,com.qualcomm.qmapbridge,libairbrush-pixel.so,com.google.android.camera.experimental2019,libOpenCL-pixel.so,libadsprpc.so,com.android.location.provider,android.net.ipsec.ike,com.android.future.usb.accessory,libsdsprpc.so,android.ext.shared,javax.obex,izat.xt.srv,com.google.android.gms,lib_aion_buffer.so,com.qualcomm.uimremoteclientlibrary,libqdMetaData.so,com.qualcomm.uimremoteserverlibrary,com.qualcomm.qcrilhook,android.test.runner,org.apache.http.legacy,com.google.android.camera.extensions,com.google.android.hardwareinfo,com.android.cts.ctsshim.shared_library,com.android.nfc_extras,com.android.media.remotedisplay,com.android.mediadrm.signer,com.qualcomm.qti.imscmservice-V2.0-java,qti-telephony-hidl-wrapper-prd,com.qualcomm.qti.imscmservice-V2.1-java,com.qualcomm.qti.imscmservice-V2.2-java") - setProperty("GL.Version", "196610") - setProperty("GL.Extensions", ",GL_AMD_compressed_ATC_texture,GL_AMD_performance_monitor,GL_ANDROID_extension_pack_es31a,GL_APPLE_texture_2D_limited_npot,GL_ARB_vertex_buffer_object,GL_ARM_shader_framebuffer_fetch_depth_stencil,GL_EXT_EGL_image_array,GL_EXT_EGL_image_external_wrap_modes,GL_EXT_EGL_image_storage,GL_EXT_YUV_target,GL_EXT_blend_func_extended,GL_EXT_blit_framebuffer_params,GL_EXT_buffer_storage,GL_EXT_clip_control,GL_EXT_clip_cull_distance,GL_EXT_color_buffer_float,GL_EXT_color_buffer_half_float,GL_EXT_copy_image,GL_EXT_debug_label,GL_EXT_debug_marker,GL_EXT_discard_framebuffer,GL_EXT_disjoint_timer_query,GL_EXT_draw_buffers_indexed,GL_EXT_external_buffer,GL_EXT_fragment_invocation_density,GL_EXT_geometry_shader,GL_EXT_gpu_shader5,GL_EXT_memory_object,GL_EXT_memory_object_fd,GL_EXT_multisampled_render_to_texture,GL_EXT_multisampled_render_to_texture2,GL_EXT_primitive_bounding_box,GL_EXT_protected_textures,GL_EXT_read_format_bgra,GL_EXT_robustness,GL_EXT_sRGB,GL_EXT_sRGB_write_control,GL_EXT_shader_framebuffer_fetch,GL_EXT_shader_io_blocks,GL_EXT_shader_non_constant_global_initializers,GL_EXT_tessellation_shader,GL_EXT_texture_border_clamp,GL_EXT_texture_buffer,GL_EXT_texture_cube_map_array,GL_EXT_texture_filter_anisotropic,GL_EXT_texture_format_BGRA8888,GL_EXT_texture_format_sRGB_override,GL_EXT_texture_norm16,GL_EXT_texture_sRGB_R8,GL_EXT_texture_sRGB_decode,GL_EXT_texture_type_2_10_10_10_REV,GL_KHR_blend_equation_advanced,GL_KHR_blend_equation_advanced_coherent,GL_KHR_debug,GL_KHR_no_error,GL_KHR_robust_buffer_access_behavior,GL_KHR_texture_compression_astc_hdr,GL_KHR_texture_compression_astc_ldr,GL_NV_shader_noperspective_interpolation,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_EGL_sync,GL_OES_blend_equation_separate,GL_OES_blend_func_separate,GL_OES_blend_subtract,GL_OES_compressed_ETC1_RGB8_texture,GL_OES_compressed_paletted_texture,GL_OES_depth24,GL_OES_depth_texture,GL_OES_depth_texture_cube_map,GL_OES_draw_texture,GL_OES_element_index_uint,GL_OES_framebuffer_object,GL_OES_get_program_binary,GL_OES_matrix_palette,GL_OES_packed_depth_stencil,GL_OES_point_size_array,GL_OES_point_sprite,GL_OES_read_format,GL_OES_rgb8_rgba8,GL_OES_sample_shading,GL_OES_sample_variables,GL_OES_shader_image_atomic,GL_OES_shader_multisample_interpolation,GL_OES_standard_derivatives,GL_OES_stencil_wrap,GL_OES_surfaceless_context,GL_OES_texture_3D,GL_OES_texture_compression_astc,GL_OES_texture_cube_map,GL_OES_texture_env_crossbar,GL_OES_texture_float,GL_OES_texture_float_linear,GL_OES_texture_half_float,GL_OES_texture_half_float_linear,GL_OES_texture_mirrored_repeat,GL_OES_texture_npot,GL_OES_texture_stencil8,GL_OES_texture_storage_multisample_2d_array,GL_OES_texture_view,GL_OES_vertex_array_object,GL_OES_vertex_half_float,GL_OVR_multiview,GL_OVR_multiview2,GL_OVR_multiview_multisampled_render_to_texture,GL_QCOM_YUV_texture_gather,GL_QCOM_alpha_test,GL_QCOM_extended_get,GL_QCOM_motion_estimation,GL_QCOM_shader_framebuffer_fetch_noncoherent,GL_QCOM_shader_framebuffer_fetch_rate,GL_QCOM_texture_foveated,GL_QCOM_texture_foveated_subsampled_layout,GL_QCOM_tiled_rendering,GL_QCOM_validate_shader_binary") - setProperty("Client", "android-google") - setProperty("GSF.version", "223616055") - setProperty("Vending.version", "82151710") - setProperty("Vending.versionString", "21.5.17-21 [0] [PR] 326734551") - setProperty("Roaming", "mobile-notroaming") - setProperty("TimeZone", "UTC-10") - setProperty("CellOperator", "310") - setProperty("SimOperator", "38") -} diff --git a/modules/src/main/java/app/lounge/di/NetworkModule.kt b/modules/src/main/java/app/lounge/di/NetworkModule.kt index 52667088e..5251de66f 100644 --- a/modules/src/main/java/app/lounge/di/NetworkModule.kt +++ b/modules/src/main/java/app/lounge/di/NetworkModule.kt @@ -1,6 +1,5 @@ package app.lounge.di -import app.lounge.networking.UserAuthenticationRetrofitAPI import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -23,7 +22,7 @@ internal object NetworkModule { @Singleton internal fun providesRetrofit( okHttpClient: OkHttpClient, - baseUrl: String = UserAuthenticationRetrofitAPI.tokenBaseURL + baseUrl: String ) : Retrofit { return Retrofit.Builder() .baseUrl(baseUrl) diff --git a/modules/src/main/java/app/lounge/extension/Extension.kt b/modules/src/main/java/app/lounge/extension/Extension.kt deleted file mode 100644 index 17a68e188..000000000 --- a/modules/src/main/java/app/lounge/extension/Extension.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.lounge.extension - -import com.google.gson.Gson -import java.util.Properties - -/** - * Convert Properties parameter to byte array - * @return Byte Array of Properties - * */ -fun Properties.toByteArray() = Gson().toJson(this).toByteArray() \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/model/Model.kt b/modules/src/main/java/app/lounge/model/Model.kt deleted file mode 100644 index ba4263416..000000000 --- a/modules/src/main/java/app/lounge/model/Model.kt +++ /dev/null @@ -1,24 +0,0 @@ -package app.lounge.model - -import com.aurora.gplayapi.data.models.AuthData -import com.aurora.gplayapi.data.providers.HeaderProvider -import okhttp3.ResponseBody -import java.util.Properties - - -/** AnonymousAuthDataRequestBody */ -data class AnonymousAuthDataRequestBody( - val properties: Properties, - val userAgent: String -) - -/** AnonymousLoginRequestBody */ -data class AnonymousAuthDataValidationRequestBody( - val authDataResponse: AuthDataResponse, -) { - val header = HeaderProvider.getDefaultHeaders(authDataResponse) -} - -typealias AuthDataResponse = AuthData - -typealias AuthDataValidationResponse = ResponseBody \ No newline at end of file diff --git a/modules/src/main/java/app/lounge/networking/UserAuthentication.kt b/modules/src/main/java/app/lounge/networking/UserAuthentication.kt deleted file mode 100644 index 2eeed0f13..000000000 --- a/modules/src/main/java/app/lounge/networking/UserAuthentication.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.lounge.networking - -import app.lounge.model.AnonymousAuthDataRequestBody -import app.lounge.model.AnonymousAuthDataValidationRequestBody -import app.lounge.model.AuthDataResponse -import app.lounge.model.AuthDataValidationResponse - -interface UserAuthentication { - suspend fun requestAuthData( - anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody - ) : NetworkResult - - suspend fun requestAuthDataValidation( - anonymousAuthDataValidationRequestBody: AnonymousAuthDataValidationRequestBody - ) : NetworkResult -} - diff --git a/modules/src/main/java/app/lounge/networking/UserAuthenticationRetrofitImpl.kt b/modules/src/main/java/app/lounge/networking/UserAuthenticationRetrofitImpl.kt deleted file mode 100644 index ae87eaded..000000000 --- a/modules/src/main/java/app/lounge/networking/UserAuthenticationRetrofitImpl.kt +++ /dev/null @@ -1,93 +0,0 @@ -package app.lounge.networking - -import app.lounge.extension.toByteArray -import app.lounge.model.AnonymousAuthDataRequestBody -import app.lounge.model.AnonymousAuthDataValidationRequestBody -import app.lounge.model.AuthDataResponse -import app.lounge.model.AuthDataValidationResponse -import com.aurora.gplayapi.GooglePlayApi -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.RequestBody -import okhttp3.RequestBody.Companion.toRequestBody -import retrofit2.Response -import retrofit2.Retrofit -import retrofit2.http.Body -import retrofit2.http.HeaderMap -import retrofit2.http.POST -import javax.inject.Inject -import javax.inject.Singleton - -interface UserAuthenticationRetrofitAPI { - - companion object { - const val tokenBaseURL: String = "https://eu.gtoken.ecloud.global" - const val googlePlayBaseURL: String = GooglePlayApi.URL_BASE - } - - @POST(Path.authData) - suspend fun authDataRequest( - @HeaderMap headers: Map, - @Body requestBody: RequestBody - ): Response - - @POST(Path.sync) - suspend fun validateAuthentication( - @HeaderMap headers: Map - ): Response - - - - object Header { - val authData: (() -> String) -> Map = { - mapOf(Pair("User-Agent", it.invoke())) - } - } - - private object Path { - const val authData = "/" - const val sync = "/fdfe/apps/contentSync" - } - -} - -@Singleton -class UserAuthenticationRetrofitImpl @Inject constructor( - retrofit: Retrofit -) : UserAuthentication { - - private val userAuthenticationRetrofitAPI = retrofit.create( - UserAuthenticationRetrofitAPI::class.java - ) - - override suspend fun requestAuthData( - anonymousAuthDataRequestBody: AnonymousAuthDataRequestBody - ): NetworkResult { - val requestBody: RequestBody = - anonymousAuthDataRequestBody.properties.toByteArray().let { result -> - result.toRequestBody( - contentType = "application/json".toMediaTypeOrNull(), - offset = 0, - byteCount = result.size - ) - } - return fetch { - userAuthenticationRetrofitAPI.authDataRequest( - requestBody = requestBody, - headers = UserAuthenticationRetrofitAPI.Header.authData { - anonymousAuthDataRequestBody.userAgent - } - ) - } - } - - override suspend fun requestAuthDataValidation( - anonymousAuthDataValidationRequestBody: AnonymousAuthDataValidationRequestBody - ): NetworkResult { - return fetch { - userAuthenticationRetrofitAPI.validateAuthentication( - headers = anonymousAuthDataValidationRequestBody.header - ) - } - } - -} \ No newline at end of file -- GitLab From 054f1424416995c828ffe08cc86d2f07d0b444ac Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Thu, 27 Jul 2023 14:39:38 +0530 Subject: [PATCH 10/11] Add Copyright text --- app/build.gradle | 20 +++++++++++++++++-- modules/build.gradle | 19 ++++++++++++++++++ .../main/java/app/lounge/di/NetworkModule.kt | 19 ++++++++++++++++++ .../app/lounge/networking/RetrofitHandler.kt | 19 ++++++++++++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f0e0d5e26..15d44becc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,3 +1,21 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * 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 . + */ + plugins { id 'com.android.application' @@ -147,8 +165,6 @@ allOpen { dependencies { - implementation project(path: ':modules') - // TODO: Add splitinstall-lib to a repo https://gitlab.e.foundation/e/os/backlog/-/issues/628 api files('libs/splitinstall-lib.jar') diff --git a/modules/build.gradle b/modules/build.gradle index d36cf010a..48fab303e 100644 --- a/modules/build.gradle +++ b/modules/build.gradle @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * 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 . + */ + + plugins { id 'com.android.library' id 'org.jetbrains.kotlin.android' diff --git a/modules/src/main/java/app/lounge/di/NetworkModule.kt b/modules/src/main/java/app/lounge/di/NetworkModule.kt index 5251de66f..e64cde0cf 100644 --- a/modules/src/main/java/app/lounge/di/NetworkModule.kt +++ b/modules/src/main/java/app/lounge/di/NetworkModule.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * 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 . + */ + + package app.lounge.di import dagger.Module diff --git a/modules/src/main/java/app/lounge/networking/RetrofitHandler.kt b/modules/src/main/java/app/lounge/networking/RetrofitHandler.kt index 804dc542e..9138167f7 100644 --- a/modules/src/main/java/app/lounge/networking/RetrofitHandler.kt +++ b/modules/src/main/java/app/lounge/networking/RetrofitHandler.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * 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 . + */ + + package app.lounge.networking import retrofit2.Response -- GitLab From d3400d52dc4bfe8dab349541aad7f7f3ed5d86f5 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Thu, 27 Jul 2023 14:41:11 +0530 Subject: [PATCH 11/11] revert unwnated changes --- app/build.gradle | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 15d44becc..1d0b1c0d7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,21 +1,3 @@ -/* - * Copyright MURENA SAS 2023 - * Apps Quickly and easily install Android apps onto your device! - * - * 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 . - */ - plugins { id 'com.android.application' -- GitLab