mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-01-31 05:48:19 +01:00
[APIv2/Librus] Add Librus Synergia login method. Update structure and error handling.
This commit is contained in:
parent
76d39ac623
commit
a785db4d47
@ -8,6 +8,7 @@ import android.os.Build
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import com.google.gson.JsonArray
|
import com.google.gson.JsonArray
|
||||||
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import pl.szczodrzynski.edziennik.datamodels.Profile
|
import pl.szczodrzynski.edziennik.datamodels.Profile
|
||||||
import pl.szczodrzynski.edziennik.datamodels.Teacher
|
import pl.szczodrzynski.edziennik.datamodels.Teacher
|
||||||
@ -21,19 +22,21 @@ fun List<Teacher>.byNameLastFirst(nameLastFirst: String) = firstOrNull { it.surn
|
|||||||
fun List<Teacher>.byNameFDotLast(nameFDotLast: String) = firstOrNull { it.name + "." + it.surname == nameFDotLast }
|
fun List<Teacher>.byNameFDotLast(nameFDotLast: String) = firstOrNull { it.name + "." + it.surname == nameFDotLast }
|
||||||
fun List<Teacher>.byNameFDotSpaceLast(nameFDotSpaceLast: String) = firstOrNull { it.name + ". " + it.surname == nameFDotSpaceLast }
|
fun List<Teacher>.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?.get(key: String): JsonElement? = this?.get(key)
|
||||||
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?.getBoolean(key: String): Boolean? = get(key)?.let { if (it.isJsonNull) null else it.asBoolean }
|
||||||
fun JsonObject.getString(key: String, defaultValue: String): String = get(key)?.let { if (it.isJsonNull) defaultValue else it.asString } ?: defaultValue
|
fun JsonObject?.getString(key: String): String? = get(key)?.let { if (it.isJsonNull) null else it.asString }
|
||||||
fun JsonObject.getInt(key: String, defaultValue: Int): Int = get(key)?.let { if (it.isJsonNull) defaultValue else it.asInt } ?: defaultValue
|
fun JsonObject?.getInt(key: String): Int? = get(key)?.let { if (it.isJsonNull) null else it.asInt }
|
||||||
fun JsonObject.getLong(key: String, defaultValue: Long): Long = get(key)?.let { if (it.isJsonNull) defaultValue else it.asLong } ?: defaultValue
|
fun JsonObject?.getLong(key: String): Long? = get(key)?.let { if (it.isJsonNull) null else it.asLong }
|
||||||
fun JsonObject.getJsonObject(key: String, defaultValue: JsonObject): JsonObject = get(key)?.let { if (it.isJsonNull) defaultValue else it.asJsonObject } ?: defaultValue
|
fun JsonObject?.getJsonObject(key: String): JsonObject? = get(key)?.let { if (it.isJsonNull) null else it.asJsonObject }
|
||||||
fun JsonObject.getJsonArray(key: String, defaultValue: JsonArray): JsonArray = get(key)?.let { if (it.isJsonNull) defaultValue else it.asJsonArray } ?: defaultValue
|
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 {
|
fun CharSequence?.isNotNullNorEmpty(): Boolean {
|
||||||
return this != null && this.isNotEmpty()
|
return this != null && this.isNotEmpty()
|
||||||
|
@ -85,10 +85,10 @@ public class AppError {
|
|||||||
this(TAG, line, errorCode, null, null, null, throwable, apiResponse);
|
this(TAG, line, errorCode, null, null, null, throwable, apiResponse);
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, Throwable throwable, JsonObject 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) {
|
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) {
|
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);
|
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);
|
this(TAG, line, errorCode, errorText, null, null, null, apiResponse);
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, String errorText, JsonObject 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) {
|
public AppError(String TAG, int line, int errorCode, String errorText) {
|
||||||
this(TAG, line, errorCode, errorText, null, null, null, null);
|
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());
|
this(TAG, line, errorCode, null, null, null, null, apiResponse.toString());
|
||||||
}
|
}
|
||||||
public AppError(String TAG, int line, int errorCode, Response response, Throwable throwable, JsonObject apiResponse) {
|
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) {
|
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);
|
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);
|
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) {
|
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) {
|
public String getDetails(Context context) {
|
||||||
|
@ -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_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_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"
|
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_TOKEN_JST_URL = "https://api.librus.pl/OAuth/TokenJST"
|
||||||
const val LIBRUS_API_AUTHORIZATION = "Mjg6ODRmZGQzYTg3YjAzZDNlYTZmZmU3NzdiNThiMzMyYjE="
|
const val LIBRUS_API_AUTHORIZATION = "Mjg6ODRmZGQzYTg3YjAzZDNlYTZmZmU3NzdiNThiMzMyYjE="
|
||||||
const val LIBRUS_API_SECRET_JST = "18b7c1ee08216f636a1b1a2440e68398"
|
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_CODE = "68656A21"
|
||||||
const val LIBRUS_JST_DEMO_PIN = "1290"
|
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_MESSAGES_URL = "https://wiadomosci.librus.pl/module/"
|
||||||
const val LIBRUS_SANDBOX_URL = "https://sandbox.librus.pl/index.php?action="
|
const val LIBRUS_SANDBOX_URL = "https://sandbox.librus.pl/index.php?action="
|
@ -30,12 +30,58 @@ const val CODE_LIBRUS_NOT_ACTIVATED = 29
|
|||||||
const val CODE_SYNERGIA_NOT_ACTIVATED = 32
|
const val CODE_SYNERGIA_NOT_ACTIVATED = 32
|
||||||
const val CODE_LIBRUS_DISCONNECTED = 31
|
const val CODE_LIBRUS_DISCONNECTED = 31
|
||||||
const val CODE_PROFILE_ARCHIVED = 30*/
|
const val CODE_PROFILE_ARCHIVED = 30*/
|
||||||
const val CODE_INVALID_LOGIN_MODE = 130
|
|
||||||
const val CODE_INTERNAL_MISSING_DATA = 100
|
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_ACCOUNT_410 = 120
|
||||||
const val CODE_INTERNAL_LIBRUS_SYNERGIA_EXPIRED = 121
|
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 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_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
|
@ -23,17 +23,17 @@ class LibrusTest(val app: App) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val profile = Profile(1, "Profil", "xd", 1).apply {
|
val profile = Profile(1, "Profil", "xd", 1).apply {
|
||||||
//putStudentData("accountLogin", "1234567")
|
putStudentData("accountLogin", "1234567")
|
||||||
//putStudentData("accountPassword", "zaq1@WSX")
|
//putStudentData("accountPassword", "zaq1@WSX")
|
||||||
|
|
||||||
putStudentData("accountCode", LIBRUS_JST_DEMO_CODE)
|
//putStudentData("accountCode", LIBRUS_JST_DEMO_CODE)
|
||||||
putStudentData("accountPin", LIBRUS_JST_DEMO_PIN)
|
//putStudentData("accountPin", LIBRUS_JST_DEMO_PIN)
|
||||||
}
|
}
|
||||||
val loginStore = LoginStore(1, LOGIN_TYPE_LIBRUS, JsonObject().apply {
|
val loginStore = LoginStore(1, LOGIN_TYPE_LIBRUS, JsonObject().apply {
|
||||||
addProperty("email", "test@example.com")
|
addProperty("email", "test@example.com")
|
||||||
addProperty("password", "zaq1@WSX")
|
addProperty("password", "zaq1@WSX")
|
||||||
}).also {
|
}).also {
|
||||||
it.mode = LOGIN_MODE_LIBRUS_JST
|
it.mode = LOGIN_MODE_LIBRUS_EMAIL
|
||||||
}
|
}
|
||||||
|
|
||||||
fun go() {
|
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, "Login succeeded.")
|
||||||
d(TAG, "Profile data: ${data.profile?.studentData?.toString()}")
|
d(TAG, "Profile data: ${data.profile?.studentData?.toString()}")
|
||||||
d(TAG, "LoginStore data: ${data.loginStore.data}")
|
d(TAG, "LoginStore data: ${data.loginStore.data}")
|
||||||
|
@ -49,6 +49,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
|||||||
/**
|
/**
|
||||||
* A Synergia login, like 1234567u.
|
* A Synergia login, like 1234567u.
|
||||||
* Used: for login (API Login Method) in Synergia mode.
|
* 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
|
* And also in various places in [pl.szczodrzynski.edziennik.api.v2.models.Endpoint]s
|
||||||
*/
|
*/
|
||||||
private var mApiLogin: String? = null
|
private var mApiLogin: String? = null
|
||||||
@ -58,6 +59,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
|||||||
/**
|
/**
|
||||||
* A Synergia password.
|
* A Synergia password.
|
||||||
* Used: for login (API Login Method) in Synergia mode.
|
* Used: for login (API Login Method) in Synergia mode.
|
||||||
|
* Used: for login (Synergia Login Method) in Synergia mode.
|
||||||
*/
|
*/
|
||||||
private var mApiPassword: String? = null
|
private var mApiPassword: String? = null
|
||||||
var apiPassword: String?
|
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 }
|
get() { mApiTokenExpiryTime = mApiTokenExpiryTime ?: profile?.getStudentData("accountTokenTime", 0L); return mApiTokenExpiryTime ?: 0L }
|
||||||
set(value) { profile?.putStudentData("accountTokenTime", value) ?: return; mApiTokenExpiryTime = value }
|
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 }
|
||||||
|
|
||||||
/* ____ _ _
|
/* ____ _ _
|
||||||
/ __ \| | | |
|
/ __ \| | | |
|
||||||
| | | | |_| |__ ___ _ __
|
| | | | |_| |__ ___ _ __
|
||||||
|
@ -24,9 +24,9 @@ open class LibrusApi(override val data: DataLibrus) : Api(data) {
|
|||||||
const val TAG = "LibrusApi"
|
const val TAG = "LibrusApi"
|
||||||
}
|
}
|
||||||
fun apiRequest(endpoint: String, callback: (json: JsonObject?) -> Unit) {
|
fun apiRequest(endpoint: String, callback: (json: JsonObject?) -> Unit) {
|
||||||
d(TAG, "Requesting $LIBRUS_API_URL$endpoint")
|
d(TAG, "Requesting $LIBRUS_API_URL/$endpoint")
|
||||||
Request.builder()
|
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)
|
.userAgent(LIBRUS_USER_AGENT)
|
||||||
.addHeader("Authorization", "Bearer ${data.apiAccessToken}")
|
.addHeader("Authorization", "Bearer ${data.apiAccessToken}")
|
||||||
.get()
|
.get()
|
||||||
|
@ -63,7 +63,7 @@ class LoginLibrus(val data: DataLibrus, vararg loginMethodIds: Int, val onSucces
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOGIN_METHOD_LIBRUS_SYNERGIA -> {
|
LOGIN_METHOD_LIBRUS_SYNERGIA -> {
|
||||||
LoginLibrusApi(data) {
|
LoginLibrusSynergia(data) {
|
||||||
data.loginMethods.add(loginMethodId)
|
data.loginMethods.add(loginMethodId)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ import pl.szczodrzynski.edziennik.currentTimeUnix
|
|||||||
import pl.szczodrzynski.edziennik.getInt
|
import pl.szczodrzynski.edziennik.getInt
|
||||||
import pl.szczodrzynski.edziennik.getString
|
import pl.szczodrzynski.edziennik.getString
|
||||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||||
import java.net.HttpURLConnection
|
|
||||||
import java.net.HttpURLConnection.*
|
import java.net.HttpURLConnection.*
|
||||||
|
|
||||||
class LoginLibrusApi {
|
class LoginLibrusApi {
|
||||||
@ -28,12 +27,13 @@ class LoginLibrusApi {
|
|||||||
private lateinit var data: DataLibrus
|
private lateinit var data: DataLibrus
|
||||||
private lateinit var onSuccess: () -> Unit
|
private lateinit var onSuccess: () -> Unit
|
||||||
|
|
||||||
|
/* do NOT move this to primary constructor */
|
||||||
constructor(data: DataLibrus, onSuccess: () -> Unit) {
|
constructor(data: DataLibrus, onSuccess: () -> Unit) {
|
||||||
this.data = data
|
this.data = data
|
||||||
this.onSuccess = onSuccess
|
this.onSuccess = onSuccess
|
||||||
|
|
||||||
if (data.profile == null) {
|
if (data.profile == null) {
|
||||||
data.callback.onError(null, AppError(TAG, 19, CODE_LIBRUS_PROFILE_NULL))
|
data.error(TAG, ERROR_PROFILE_MISSING)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ class LoginLibrusApi {
|
|||||||
LOGIN_MODE_LIBRUS_SYNERGIA -> loginWithSynergia()
|
LOGIN_MODE_LIBRUS_SYNERGIA -> loginWithSynergia()
|
||||||
LOGIN_MODE_LIBRUS_JST -> loginWithJst()
|
LOGIN_MODE_LIBRUS_JST -> loginWithJst()
|
||||||
else -> {
|
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() {
|
private fun loginWithPortal() {
|
||||||
if (!data.loginMethods.contains(LOGIN_METHOD_LIBRUS_PORTAL)) {
|
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
|
return
|
||||||
}
|
}
|
||||||
SynergiaTokenExtractor(data) {
|
SynergiaTokenExtractor(data) {
|
||||||
@ -94,7 +94,7 @@ class LoginLibrusApi {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// cannot log in: token expired, no login data present
|
// 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,45 +111,31 @@ class LoginLibrusApi {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// cannot log in: token expired, no login data present
|
// 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() {
|
private val tokenCallback = object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
override fun onSuccess(json: JsonObject?, response: Response?) {
|
||||||
if (json == null) {
|
if (json == null) {
|
||||||
data.callback.onError(null, AppError(TAG, 117, CODE_MAINTENANCE, response))
|
data.error(TAG, ERROR_RESPONSE_EMPTY, response)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
json.getString("error")?.let { error ->
|
json.getString("error")?.let { error ->
|
||||||
when (error) {
|
when (error) {
|
||||||
"librus_captcha_needed" -> {
|
"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
|
||||||
"connection_problems" -> {
|
"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_client" -> {
|
"invalid_grant" -> ERROR_LOGIN_LIBRUS_API_INVALID_GRANT
|
||||||
|
else -> ERROR_LOGIN_LIBRUS_API_OTHER
|
||||||
}
|
}.let { errorCode ->
|
||||||
"librus_reg_accept_needed" -> {
|
data.error(TAG, errorCode, apiResponse = json, response = response)
|
||||||
|
|
||||||
}
|
|
||||||
"librus_change_password_error" -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
"librus_password_change_required" -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
"invalid_grant" -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
data.apiAccessToken = json.getString("access_token")
|
data.apiAccessToken = json.getString("access_token")
|
||||||
@ -157,12 +143,12 @@ class LoginLibrusApi {
|
|||||||
data.apiTokenExpiryTime = currentTimeUnix() + json.getInt("expires_in", 86400)
|
data.apiTokenExpiryTime = currentTimeUnix() + json.getInt("expires_in", 86400)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
} catch (e: NullPointerException) {
|
} 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?) {
|
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)
|
.contentType(MediaTypeUtils.APPLICATION_FORM)
|
||||||
.post()
|
.post()
|
||||||
.allowErrorCode(HTTP_BAD_REQUEST)
|
.allowErrorCode(HTTP_BAD_REQUEST)
|
||||||
.allowErrorCode(HTTP_FORBIDDEN)
|
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
.allowErrorCode(HTTP_UNAUTHORIZED)
|
||||||
.callback(tokenCallback)
|
.callback(tokenCallback)
|
||||||
.build()
|
.build()
|
||||||
@ -197,7 +182,6 @@ class LoginLibrusApi {
|
|||||||
.contentType(MediaTypeUtils.APPLICATION_FORM)
|
.contentType(MediaTypeUtils.APPLICATION_FORM)
|
||||||
.post()
|
.post()
|
||||||
.allowErrorCode(HTTP_BAD_REQUEST)
|
.allowErrorCode(HTTP_BAD_REQUEST)
|
||||||
.allowErrorCode(HTTP_FORBIDDEN)
|
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
.allowErrorCode(HTTP_UNAUTHORIZED)
|
||||||
.callback(tokenCallback)
|
.callback(tokenCallback)
|
||||||
.build()
|
.build()
|
||||||
@ -218,7 +202,6 @@ class LoginLibrusApi {
|
|||||||
.contentType(MediaTypeUtils.APPLICATION_FORM)
|
.contentType(MediaTypeUtils.APPLICATION_FORM)
|
||||||
.post()
|
.post()
|
||||||
.allowErrorCode(HTTP_BAD_REQUEST)
|
.allowErrorCode(HTTP_BAD_REQUEST)
|
||||||
.allowErrorCode(HTTP_FORBIDDEN)
|
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
.allowErrorCode(HTTP_UNAUTHORIZED)
|
||||||
.callback(tokenCallback)
|
.callback(tokenCallback)
|
||||||
.build()
|
.build()
|
||||||
@ -237,7 +220,6 @@ class LoginLibrusApi {
|
|||||||
.contentType(MediaTypeUtils.APPLICATION_FORM)
|
.contentType(MediaTypeUtils.APPLICATION_FORM)
|
||||||
.post()
|
.post()
|
||||||
.allowErrorCode(HTTP_BAD_REQUEST)
|
.allowErrorCode(HTTP_BAD_REQUEST)
|
||||||
.allowErrorCode(HTTP_FORBIDDEN)
|
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
.allowErrorCode(HTTP_UNAUTHORIZED)
|
||||||
.callback(tokenCallback)
|
.callback(tokenCallback)
|
||||||
.build()
|
.build()
|
||||||
|
@ -24,11 +24,11 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
|
|
||||||
init { run {
|
init { run {
|
||||||
if (data.loginStore.mode != LOGIN_MODE_LIBRUS_EMAIL) {
|
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
|
return@run
|
||||||
}
|
}
|
||||||
if (data.portalEmail == null || data.portalPassword == null) {
|
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
|
return@run
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,13 +67,13 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
if (csrfMatcher.find()) {
|
if (csrfMatcher.find()) {
|
||||||
login(csrfMatcher.group(1))
|
login(csrfMatcher.group(1))
|
||||||
} else {
|
} 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) {
|
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()
|
.build()
|
||||||
@ -94,14 +94,14 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
override fun onSuccess(json: JsonObject?, response: Response) {
|
override fun onSuccess(json: JsonObject?, response: Response) {
|
||||||
if (json == null) {
|
if (json == null) {
|
||||||
if (response.parserErrorBody?.contains("wciąż nieaktywne") == true) {
|
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
|
return
|
||||||
}
|
}
|
||||||
data.callback.onError(null, AppError(TAG, 489, CODE_MAINTENANCE, response))
|
data.error(TAG, ERROR_RESPONSE_EMPTY, response)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (json.get("errors") != null) {
|
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
|
return
|
||||||
}
|
}
|
||||||
authorize(json.getString("redirect", LIBRUS_AUTHORIZE_URL))
|
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) {
|
override fun onFailure(response: Response, throwable: Throwable) {
|
||||||
if (response.code() == 403 || response.code() == 401) {
|
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
|
return
|
||||||
}
|
}
|
||||||
data.callback.onError(null, AppError(TAG, 251, CODE_OTHER, response, throwable))
|
data.error(TAG, ERROR_REQUEST_FAILURE, response, throwable)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.build()
|
.build()
|
||||||
@ -141,20 +141,19 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
.callback(object : JsonCallbackHandler() {
|
.callback(object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response) {
|
override fun onSuccess(json: JsonObject?, response: Response) {
|
||||||
if (json == null) {
|
if (json == null) {
|
||||||
data.callback.onError(null, AppError(TAG, 539, CODE_MAINTENANCE, response))
|
data.error(TAG, ERROR_RESPONSE_EMPTY, response)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
json.getString("error")?.let { error ->
|
json.getString("error")?.let { error ->
|
||||||
val hint = json.getString("hint", "")
|
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")) {
|
if (!refreshTokenFailed && refreshToken != null && (hint == "Token has been revoked" || hint == "Token has expired")) {
|
||||||
c(TAG, "refreshing the token failed. Trying to log in again.")
|
c(TAG, "refreshing the token failed. Trying to log in again.")
|
||||||
refreshTokenFailed = true
|
refreshTokenFailed = true
|
||||||
authorize(LIBRUS_AUTHORIZE_URL)
|
authorize(LIBRUS_AUTHORIZE_URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val errorText = "$error $message $hint"
|
data.error(TAG, ERROR_LOGIN_LIBRUS_PORTAL_TOKEN_ERROR, response, apiResponse = json)
|
||||||
data.callback.onError(null, AppError(TAG, 552, CODE_OTHER, errorText, response, json))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,13 +163,13 @@ class LoginLibrusPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
data.portalTokenExpiryTime = currentTimeUnix() + json.getInt("expires_in", 86400)
|
data.portalTokenExpiryTime = currentTimeUnix() + json.getInt("expires_in", 86400)
|
||||||
onSuccess()
|
onSuccess()
|
||||||
} catch (e: NullPointerException) {
|
} 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) {
|
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()
|
.build()
|
||||||
|
@ -4,5 +4,175 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.librus.login
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
@ -15,16 +15,16 @@ import java.net.HttpURLConnection.*
|
|||||||
|
|
||||||
class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) {
|
class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "librus.SynergiaToken"
|
private const val TAG = "SynergiaTokenExtractor"
|
||||||
}
|
}
|
||||||
|
|
||||||
init { run {
|
init { run {
|
||||||
if (data.loginStore.mode != LOGIN_MODE_LIBRUS_EMAIL) {
|
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
|
return@run
|
||||||
}
|
}
|
||||||
if (data.profile == null) {
|
if (data.profile == null) {
|
||||||
data.callback.onError(null, AppError(TAG, 28, CODE_LIBRUS_PROFILE_NULL))
|
data.error(TAG, ERROR_PROFILE_MISSING)
|
||||||
return@run
|
return@run
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,9 @@ class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
onSuccess()
|
onSuccess()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
synergiaAccount()
|
if (!synergiaAccount()) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@ -54,25 +56,25 @@ class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
.callback(object : JsonCallbackHandler() {
|
.callback(object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response) {
|
override fun onSuccess(json: JsonObject?, response: Response) {
|
||||||
if (json == null) {
|
if (json == null) {
|
||||||
data.callback.onError(null, AppError(TAG, 641, CODE_MAINTENANCE, response))
|
data.error(TAG, ERROR_RESPONSE_EMPTY, response)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (response.code() == 410) {
|
if (response.code() == 410) {
|
||||||
val reason = json.get("reason")
|
val reason = json.get("reason")
|
||||||
if (reason != null && reason !is JsonNull && reason.asString == "requires_an_action") {
|
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
|
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
|
return
|
||||||
}
|
}
|
||||||
if (json.get("message") != null) {
|
if (json.get("message") != null) {
|
||||||
val message = json.get("message").asString
|
val message = json.get("message").asString
|
||||||
if (message == "Account not found") {
|
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
|
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
|
return
|
||||||
}
|
}
|
||||||
if (response.code() == HTTP_OK) {
|
if (response.code() == HTTP_OK) {
|
||||||
@ -81,7 +83,7 @@ class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
val accountId = json.getInt("id")
|
val accountId = json.getInt("id")
|
||||||
val accountToken = json.getString("accessToken")
|
val accountToken = json.getString("accessToken")
|
||||||
if (accountId == null || accountToken == null) {
|
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
|
return
|
||||||
}
|
}
|
||||||
data.apiAccessToken = accountToken
|
data.apiAccessToken = accountToken
|
||||||
@ -92,16 +94,16 @@ class SynergiaTokenExtractor(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
onSuccess()
|
onSuccess()
|
||||||
} catch (e: NullPointerException) {
|
} catch (e: NullPointerException) {
|
||||||
e.printStackTrace()
|
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 {
|
} 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) {
|
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()
|
.build()
|
||||||
|
@ -3,7 +3,10 @@ package pl.szczodrzynski.edziennik.api.v2.models
|
|||||||
import android.util.LongSparseArray
|
import android.util.LongSparseArray
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.core.util.isNotEmpty
|
import androidx.core.util.isNotEmpty
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import im.wangchao.mhttp.Response
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
|
import pl.szczodrzynski.edziennik.api.AppError
|
||||||
import pl.szczodrzynski.edziennik.api.interfaces.ProgressCallback
|
import pl.szczodrzynski.edziennik.api.interfaces.ProgressCallback
|
||||||
import pl.szczodrzynski.edziennik.datamodels.*
|
import pl.szczodrzynski.edziennik.datamodels.*
|
||||||
import pl.szczodrzynski.edziennik.models.Date
|
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
|
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<Int>()
|
val loginMethods = mutableListOf<Int>()
|
||||||
|
|
||||||
val teacherList = LongSparseArray<Teacher>()
|
val teacherList = LongSparseArray<Teacher>()
|
||||||
@ -133,4 +142,11 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
|
|||||||
if (messageMetadataList.isNotEmpty())
|
if (messageMetadataList.isNotEmpty())
|
||||||
db.metadataDao().setSeen(messageMetadataList)
|
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))
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user