From cce47ed4724508a316a654face4d02939c025764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Mon, 29 Mar 2021 10:21:20 +0200 Subject: [PATCH] [Api] Implement caching invalid API signature response. --- .../pl/szczodrzynski/edziennik/Extensions.kt | 2 +- .../szczodrzynski/edziennik/config/Config.kt | 5 +++ .../edziennik/data/api/szkolny/SzkolnyApi.kt | 7 ++++ .../interceptor/ApiCacheInterceptor.kt | 36 +++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/ApiCacheInterceptor.kt diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index f27a0e8e..350bf67c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -1112,7 +1112,7 @@ fun Throwable.toErrorCode() = when (this) { is SzkolnyApiException -> this.error?.toErrorCode() else -> null } -private fun ApiResponse.Error.toErrorCode() = when (this.code) { +fun ApiResponse.Error.toErrorCode() = when (this.code) { "PdoError" -> ERROR_API_PDO_ERROR "InvalidClient" -> ERROR_API_INVALID_CLIENT "InvalidArgument" -> ERROR_API_INVALID_ARGUMENT diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt index 5d5f20e0..160deb23 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/Config.kt @@ -115,6 +115,11 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig { get() { mValidation = mValidation ?: values["buildValidation"]; return mValidation } set(value) { set("buildValidation", value); mValidation = value } + private var mApiInvalidCert: String? = null + var apiInvalidCert: String? + get() { mApiInvalidCert = mApiInvalidCert ?: values["apiInvalidCert"]; return mApiInvalidCert } + set(value) { set("apiInvalidCert", value); mApiInvalidCert = value } + private var rawEntries: List = db.configDao().getAllNow() private val profileConfigs: HashMap = hashMapOf() init { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt index 3a434001..20da6952 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt @@ -18,7 +18,9 @@ import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.data.api.ERROR_API_INVALID_SIGNATURE import pl.szczodrzynski.edziennik.data.api.szkolny.adapter.DateAdapter import pl.szczodrzynski.edziennik.data.api.szkolny.adapter.TimeAdapter +import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.ApiCacheInterceptor import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.SignatureInterceptor +import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.Signing import pl.szczodrzynski.edziennik.data.api.szkolny.request.* import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus @@ -57,6 +59,7 @@ class SzkolnyApi(val app: App) : CoroutineScope { val okHttpClient: OkHttpClient = app.http.newBuilder() .followRedirects(true) .callTimeout(10, SECONDS) + .addInterceptor(ApiCacheInterceptor(app)) .addInterceptor(SignatureInterceptor(app)) .build() @@ -158,6 +161,10 @@ class SzkolnyApi(val app: App) : CoroutineScope { } } + if (body?.errors?.any { it.toErrorCode() == ERROR_API_INVALID_SIGNATURE } == true) { + app.config.apiInvalidCert = Signing.appCertificate.md5() + } + throw SzkolnyApiException(body?.errors?.firstOrNull()) } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/ApiCacheInterceptor.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/ApiCacheInterceptor.kt new file mode 100644 index 00000000..6f958ef6 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/ApiCacheInterceptor.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) Kuba SzczodrzyƄski 2021-3-29. + */ + +package pl.szczodrzynski.edziennik.data.api.szkolny.interceptor + +import okhttp3.* +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse +import pl.szczodrzynski.edziennik.md5 + +class ApiCacheInterceptor(val app: App) : Interceptor { + + override fun intercept(chain: Interceptor.Chain): Response { + if (Signing.appCertificate.md5() == app.config.apiInvalidCert) { + val response = ApiResponse( + success = false, + errors = listOf(ApiResponse.Error("InvalidSignature", "")) + ) + + return Response.Builder() + .request(chain.request()) + .protocol(Protocol.HTTP_1_1) + .code(401) + .message("Unauthorized") + .addHeader("Content-Type", "application/json") + .body(ResponseBody.create( + MediaType.parse("application/json"), + app.gson.toJson(response) + )) + .build() + } + + return chain.proceed(chain.request()) + } +}