[Api] Implement caching invalid API signature response.

This commit is contained in:
Kuba Szczodrzyński 2021-03-29 10:21:20 +02:00
parent 2808c66840
commit cce47ed472
4 changed files with 49 additions and 1 deletions

View File

@ -1112,7 +1112,7 @@ fun Throwable.toErrorCode() = when (this) {
is SzkolnyApiException -> this.error?.toErrorCode() is SzkolnyApiException -> this.error?.toErrorCode()
else -> null else -> null
} }
private fun ApiResponse.Error.toErrorCode() = when (this.code) { fun ApiResponse.Error.toErrorCode() = when (this.code) {
"PdoError" -> ERROR_API_PDO_ERROR "PdoError" -> ERROR_API_PDO_ERROR
"InvalidClient" -> ERROR_API_INVALID_CLIENT "InvalidClient" -> ERROR_API_INVALID_CLIENT
"InvalidArgument" -> ERROR_API_INVALID_ARGUMENT "InvalidArgument" -> ERROR_API_INVALID_ARGUMENT

View File

@ -115,6 +115,11 @@ class Config(val db: AppDb) : CoroutineScope, AbstractConfig {
get() { mValidation = mValidation ?: values["buildValidation"]; return mValidation } get() { mValidation = mValidation ?: values["buildValidation"]; return mValidation }
set(value) { set("buildValidation", value); mValidation = value } 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<ConfigEntry> = db.configDao().getAllNow() private var rawEntries: List<ConfigEntry> = db.configDao().getAllNow()
private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf() private val profileConfigs: HashMap<Int, ProfileConfig> = hashMapOf()
init { init {

View File

@ -18,7 +18,9 @@ import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.ERROR_API_INVALID_SIGNATURE 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.DateAdapter
import pl.szczodrzynski.edziennik.data.api.szkolny.adapter.TimeAdapter 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.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.request.*
import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse
import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus 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() val okHttpClient: OkHttpClient = app.http.newBuilder()
.followRedirects(true) .followRedirects(true)
.callTimeout(10, SECONDS) .callTimeout(10, SECONDS)
.addInterceptor(ApiCacheInterceptor(app))
.addInterceptor(SignatureInterceptor(app)) .addInterceptor(SignatureInterceptor(app))
.build() .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()) throw SzkolnyApiException(body?.errors?.firstOrNull())
} }

View File

@ -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<Unit>(
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())
}
}