From 367f46fac8b6f99a8dddf49785eae246dee6676f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Fri, 21 Feb 2020 21:32:06 +0100 Subject: [PATCH] [API/Librus] Fix captcha showing as incorrect login error. Add handling CSRF error. --- .../pl/szczodrzynski/edziennik/Extensions.kt | 17 ++++++++--- .../edziennik/data/api/Errors.kt | 1 + .../data/api/edziennik/librus/Librus.kt | 1 + .../librus/login/LibrusLoginPortal.kt | 29 ++++++++++--------- app/src/main/res/values/errors.xml | 4 ++- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index 5f191b7f..e4ad829e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -94,8 +94,8 @@ fun JsonObject?.getInt(key: String): Int? = get(key)?.let { if (it.isJsonNull) n fun JsonObject?.getLong(key: String): Long? = get(key)?.let { if (it.isJsonNull) null else it.asLong } fun JsonObject?.getFloat(key: String): Float? = get(key)?.let { if(it.isJsonNull) null else it.asFloat } fun JsonObject?.getChar(key: String): Char? = get(key)?.let { if(it.isJsonNull) null else it.asCharacter } -fun JsonObject?.getJsonObject(key: String): JsonObject? = get(key)?.let { if (it.isJsonNull) null else it.asJsonObject } -fun JsonObject?.getJsonArray(key: String): JsonArray? = get(key)?.let { if (it.isJsonNull) null else it.asJsonArray } +fun JsonObject?.getJsonObject(key: String): JsonObject? = get(key)?.let { if (it.isJsonObject) it.asJsonObject else null } +fun JsonObject?.getJsonArray(key: String): JsonArray? = get(key)?.let { if (it.isJsonArray) it.asJsonArray else null } fun JsonObject?.getBoolean(key: String, defaultValue: Boolean): Boolean = get(key)?.let { if (it.isJsonNull) defaultValue else it.asBoolean } ?: defaultValue fun JsonObject?.getString(key: String, defaultValue: String): String = get(key)?.let { if (it.isJsonNull) defaultValue else it.asString } ?: defaultValue @@ -103,8 +103,17 @@ fun JsonObject?.getInt(key: String, defaultValue: Int): Int = get(key)?.let { if fun JsonObject?.getLong(key: String, defaultValue: Long): Long = get(key)?.let { if (it.isJsonNull) defaultValue else it.asLong } ?: defaultValue fun JsonObject?.getFloat(key: String, defaultValue: Float): Float = get(key)?.let { if(it.isJsonNull) defaultValue else it.asFloat } ?: defaultValue fun JsonObject?.getChar(key: String, defaultValue: Char): Char = get(key)?.let { if(it.isJsonNull) defaultValue else it.asCharacter } ?: defaultValue -fun JsonObject?.getJsonObject(key: String, defaultValue: JsonObject): JsonObject = get(key)?.let { if (it.isJsonNull) defaultValue else it.asJsonObject } ?: defaultValue -fun JsonObject?.getJsonArray(key: String, defaultValue: JsonArray): JsonArray = get(key)?.let { if (it.isJsonNull) defaultValue else it.asJsonArray } ?: defaultValue +fun JsonObject?.getJsonObject(key: String, defaultValue: JsonObject): JsonObject = get(key)?.let { if (it.isJsonObject) it.asJsonObject else defaultValue } ?: defaultValue +fun JsonObject?.getJsonArray(key: String, defaultValue: JsonArray): JsonArray = get(key)?.let { if (it.isJsonArray) it.asJsonArray else defaultValue } ?: defaultValue + +fun JsonArray.getBoolean(key: Int): Boolean? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asBoolean } +fun JsonArray.getString(key: Int): String? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asString } +fun JsonArray.getInt(key: Int): Int? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asInt } +fun JsonArray.getLong(key: Int): Long? = if (key >= size()) null else get(key)?.let { if (it.isJsonNull) null else it.asLong } +fun JsonArray.getFloat(key: Int): Float? = if (key >= size()) null else get(key)?.let { if(it.isJsonNull) null else it.asFloat } +fun JsonArray.getChar(key: Int): Char? = if (key >= size()) null else get(key)?.let { if(it.isJsonNull) null else it.asCharacter } +fun JsonArray.getJsonObject(key: Int): JsonObject? = if (key >= size()) null else get(key)?.let { if (it.isJsonObject) it.asJsonObject else null } +fun JsonArray.getJsonArray(key: Int): JsonArray? = if (key >= size()) null else get(key)?.let { if (it.isJsonArray) it.asJsonArray else null } operator fun JsonObject.set(key: String, value: JsonElement) = this.add(key, value) operator fun JsonObject.set(key: String, value: Boolean) = this.addProperty(key, value) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt index 7cb32555..27d1a529 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt @@ -122,6 +122,7 @@ const val ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN = 180 const val ERROR_LIBRUS_API_MAINTENANCE = 181 const val ERROR_LIBRUS_PORTAL_MAINTENANCE = 182 const val ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM = 183 +const val ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED = 184 const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201 const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/Librus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/Librus.kt index 8ef7d211..0e864f62 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/Librus.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/Librus.kt @@ -180,6 +180,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va } ERROR_LOGIN_LIBRUS_PORTAL_NO_CODE, ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING, + ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED, ERROR_LOGIN_LIBRUS_PORTAL_CODE_REVOKED, ERROR_LOGIN_LIBRUS_PORTAL_CODE_EXPIRED -> { login() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt index 68be8b72..fa667dc6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/login/LibrusLoginPortal.kt @@ -12,7 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.* import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus import pl.szczodrzynski.edziennik.data.api.models.ApiError import pl.szczodrzynski.edziennik.utils.Utils.d -import java.net.HttpURLConnection.HTTP_UNAUTHORIZED +import java.net.HttpURLConnection.* import java.util.* import java.util.regex.Pattern @@ -112,6 +112,8 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) { it.addParameter("g-recaptcha-response", recaptchaCode) } .addHeader("X-CSRF-TOKEN", csrfToken) + .allowErrorCode(HTTP_BAD_REQUEST) + .allowErrorCode(HTTP_FORBIDDEN) .contentType(MediaTypeUtils.APPLICATION_JSON) .post() .callback(object : JsonCallbackHandler() { @@ -140,22 +142,24 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) { .withApiResponse(json)) return } - if (json.get("errors") != null) { - data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR) - .withResponse(response) - .withApiResponse(json)) - return + val error = if (response.code() == 200) null else + json.getJsonArray("errors")?.getString(0) + error?.let { code -> + when { + code.contains("Sesja logowania wygasła") -> ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED + code.contains("Upewnij się, że nie") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN + else -> ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR + }.let { errorCode -> + data.error(ApiError(TAG, errorCode) + .withApiResponse(json) + .withResponse(response)) + return + } } authorize(json.getString("redirect", LIBRUS_AUTHORIZE_URL)) } override fun onFailure(response: Response, throwable: Throwable) { - if (response.code() == 403 || response.code() == 401) { - data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN) - .withResponse(response) - .withThrowable(throwable)) - return - } data.error(ApiError(TAG, ERROR_REQUEST_FAILURE) .withResponse(response) .withThrowable(throwable)) @@ -165,7 +169,6 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) { .enqueue() } - private var refreshTokenFailed = false private fun accessToken(code: String?, refreshToken: String?) { d(TAG, "Request: Librus/Login/Portal - ${if (data.fakeLogin) FAKE_LIBRUS_TOKEN else LIBRUS_TOKEN_URL}") diff --git a/app/src/main/res/values/errors.xml b/app/src/main/res/values/errors.xml index 602712d3..f9842e65 100644 --- a/app/src/main/res/values/errors.xml +++ b/app/src/main/res/values/errors.xml @@ -94,6 +94,7 @@ ERROR_LIBRUS_API_MAINTENANCE ERROR_LIBRUS_PORTAL_MAINTENANCE ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM + ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD @@ -264,6 +265,7 @@ Librus API: przerwa techniczna Librus Portal: przerwa techniczna Wystąpił problem z tablicą ogłoszeń + Librus: Sesja logowania wygasła. Zaloguj się ponownie. Nieprawidłowy login lub hasło Podano stare hasło @@ -335,7 +337,7 @@ EXCEPTION_MOBIDZIENNIK_WEB_FILE_REQUEST EXCEPTION_LIBRUS_MESSAGES_FILE_REQUEST EXCEPTION_NOTIFY - EXCEPTION_LIBRUS_MESSAGES_REQUEST + Zgłoś błąd: pobieranie wiadomości Librus EXCEPTION_IDZIENNIK_WEB_REQUEST EXCEPTION_IDZIENNIK_WEB_API_REQUEST EXCEPTION_IDZIENNIK_API_REQUEST