diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt index 2dff656b..a6a8ab76 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/Extensions.kt @@ -8,6 +8,7 @@ import android.os.Build import android.os.Bundle import androidx.core.app.ActivityCompat import com.google.gson.JsonArray +import com.google.gson.JsonElement import com.google.gson.JsonObject import pl.szczodrzynski.edziennik.datamodels.Profile import pl.szczodrzynski.edziennik.datamodels.Teacher @@ -21,19 +22,21 @@ fun List.byNameLastFirst(nameLastFirst: String) = firstOrNull { it.surn fun List.byNameFDotLast(nameFDotLast: String) = firstOrNull { it.name + "." + it.surname == nameFDotLast } fun List.byNameFDotSpaceLast(nameFDotSpaceLast: String) = firstOrNull { it.name + ". " + it.surname == nameFDotSpaceLast } -fun JsonObject.getBoolean(key: String): Boolean? = get(key)?.let { if (it.isJsonNull) null else it.asBoolean } -fun JsonObject.getString(key: String): String? = get(key)?.let { if (it.isJsonNull) null else it.asString } -fun JsonObject.getInt(key: String): Int? = get(key)?.let { if (it.isJsonNull) null else it.asInt } -fun JsonObject.getLong(key: String): Long? = get(key)?.let { if (it.isJsonNull) null else it.asLong } -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?.get(key: String): JsonElement? = this?.get(key) -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 -fun JsonObject.getInt(key: String, defaultValue: Int): Int = get(key)?.let { if (it.isJsonNull) defaultValue else it.asInt } ?: defaultValue -fun JsonObject.getLong(key: String, defaultValue: Long): Long = get(key)?.let { if (it.isJsonNull) defaultValue else it.asLong } ?: 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?.getBoolean(key: String): Boolean? = get(key)?.let { if (it.isJsonNull) null else it.asBoolean } +fun JsonObject?.getString(key: String): String? = get(key)?.let { if (it.isJsonNull) null else it.asString } +fun JsonObject?.getInt(key: String): Int? = get(key)?.let { if (it.isJsonNull) null else it.asInt } +fun JsonObject?.getLong(key: String): Long? = get(key)?.let { if (it.isJsonNull) null else it.asLong } +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?.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 +fun JsonObject?.getInt(key: String, defaultValue: Int): Int = get(key)?.let { if (it.isJsonNull) defaultValue else it.asInt } ?: defaultValue +fun JsonObject?.getLong(key: String, defaultValue: Long): Long = get(key)?.let { if (it.isJsonNull) defaultValue else it.asLong } ?: 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 CharSequence?.isNotNullNorEmpty(): Boolean { return this != null && this.isNotEmpty() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/AppError.java b/app/src/main/java/pl/szczodrzynski/edziennik/api/AppError.java index a22c8df8..2234783f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/AppError.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/AppError.java @@ -85,10 +85,10 @@ public class AppError { this(TAG, line, errorCode, null, null, null, throwable, apiResponse); } public AppError(String TAG, int line, int errorCode, Throwable throwable, JsonObject apiResponse) { - this(TAG, line, errorCode, null, null, null, throwable, apiResponse.toString()); + this(TAG, line, errorCode, null, null, null, throwable, apiResponse == null ? null : apiResponse.toString()); } public AppError(String TAG, int line, int errorCode, String errorText, Response response, JsonObject apiResponse) { - this(TAG, line, errorCode, errorText, response, response == null ? null : response.request(), null, apiResponse.toString()); + this(TAG, line, errorCode, errorText, response, response == null ? null : response.request(), null, apiResponse == null ? null : apiResponse.toString()); } public AppError(String TAG, int line, int errorCode, String errorText, Response response, String apiResponse) { this(TAG, line, errorCode, errorText, response, response == null ? null : response.request(), null, apiResponse); @@ -97,7 +97,7 @@ public class AppError { this(TAG, line, errorCode, errorText, null, null, null, apiResponse); } public AppError(String TAG, int line, int errorCode, String errorText, JsonObject apiResponse) { - this(TAG, line, errorCode, errorText, null, null, null, apiResponse.toString()); + this(TAG, line, errorCode, errorText, null, null, null, apiResponse == null ? null : apiResponse.toString()); } public AppError(String TAG, int line, int errorCode, String errorText) { this(TAG, line, errorCode, errorText, null, null, null, null); @@ -106,7 +106,7 @@ public class AppError { this(TAG, line, errorCode, null, null, null, null, apiResponse.toString()); } public AppError(String TAG, int line, int errorCode, Response response, Throwable throwable, JsonObject apiResponse) { - this(TAG, line, errorCode, null, response, response == null ? null : response.request(), throwable, apiResponse.toString()); + this(TAG, line, errorCode, null, response, response == null ? null : response.request(), throwable, apiResponse == null ? null : apiResponse.toString()); } public AppError(String TAG, int line, int errorCode, Response response, Throwable throwable, String apiResponse) { this(TAG, line, errorCode, null, response, response == null ? null : response.request(), throwable, apiResponse); @@ -115,7 +115,7 @@ public class AppError { this(TAG, line, errorCode, null, response, response == null ? null : response.request(), null, apiResponse); } public AppError(String TAG, int line, int errorCode, Response response, JsonObject apiResponse) { - this(TAG, line, errorCode, null, response, response == null ? null : response.request(), null, apiResponse.toString()); + this(TAG, line, errorCode, null, response, response == null ? null : response.request(), null, apiResponse == null ? null : apiResponse.toString()); } public String getDetails(Context context) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Constants.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Constants.kt index 047dd38f..b80d8494 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Constants.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Constants.kt @@ -27,8 +27,11 @@ const val LIBRUS_TOKEN_URL = "https://portal.librus.pl/oauth2/access_token" const val LIBRUS_ACCOUNT_URL = "https://portal.librus.pl/api/v2/SynergiaAccounts/fresh/" // + login const val LIBRUS_ACCOUNTS_URL = "https://portal.librus.pl/api/v2/SynergiaAccounts" -const val LIBRUS_API_URL = "https://api.librus.pl/2.0/" +/** https://api.librus.pl/2.0 */ +const val LIBRUS_API_URL = "https://api.librus.pl/2.0" +/** https://api.librus.pl/OAuth/Token */ const val LIBRUS_API_TOKEN_URL = "https://api.librus.pl/OAuth/Token" +/** https://api.librus.pl/OAuth/TokenJST */ const val LIBRUS_API_TOKEN_JST_URL = "https://api.librus.pl/OAuth/TokenJST" const val LIBRUS_API_AUTHORIZATION = "Mjg6ODRmZGQzYTg3YjAzZDNlYTZmZmU3NzdiNThiMzMyYjE=" const val LIBRUS_API_SECRET_JST = "18b7c1ee08216f636a1b1a2440e68398" @@ -38,7 +41,8 @@ const val LIBRUS_API_CLIENT_ID_JST = "49" const val LIBRUS_JST_DEMO_CODE = "68656A21" const val LIBRUS_JST_DEMO_PIN = "1290" -const val LIBRUS_SYNERGIA_TOKEN_LOGIN_URL = "https://synergia.librus.pl/loguj/token/\$token/przenies/" +/** https://synergia.librus.pl/loguj/token/TOKEN/przenies */ +const val LIBRUS_SYNERGIA_TOKEN_LOGIN_URL = "https://synergia.librus.pl/loguj/token/TOKEN/przenies/" const val LIBRUS_MESSAGES_URL = "https://wiadomosci.librus.pl/module/" const val LIBRUS_SANDBOX_URL = "https://sandbox.librus.pl/index.php?action=" \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Errors.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Errors.kt index 4f944965..4c89af8a 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Errors.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/Errors.kt @@ -4,38 +4,84 @@ package pl.szczodrzynski.edziennik.api.v2 -/*const val CODE_OTHER = 0 -const val CODE_OK = 1 -const val CODE_NO_INTERNET = 10 -const val CODE_SSL_ERROR = 13 -const val CODE_ARCHIVED = 5 -const val CODE_MAINTENANCE = 6 -const val CODE_LOGIN_ERROR = 7 -const val CODE_ACCOUNT_MISMATCH = 8 -const val CODE_APP_SERVER_ERROR = 9 -const val CODE_MULTIACCOUNT_SETUP = 12 -const val CODE_TIMEOUT = 11 -const val CODE_PROFILE_NOT_FOUND = 14 -const val CODE_ATTACHMENT_NOT_AVAILABLE = 28 -const val CODE_INVALID_LOGIN = 2 -const val CODE_INVALID_SERVER_ADDRESS = 21 -const val CODE_INVALID_SCHOOL_NAME = 22 -const val CODE_INVALID_DEVICE = 23 -const val CODE_OLD_PASSWORD = 4 -const val CODE_INVALID_TOKEN = 24 -const val CODE_EXPIRED_TOKEN = 27 -const val CODE_INVALID_SYMBOL = 25 -const val CODE_INVALID_PIN = 26 -const val CODE_LIBRUS_NOT_ACTIVATED = 29 -const val CODE_SYNERGIA_NOT_ACTIVATED = 32 -const val CODE_LIBRUS_DISCONNECTED = 31 -const val CODE_PROFILE_ARCHIVED = 30*/ -const val CODE_INVALID_LOGIN_MODE = 130 -const val CODE_INTERNAL_MISSING_DATA = 100 -const val CODE_INTERNAL_LIBRUS_ACCOUNT_410 = 120 -const val CODE_INTERNAL_LIBRUS_SYNERGIA_EXPIRED = 121 -const val CODE_LOGIN_METHOD_NOT_SATISFIED = 122 -const val CODE_LIBRUS_PROFILE_NULL = 123 -const val ERROR_LOGIN_LIBRUS_API_CAPTCHA_NEEDED = 124 +/*const val CODE_OTHER = 0 +const val CODE_OK = 1 +const val CODE_NO_INTERNET = 10 +const val CODE_SSL_ERROR = 13 +const val CODE_ARCHIVED = 5 +const val CODE_MAINTENANCE = 6 +const val CODE_LOGIN_ERROR = 7 +const val CODE_ACCOUNT_MISMATCH = 8 +const val CODE_APP_SERVER_ERROR = 9 +const val CODE_MULTIACCOUNT_SETUP = 12 +const val CODE_TIMEOUT = 11 +const val CODE_PROFILE_NOT_FOUND = 14 +const val CODE_ATTACHMENT_NOT_AVAILABLE = 28 +const val CODE_INVALID_LOGIN = 2 +const val CODE_INVALID_SERVER_ADDRESS = 21 +const val CODE_INVALID_SCHOOL_NAME = 22 +const val CODE_INVALID_DEVICE = 23 +const val CODE_OLD_PASSWORD = 4 +const val CODE_INVALID_TOKEN = 24 +const val CODE_EXPIRED_TOKEN = 27 +const val CODE_INVALID_SYMBOL = 25 +const val CODE_INVALID_PIN = 26 +const val CODE_LIBRUS_NOT_ACTIVATED = 29 +const val CODE_SYNERGIA_NOT_ACTIVATED = 32 +const val CODE_LIBRUS_DISCONNECTED = 31 +const val CODE_PROFILE_ARCHIVED = 30*/ -const val EXCEPTION_LOGIN_LIBRUS_API_TOKEN = 901 \ No newline at end of file +const val ERROR_REQUEST_FAILURE = 50 +const val ERROR_REQUEST_HTTP_400 = 51 +const val ERROR_REQUEST_HTTP_401 = 52 +const val ERROR_REQUEST_HTTP_403 = 53 +const val ERROR_REQUEST_HTTP_404 = 54 +const val ERROR_REQUEST_HTTP_405 = 55 +const val ERROR_REQUEST_HTTP_410 = 56 +const val ERROR_REQUEST_HTTP_500 = 57 +const val ERROR_RESPONSE_EMPTY = 100 +const val ERROR_LOGIN_DATA_MISSING = 101 +const val ERROR_LOGIN_DATA_INVALID = 102 +const val ERROR_PROFILE_MISSING = 105 +const val ERROR_INVALID_LOGIN_MODE = 110 +const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111 + +const val CODE_INTERNAL_LIBRUS_ACCOUNT_410 = 120 +const val CODE_INTERNAL_LIBRUS_SYNERGIA_EXPIRED = 121 +const val ERROR_LOGIN_LIBRUS_API_CAPTCHA_NEEDED = 124 +const val ERROR_LOGIN_LIBRUS_API_CONNECTION_PROBLEMS = 125 +const val ERROR_LOGIN_LIBRUS_API_INVALID_CLIENT = 126 +const val ERROR_LOGIN_LIBRUS_API_REG_ACCEPT_NEEDED = 127 +const val ERROR_LOGIN_LIBRUS_API_CHANGE_PASSWORD_ERROR = 128 +const val ERROR_LOGIN_LIBRUS_API_PASSWORD_CHANGE_REQUIRED = 129 +const val ERROR_LOGIN_LIBRUS_API_INVALID_GRANT = 130 +const val ERROR_LOGIN_LIBRUS_API_OTHER = 131 +const val ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING = 132 +const val ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED = 133 +const val ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR = 134 +const val ERROR_LOGIN_LIBRUS_PORTAL_TOKEN_ERROR = 135 +const val ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_DISCONNECTED = 136 +const val ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_410 = 137 +const val ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_NOT_FOUND = 138 +const val ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_OTHER = 139 +const val ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_TOKEN_MISSING = 139 +const val ERROR_LIBRUS_API_TOKEN_EXPIRED = 140 +const val ERROR_LIBRUS_API_INSUFFICIENT_SCOPES = 141 +const val ERROR_LIBRUS_API_OTHER = 142 +const val ERROR_LIBRUS_API_REQUEST_DENIED = 143 +const val ERROR_LIBRUS_API_RESOURCE_NOT_FOUND = 144 +const val ERROR_LIBRUS_API_DATA_NOT_FOUND = 145 +const val ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC = 146 +const val ERROR_LIBRUS_API_RESOURCE_ACCESS_DENIED = 147 +const val ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS = 148 +const val ERROR_LIBRUS_API_INCORRECT_ENDPOINT = 149 +const val ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE = 150 +const val ERROR_LIBRUS_API_NOTES_NOT_ACTIVE = 151 +const val ERROR_LOGIN_LIBRUS_SYNERGIA_NO_TOKEN = 152 +const val ERROR_LOGIN_LIBRUS_SYNERGIA_TOKEN_INVALID = 153 +const val ERROR_LOGIN_LIBRUS_SYNERGIA_NO_SESSION_ID = 154 + +const val EXCEPTION_LOGIN_LIBRUS_API_TOKEN = 901 +const val EXCEPTION_LOGIN_LIBRUS_PORTAL_TOKEN = 902 +const val EXCEPTION_LOGIN_LIBRUS_PORTAL_SYNERGIA_TOKEN = 903 +const val EXCEPTION_LIBRUS_API_REQUEST = 904 \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/LibrusTest.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/LibrusTest.kt index 592423b3..bb009d86 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/LibrusTest.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/LibrusTest.kt @@ -23,17 +23,17 @@ class LibrusTest(val app: App) { } val profile = Profile(1, "Profil", "xd", 1).apply { - //putStudentData("accountLogin", "1234567") + putStudentData("accountLogin", "1234567") //putStudentData("accountPassword", "zaq1@WSX") - putStudentData("accountCode", LIBRUS_JST_DEMO_CODE) - putStudentData("accountPin", LIBRUS_JST_DEMO_PIN) + //putStudentData("accountCode", LIBRUS_JST_DEMO_CODE) + //putStudentData("accountPin", LIBRUS_JST_DEMO_PIN) } val loginStore = LoginStore(1, LOGIN_TYPE_LIBRUS, JsonObject().apply { addProperty("email", "test@example.com") addProperty("password", "zaq1@WSX") }).also { - it.mode = LOGIN_MODE_LIBRUS_JST + it.mode = LOGIN_MODE_LIBRUS_EMAIL } fun go() { @@ -54,7 +54,7 @@ class LibrusTest(val app: App) { } } - LoginLibrus(data, LOGIN_METHOD_LIBRUS_API) { + LoginLibrus(data, LOGIN_METHOD_LIBRUS_SYNERGIA) { d(TAG, "Login succeeded.") d(TAG, "Profile data: ${data.profile?.studentData?.toString()}") d(TAG, "LoginStore data: ${data.loginStore.data}") diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/DataLibrus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/DataLibrus.kt index 61ede774..d7437d77 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/DataLibrus.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/DataLibrus.kt @@ -49,6 +49,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app /** * A Synergia login, like 1234567u. * Used: for login (API Login Method) in Synergia mode. + * Used: for login (Synergia Login Method) in Synergia mode. * And also in various places in [pl.szczodrzynski.edziennik.api.v2.models.Endpoint]s */ private var mApiLogin: String? = null @@ -58,6 +59,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app /** * A Synergia password. * Used: for login (API Login Method) in Synergia mode. + * Used: for login (Synergia Login Method) in Synergia mode. */ private var mApiPassword: String? = null var apiPassword: String? @@ -109,6 +111,32 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app get() { mApiTokenExpiryTime = mApiTokenExpiryTime ?: profile?.getStudentData("accountTokenTime", 0L); return mApiTokenExpiryTime ?: 0L } set(value) { profile?.putStudentData("accountTokenTime", value) ?: return; mApiTokenExpiryTime = value } + /* _____ _ + / ____| (_) + | (___ _ _ _ __ ___ _ __ __ _ _ __ _ + \___ \| | | | '_ \ / _ \ '__/ _` | |/ _` | + ____) | |_| | | | | __/ | | (_| | | (_| | + |_____/ \__, |_| |_|\___|_| \__, |_|\__,_| + __/ | __/ | + |___/ |__*/ + /** + * A Synergia web Session ID (DZIENNIKSID). + * Used in endpoints with Synergia login method. + */ + private var mSynergiaSessionId: String? = null + var synergiaSessionId: String? + get() { mSynergiaSessionId = mSynergiaSessionId ?: profile?.getStudentData("accountSID", null); return mSynergiaSessionId } + set(value) { profile?.putStudentData("accountSID", value) ?: return; mSynergiaSessionId = value } + /** + * The expiry time for [synergiaSessionId], as a UNIX timestamp. + * Used in endpoints with Synergia login method. + * TODO verify how long is the session ID valid. + */ + private var mSynergiaSessionIdExpiryTime: Long? = null + var synergiaSessionIdExpiryTime: Long + get() { mSynergiaSessionIdExpiryTime = mSynergiaSessionIdExpiryTime ?: profile?.getStudentData("accountSIDTime", 0L); return mSynergiaSessionIdExpiryTime ?: 0L } + set(value) { profile?.putStudentData("accountSIDTime", value) ?: return; mSynergiaSessionIdExpiryTime = value } + /* ____ _ _ / __ \| | | | | | | | |_| |__ ___ _ __ diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusApi.kt index 3720b212..c95dc929 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusApi.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/data/LibrusApi.kt @@ -24,9 +24,9 @@ open class LibrusApi(override val data: DataLibrus) : Api(data) { const val TAG = "LibrusApi" } fun apiRequest(endpoint: String, callback: (json: JsonObject?) -> Unit) { - d(TAG, "Requesting $LIBRUS_API_URL$endpoint") + d(TAG, "Requesting $LIBRUS_API_URL/$endpoint") Request.builder() - .url(if (data.fakeLogin) "http://szkolny.eu/librus/api/$endpoint" else LIBRUS_API_URL + endpoint) + .url(if (data.fakeLogin) "http://szkolny.eu/librus/api/$endpoint" else "$LIBRUS_API_URL/$endpoint") .userAgent(LIBRUS_USER_AGENT) .addHeader("Authorization", "Bearer ${data.apiAccessToken}") .get() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrus.kt index e16ada31..b79c09c1 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrus.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrus.kt @@ -63,7 +63,7 @@ class LoginLibrus(val data: DataLibrus, vararg loginMethodIds: Int, val onSucces } } LOGIN_METHOD_LIBRUS_SYNERGIA -> { - LoginLibrusApi(data) { + LoginLibrusSynergia(data) { data.loginMethods.add(loginMethodId) onSuccess() } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusApi.kt index ef6da7d5..3166f211 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusApi.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusApi.kt @@ -17,7 +17,6 @@ import pl.szczodrzynski.edziennik.currentTimeUnix import pl.szczodrzynski.edziennik.getInt import pl.szczodrzynski.edziennik.getString import pl.szczodrzynski.edziennik.isNotNullNorEmpty -import java.net.HttpURLConnection import java.net.HttpURLConnection.* class LoginLibrusApi { @@ -28,12 +27,13 @@ class LoginLibrusApi { private lateinit var data: DataLibrus private lateinit var onSuccess: () -> Unit + /* do NOT move this to primary constructor */ constructor(data: DataLibrus, onSuccess: () -> Unit) { this.data = data this.onSuccess = onSuccess if (data.profile == null) { - data.callback.onError(null, AppError(TAG, 19, CODE_LIBRUS_PROFILE_NULL)) + data.error(TAG, ERROR_PROFILE_MISSING) return } @@ -46,7 +46,7 @@ class LoginLibrusApi { LOGIN_MODE_LIBRUS_SYNERGIA -> loginWithSynergia() LOGIN_MODE_LIBRUS_JST -> loginWithJst() else -> { - data.callback.onError(null, AppError(TAG, 25, CODE_INVALID_LOGIN_MODE)) + data.error(TAG, ERROR_INVALID_LOGIN_MODE) } } } @@ -54,7 +54,7 @@ class LoginLibrusApi { private fun loginWithPortal() { if (!data.loginMethods.contains(LOGIN_METHOD_LIBRUS_PORTAL)) { - data.callback.onError(null, AppError(TAG, 26, CODE_LOGIN_METHOD_NOT_SATISFIED)) + data.error(TAG, ERROR_LOGIN_METHOD_NOT_SATISFIED) return } SynergiaTokenExtractor(data) { @@ -94,7 +94,7 @@ class LoginLibrusApi { } else { // cannot log in: token expired, no login data present - data.callback.onError(null, AppError(TAG, 91, CODE_INVALID_LOGIN)) + data.error(TAG, ERROR_LOGIN_DATA_MISSING) } } @@ -111,44 +111,30 @@ class LoginLibrusApi { } else { // cannot log in: token expired, no login data present - data.callback.onError(null, AppError(TAG, 110, CODE_INVALID_LOGIN)) + data.error(TAG, ERROR_LOGIN_DATA_MISSING) } } private val tokenCallback = object : JsonCallbackHandler() { override fun onSuccess(json: JsonObject?, response: Response?) { if (json == null) { - data.callback.onError(null, AppError(TAG, 117, CODE_MAINTENANCE, response)) + data.error(TAG, ERROR_RESPONSE_EMPTY, response) return } json.getString("error")?.let { error -> when (error) { - "librus_captcha_needed" -> { - - } - "connection_problems" -> { - - } - "invalid_client" -> { - - } - "librus_reg_accept_needed" -> { - - } - "librus_change_password_error" -> { - - } - "librus_password_change_required" -> { - - } - "invalid_grant" -> { - - } - else -> { - - } + "librus_captcha_needed" -> ERROR_LOGIN_LIBRUS_API_CAPTCHA_NEEDED + "connection_problems" -> ERROR_LOGIN_LIBRUS_API_CONNECTION_PROBLEMS + "invalid_client" -> ERROR_LOGIN_LIBRUS_API_INVALID_CLIENT + "librus_reg_accept_needed" -> ERROR_LOGIN_LIBRUS_API_REG_ACCEPT_NEEDED + "librus_change_password_error" -> ERROR_LOGIN_LIBRUS_API_CHANGE_PASSWORD_ERROR + "librus_password_change_required" -> ERROR_LOGIN_LIBRUS_API_PASSWORD_CHANGE_REQUIRED + "invalid_grant" -> ERROR_LOGIN_LIBRUS_API_INVALID_GRANT + else -> ERROR_LOGIN_LIBRUS_API_OTHER + }.let { errorCode -> + data.error(TAG, errorCode, apiResponse = json, response = response) + return } - return } try { @@ -157,12 +143,12 @@ class LoginLibrusApi { data.apiTokenExpiryTime = currentTimeUnix() + json.getInt("expires_in", 86400) onSuccess() } catch (e: NullPointerException) { - data.callback.onError(null, AppError(TAG, 154, EXCEPTION_LOGIN_LIBRUS_API_TOKEN, response, e, json)) + data.error(TAG, EXCEPTION_LOGIN_LIBRUS_API_TOKEN, response, e, json) } } override fun onFailure(response: Response?, throwable: Throwable?) { - data.callback.onError(null, AppError(TAG, 159, CODE_OTHER, response, throwable)) + data.error(TAG, ERROR_REQUEST_FAILURE, response, throwable) } } @@ -179,7 +165,6 @@ class LoginLibrusApi { .contentType(MediaTypeUtils.APPLICATION_FORM) .post() .allowErrorCode(HTTP_BAD_REQUEST) - .allowErrorCode(HTTP_FORBIDDEN) .allowErrorCode(HTTP_UNAUTHORIZED) .callback(tokenCallback) .build() @@ -197,7 +182,6 @@ class LoginLibrusApi { .contentType(MediaTypeUtils.APPLICATION_FORM) .post() .allowErrorCode(HTTP_BAD_REQUEST) - .allowErrorCode(HTTP_FORBIDDEN) .allowErrorCode(HTTP_UNAUTHORIZED) .callback(tokenCallback) .build() @@ -218,7 +202,6 @@ class LoginLibrusApi { .contentType(MediaTypeUtils.APPLICATION_FORM) .post() .allowErrorCode(HTTP_BAD_REQUEST) - .allowErrorCode(HTTP_FORBIDDEN) .allowErrorCode(HTTP_UNAUTHORIZED) .callback(tokenCallback) .build() @@ -237,7 +220,6 @@ class LoginLibrusApi { .contentType(MediaTypeUtils.APPLICATION_FORM) .post() .allowErrorCode(HTTP_BAD_REQUEST) - .allowErrorCode(HTTP_FORBIDDEN) .allowErrorCode(HTTP_UNAUTHORIZED) .callback(tokenCallback) .build() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusPortal.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusPortal.kt index e0d5c309..242d5596 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusPortal.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusPortal.kt @@ -24,11 +24,11 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) { init { run { if (data.loginStore.mode != LOGIN_MODE_LIBRUS_EMAIL) { - data.callback.onError(null, AppError(TAG, 27, CODE_INVALID_LOGIN_MODE)) + data.error(TAG, ERROR_INVALID_LOGIN_MODE) return@run } if (data.portalEmail == null || data.portalPassword == null) { - data.callback.onError(null, AppError(TAG, 31, CODE_INVALID_LOGIN)) + data.error(TAG, ERROR_LOGIN_DATA_MISSING) return@run } @@ -67,13 +67,13 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) { if (csrfMatcher.find()) { login(csrfMatcher.group(1)) } else { - data.callback.onError(null, AppError(TAG, 463, CODE_OTHER, "CSRF token not found.", response, json)) + data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_CSRF_MISSING, response, json) } } } override fun onFailure(response: Response, throwable: Throwable) { - data.callback.onError(null, AppError(TAG, 207, CODE_OTHER, response, throwable)) + data.error(TAG, ERROR_REQUEST_FAILURE, response, throwable) } }) .build() @@ -94,14 +94,14 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) { override fun onSuccess(json: JsonObject?, response: Response) { if (json == null) { if (response.parserErrorBody?.contains("wciąż nieaktywne") == true) { - data.callback.onError(null, AppError(TAG, 487, CODE_LIBRUS_NOT_ACTIVATED, response)) + data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED, response) return } - data.callback.onError(null, AppError(TAG, 489, CODE_MAINTENANCE, response)) + data.error(TAG, ERROR_RESPONSE_EMPTY, response) return } if (json.get("errors") != null) { - data.callback.onError(null, AppError(TAG, 490, CODE_OTHER, json.getJsonArray("errors")?.get(0)?.asString, response, json)) + data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR, response, apiResponse = json) return } authorize(json.getString("redirect", LIBRUS_AUTHORIZE_URL)) @@ -109,10 +109,10 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) { override fun onFailure(response: Response, throwable: Throwable) { if (response.code() == 403 || response.code() == 401) { - data.callback.onError(null, AppError(TAG, 248, CODE_INVALID_LOGIN, response, throwable)) + data.error(TAG, ERROR_LOGIN_DATA_INVALID, response, throwable) return } - data.callback.onError(null, AppError(TAG, 251, CODE_OTHER, response, throwable)) + data.error(TAG, ERROR_REQUEST_FAILURE, response, throwable) } }) .build() @@ -141,20 +141,19 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) { .callback(object : JsonCallbackHandler() { override fun onSuccess(json: JsonObject?, response: Response) { if (json == null) { - data.callback.onError(null, AppError(TAG, 539, CODE_MAINTENANCE, response)) + data.error(TAG, ERROR_RESPONSE_EMPTY, response) return } json.getString("error")?.let { error -> val hint = json.getString("hint", "") - val message = json.getString("message", "") + //val message = json.getString("message", "") if (!refreshTokenFailed && refreshToken != null && (hint == "Token has been revoked" || hint == "Token has expired")) { c(TAG, "refreshing the token failed. Trying to log in again.") refreshTokenFailed = true authorize(LIBRUS_AUTHORIZE_URL) return } - val errorText = "$error $message $hint" - data.callback.onError(null, AppError(TAG, 552, CODE_OTHER, errorText, response, json)) + data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_TOKEN_ERROR, response, apiResponse = json) return } @@ -164,13 +163,13 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) { data.portalTokenExpiryTime = currentTimeUnix() + json.getInt("expires_in", 86400) onSuccess() } catch (e: NullPointerException) { - data.callback.onError(null, AppError(TAG, 311, CODE_OTHER, response, e, json)) + data.error(TAG, EXCEPTION_LOGIN_LIBRUS_PORTAL_TOKEN, response, e, json) } } override fun onFailure(response: Response, throwable: Throwable) { - data.callback.onError(null, AppError(TAG, 317, CODE_OTHER, response, throwable)) + data.error(TAG, ERROR_REQUEST_FAILURE, response, throwable) } }) .build() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusSynergia.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusSynergia.kt index 2bad6904..0134347d 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusSynergia.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/LoginLibrusSynergia.kt @@ -4,5 +4,175 @@ package pl.szczodrzynski.edziennik.api.v2.librus.login -class LoginLibrusSynergia { +import com.google.gson.JsonObject +import im.wangchao.mhttp.Request +import im.wangchao.mhttp.Response +import im.wangchao.mhttp.body.MediaTypeUtils +import im.wangchao.mhttp.callback.JsonCallbackHandler +import im.wangchao.mhttp.callback.TextCallbackHandler +import okhttp3.HttpUrl +import pl.szczodrzynski.edziennik.api.v2.* +import pl.szczodrzynski.edziennik.api.v2.librus.data.DataLibrus +import pl.szczodrzynski.edziennik.currentTimeUnix +import pl.szczodrzynski.edziennik.getString +import pl.szczodrzynski.edziennik.isNotNullNorEmpty +import java.lang.Exception +import java.net.HttpURLConnection + +class LoginLibrusSynergia(val data: DataLibrus, val onSuccess: () -> Unit) { + companion object { + private const val TAG = "LoginLibrusSynergia" + } + + init { run { + if (data.profile == null) { + data.error(TAG, ERROR_PROFILE_MISSING) + return@run + } + + if (data.synergiaSessionIdExpiryTime-30 > currentTimeUnix() && data.synergiaSessionId.isNotNullNorEmpty()) { + onSuccess() + } + else { + when (data.loginStore.mode) { + LOGIN_MODE_LIBRUS_SYNERGIA -> loginWithSynergia() + else -> { + loginWithApi() + } + } + } + }} + + /** + * HTML form-based login method. Uses a Synergia login and password. + */ + private fun loginWithSynergia() { + if (data.apiLogin == null || data.apiPassword == null) { + data.error(TAG, ERROR_LOGIN_DATA_MISSING) + return + } + + } + + /** + * A login method using the Synergia API (AutoLoginToken endpoint). + */ + private fun loginWithApi() { + if (!data.loginMethods.contains(LOGIN_METHOD_LIBRUS_API)) { + data.error(TAG, ERROR_LOGIN_METHOD_NOT_SATISFIED) + return + } + + val onSuccess = { json: JsonObject -> + loginWithToken(json.getString("Token")) + } + + val callback = object : JsonCallbackHandler() { + override fun onSuccess(json: JsonObject?, response: Response?) { + if (json == null && response?.parserErrorBody == null) { + data.error(TAG, ERROR_RESPONSE_EMPTY, response) + return + } + val error = json.getString("Code") ?: json.getString("Message") ?: response?.parserErrorBody + error?.let { code -> + when (code) { + "TokenIsExpired" -> ERROR_LIBRUS_API_TOKEN_EXPIRED + "Insufficient scopes" -> ERROR_LIBRUS_API_INSUFFICIENT_SCOPES + "Request is denied" -> ERROR_LIBRUS_API_REQUEST_DENIED + "Resource not found" -> ERROR_LIBRUS_API_RESOURCE_NOT_FOUND + "NotFound" -> ERROR_LIBRUS_API_DATA_NOT_FOUND + "AccessDeny" -> when (json.getString("Message")) { + "Student timetable is not public" -> ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC + else -> ERROR_LIBRUS_API_RESOURCE_ACCESS_DENIED + } + "LuckyNumberIsNotActive" -> ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE + "NotesIsNotActive" -> ERROR_LIBRUS_API_NOTES_NOT_ACTIVE + "InvalidRequest" -> ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS + "Nieprawidłowy węzeł." -> ERROR_LIBRUS_API_INCORRECT_ENDPOINT + else -> ERROR_LIBRUS_API_OTHER + }.let { errorCode -> + data.error(TAG, errorCode, apiResponse = json, response = response) + return + } + } + + if (json == null) { + data.error(TAG, ERROR_RESPONSE_EMPTY, response) + return + } + + try { + onSuccess(json) + } catch (e: Exception) { + data.error(TAG, EXCEPTION_LIBRUS_API_REQUEST, response, e, json) + } + } + + override fun onFailure(response: Response?, throwable: Throwable?) { + // TODO add hotfix for Classrooms 500 + data.error(TAG, ERROR_REQUEST_FAILURE, response, throwable) + } + } + + Request.builder() + .url("$LIBRUS_API_URL/AutoLoginToken") + .userAgent(LIBRUS_USER_AGENT) + .addHeader("Authorization", "Bearer ${data.apiAccessToken}") + .post() + .allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST) + .allowErrorCode(HttpURLConnection.HTTP_FORBIDDEN) + .allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED) + .callback(callback) + .build() + .enqueue() + } + + private fun loginWithToken(token: String?) { + if (token == null) { + data.error(TAG, ERROR_LOGIN_LIBRUS_SYNERGIA_NO_TOKEN) + return + } + + val callback = object : TextCallbackHandler() { + override fun onSuccess(json: String?, response: Response?) { + val location = response?.headers()?.get("Location") + if (location?.endsWith("centrum_powiadomien") == true) { + val cookieList = data.app.cookieJar.loadForRequest(HttpUrl.get("https://synergia.librus.pl")) + var sessionId: String? = null + for (cookie in cookieList) { + if (cookie.name().equals("DZIENNIKSID", ignoreCase = true)) { + sessionId = cookie.value() + } + } + if (sessionId == null) { + data.error(TAG, ERROR_LOGIN_LIBRUS_SYNERGIA_NO_SESSION_ID, response, json) + return + } + data.synergiaSessionId = sessionId + data.synergiaSessionIdExpiryTime = currentTimeUnix() + 3600 /* 1h */ + onSuccess() + } + else { + data.error(TAG, ERROR_LOGIN_LIBRUS_SYNERGIA_TOKEN_INVALID, response, json) + } + } + + override fun onFailure(response: Response?, throwable: Throwable?) { + data.error(TAG, ERROR_REQUEST_FAILURE, response, throwable) + } + } + + data.app.cookieJar.clearForDomain("synergia.librus.pl") + Request.builder() + .url(LIBRUS_SYNERGIA_TOKEN_LOGIN_URL.replace("TOKEN", token) + "/uczen/widok/centrum_powiadomien") + .userAgent(LIBRUS_USER_AGENT) + .get() + .allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST) + .allowErrorCode(HttpURLConnection.HTTP_FORBIDDEN) + .allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED) + .callback(callback) + .withClient(data.app.httpLazy) + .build() + .enqueue() + } } \ No newline at end of file diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/SynergiaTokenExtractor.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/SynergiaTokenExtractor.kt index 80f26158..f771afde 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/SynergiaTokenExtractor.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/librus/login/SynergiaTokenExtractor.kt @@ -15,16 +15,16 @@ import java.net.HttpURLConnection.* class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) { companion object { - private const val TAG = "librus.SynergiaToken" + private const val TAG = "SynergiaTokenExtractor" } init { run { if (data.loginStore.mode != LOGIN_MODE_LIBRUS_EMAIL) { - data.callback.onError(null, AppError(TAG, 23, CODE_INVALID_LOGIN_MODE)) + data.error(TAG, ERROR_INVALID_LOGIN_MODE) return@run } if (data.profile == null) { - data.callback.onError(null, AppError(TAG, 28, CODE_LIBRUS_PROFILE_NULL)) + data.error(TAG, ERROR_PROFILE_MISSING) return@run } @@ -32,7 +32,9 @@ class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) { onSuccess() } else { - synergiaAccount() + if (!synergiaAccount()) { + + } } }} @@ -54,25 +56,25 @@ class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) { .callback(object : JsonCallbackHandler() { override fun onSuccess(json: JsonObject?, response: Response) { if (json == null) { - data.callback.onError(null, AppError(TAG, 641, CODE_MAINTENANCE, response)) + data.error(TAG, ERROR_RESPONSE_EMPTY, response) return } if (response.code() == 410) { val reason = json.get("reason") if (reason != null && reason !is JsonNull && reason.asString == "requires_an_action") { - data.callback.onError(null, AppError(TAG, 1078, CODE_LIBRUS_DISCONNECTED, response, json)) + data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_DISCONNECTED, response, apiResponse = json) return } - data.callback.onError(null, AppError(TAG, 70, CODE_INTERNAL_LIBRUS_ACCOUNT_410)) + data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_410, response, apiResponse = json) return } if (json.get("message") != null) { val message = json.get("message").asString if (message == "Account not found") { - data.callback.onError(null, AppError(TAG, 651, CODE_OTHER, data.app.getString(R.string.sync_error_register_student_not_associated_format, data.profile?.studentNameLong ?: "", accountLogin), response, json)) + data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_NOT_FOUND, response, apiResponse = json) return } - data.callback.onError(null, AppError(TAG, 654, CODE_OTHER, message + "\n\n" + accountLogin, response, json)) + data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_OTHER, response, apiResponse = json) return } if (response.code() == HTTP_OK) { @@ -81,7 +83,7 @@ class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) { val accountId = json.getInt("id") val accountToken = json.getString("accessToken") if (accountId == null || accountToken == null) { - data.callback.onError(null, AppError(TAG, 1284, CODE_OTHER, json)) + data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_SYNERGIA_TOKEN_MISSING, response, apiResponse = json) return } data.apiAccessToken = accountToken @@ -92,16 +94,16 @@ class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) { onSuccess() } catch (e: NullPointerException) { e.printStackTrace() - data.callback.onError(null, AppError(TAG, 662, CODE_OTHER, response, e, json)) + data.error(TAG, EXCEPTION_LOGIN_LIBRUS_PORTAL_SYNERGIA_TOKEN, response, e, json) } } else { - data.callback.onError(null, AppError(TAG, 425, CODE_OTHER, response, json)) + data.error(TAG, ERROR_REQUEST_FAILURE, response, apiResponse = json) } } override fun onFailure(response: Response, throwable: Throwable) { - data.callback.onError(null, AppError(TAG, 432, CODE_OTHER, response, throwable)) + data.error(TAG, ERROR_REQUEST_FAILURE, response, throwable) } }) .build() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/models/Data.kt b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/models/Data.kt index 7578c64d..edca2ce6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/models/Data.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/api/v2/models/Data.kt @@ -3,7 +3,10 @@ package pl.szczodrzynski.edziennik.api.v2.models import android.util.LongSparseArray import androidx.core.util.forEach import androidx.core.util.isNotEmpty +import com.google.gson.JsonObject +import im.wangchao.mhttp.Response import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.api.AppError import pl.szczodrzynski.edziennik.api.interfaces.ProgressCallback import pl.szczodrzynski.edziennik.datamodels.* import pl.szczodrzynski.edziennik.models.Date @@ -14,6 +17,12 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) lateinit var callback: ProgressCallback + /** + * A list of [LoginMethod]s *already fulfilled* during this sync. + * + * A [LoginMethod] may add elements to this list only after a successful login + * with that method. + */ val loginMethods = mutableListOf() val teacherList = LongSparseArray() @@ -133,4 +142,11 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore) if (messageMetadataList.isNotEmpty()) db.metadataDao().setSeen(messageMetadataList) } + + fun error(tag: String, errorCode: Int, response: Response? = null, throwable: Throwable? = null, apiResponse: JsonObject? = null) { + callback.onError(null, AppError(tag, 999, errorCode, response, throwable, apiResponse)) + } + fun error(tag: String, errorCode: Int, response: Response? = null, apiResponse: String? = null) { + callback.onError(null, AppError(tag, 999, errorCode, response, null, apiResponse)) + } } \ No newline at end of file