forked from github/szkolny
[API/Login] Make user action handling more universal.
This commit is contained in:
parent
7ded400a30
commit
93ccdbdeb7
@ -34,6 +34,7 @@ import org.greenrobot.eventbus.EventBus
|
|||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import pl.droidsonroids.gif.GifDrawable
|
import pl.droidsonroids.gif.GifDrawable
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.ERROR_REQUIRES_USER_ACTION
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_VULCAN_API_DEPRECATED
|
import pl.szczodrzynski.edziennik.data.api.ERROR_VULCAN_API_DEPRECATED
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.*
|
import pl.szczodrzynski.edziennik.data.api.events.*
|
||||||
@ -69,6 +70,7 @@ import pl.szczodrzynski.edziennik.ui.grades.editor.GradesEditorFragment
|
|||||||
import pl.szczodrzynski.edziennik.ui.home.HomeFragment
|
import pl.szczodrzynski.edziennik.ui.home.HomeFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.homework.HomeworkFragment
|
import pl.szczodrzynski.edziennik.ui.homework.HomeworkFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.login.LoginActivity
|
import pl.szczodrzynski.edziennik.ui.login.LoginActivity
|
||||||
|
import pl.szczodrzynski.edziennik.ui.login.LoginProgressFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.messages.compose.MessagesComposeFragment
|
import pl.szczodrzynski.edziennik.ui.messages.compose.MessagesComposeFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.messages.list.MessagesFragment
|
import pl.szczodrzynski.edziennik.ui.messages.list.MessagesFragment
|
||||||
import pl.szczodrzynski.edziennik.ui.messages.single.MessageFragment
|
import pl.szczodrzynski.edziennik.ui.messages.single.MessageFragment
|
||||||
@ -83,6 +85,7 @@ import pl.szczodrzynski.edziennik.utils.*
|
|||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.dpToPx
|
import pl.szczodrzynski.edziennik.utils.Utils.dpToPx
|
||||||
import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type
|
import pl.szczodrzynski.edziennik.utils.managers.AvailabilityManager.Error.Type
|
||||||
|
import pl.szczodrzynski.edziennik.utils.managers.UserActionManager
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.edziennik.utils.models.NavTarget
|
import pl.szczodrzynski.edziennik.utils.models.NavTarget
|
||||||
import pl.szczodrzynski.navlib.*
|
import pl.szczodrzynski.navlib.*
|
||||||
@ -853,7 +856,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
|||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onUserActionRequiredEvent(event: UserActionRequiredEvent) {
|
fun onUserActionRequiredEvent(event: UserActionRequiredEvent) {
|
||||||
app.userActionManager.execute(this, event.profileId, event.type, event.params)
|
app.userActionManager.execute(this, event, UserActionManager.UserActionCallback())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fragmentToSyncName(currentFragment: Int): Int {
|
private fun fragmentToSyncName(currentFragment: Int): Int {
|
||||||
@ -911,12 +914,13 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
"userActionRequired" -> {
|
"userActionRequired" -> {
|
||||||
app.userActionManager.execute(
|
val event = UserActionRequiredEvent(
|
||||||
this,
|
profileId = extras.getInt("profileId"),
|
||||||
extras.getInt("profileId"),
|
type = extras.getEnum<UserActionRequiredEvent.Type>("type") ?: return,
|
||||||
extras.getInt("type"),
|
params = extras.getBundle("params") ?: return,
|
||||||
extras.getBundle("params"),
|
errorText = 0,
|
||||||
)
|
)
|
||||||
|
app.userActionManager.execute(this, event, UserActionManager.UserActionCallback())
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
"createManualEvent" -> {
|
"createManualEvent" -> {
|
||||||
|
@ -84,19 +84,21 @@ class ApiService : Service() {
|
|||||||
runTask()
|
runTask()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRequiresUserAction(event: UserActionRequiredEvent) {
|
||||||
|
app.userActionManager.sendToUser(event)
|
||||||
|
taskRunning?.cancel()
|
||||||
|
clearTask()
|
||||||
|
runTask()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(apiError: ApiError) {
|
override fun onError(apiError: ApiError) {
|
||||||
lastEventTime = System.currentTimeMillis()
|
lastEventTime = System.currentTimeMillis()
|
||||||
d(TAG, "Task $taskRunningId threw an error - $apiError")
|
d(TAG, "Task $taskRunningId threw an error - $apiError")
|
||||||
apiError.profileId = taskProfileId
|
apiError.profileId = taskProfileId
|
||||||
|
|
||||||
if (app.userActionManager.requiresUserAction(apiError)) {
|
|
||||||
app.userActionManager.sendToUser(apiError)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
EventBus.getDefault().postSticky(ApiTaskErrorEvent(apiError))
|
EventBus.getDefault().postSticky(ApiTaskErrorEvent(apiError))
|
||||||
errorList.add(apiError)
|
errorList.add(apiError)
|
||||||
apiError.throwable?.printStackTrace()
|
apiError.throwable?.printStackTrace()
|
||||||
}
|
|
||||||
|
|
||||||
if (apiError.isCritical) {
|
if (apiError.isCritical) {
|
||||||
taskRunning?.cancel()
|
taskRunning?.cancel()
|
||||||
|
@ -59,6 +59,9 @@ const val LIBRUS_SANDBOX_URL = "https://sandbox.librus.pl/index.php?action="
|
|||||||
const val LIBRUS_SYNERGIA_HOMEWORK_ATTACHMENT_URL = "https://synergia.librus.pl/homework/downloadFile"
|
const val LIBRUS_SYNERGIA_HOMEWORK_ATTACHMENT_URL = "https://synergia.librus.pl/homework/downloadFile"
|
||||||
const val LIBRUS_SYNERGIA_MESSAGES_ATTACHMENT_URL = "https://synergia.librus.pl/wiadomosci/pobierz_zalacznik"
|
const val LIBRUS_SYNERGIA_MESSAGES_ATTACHMENT_URL = "https://synergia.librus.pl/wiadomosci/pobierz_zalacznik"
|
||||||
|
|
||||||
|
const val LIBRUS_PORTAL_RECAPTCHA_KEY = "6Lf48moUAAAAAB9ClhdvHr46gRWR"
|
||||||
|
const val LIBRUS_PORTAL_RECAPTCHA_REFERER = "https://portal.librus.pl/rodzina/login"
|
||||||
|
|
||||||
|
|
||||||
val MOBIDZIENNIK_USER_AGENT = SYSTEM_USER_AGENT
|
val MOBIDZIENNIK_USER_AGENT = SYSTEM_USER_AGENT
|
||||||
|
|
||||||
|
@ -58,11 +58,7 @@ const val ERROR_INVALID_LOGIN_MODE = 110
|
|||||||
const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111
|
const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111
|
||||||
const val ERROR_NOT_IMPLEMENTED = 112
|
const val ERROR_NOT_IMPLEMENTED = 112
|
||||||
const val ERROR_FILE_DOWNLOAD = 113
|
const val ERROR_FILE_DOWNLOAD = 113
|
||||||
|
const val ERROR_REQUIRES_USER_ACTION = 114
|
||||||
const val ERROR_NO_STUDENTS_IN_ACCOUNT = 115
|
|
||||||
|
|
||||||
const val ERROR_CAPTCHA_NEEDED = 3000
|
|
||||||
const val ERROR_CAPTCHA_LIBRUS_PORTAL = 3001
|
|
||||||
|
|
||||||
const val ERROR_API_PDO_ERROR = 5000
|
const val ERROR_API_PDO_ERROR = 5000
|
||||||
const val ERROR_API_INVALID_CLIENT = 5001
|
const val ERROR_API_INVALID_CLIENT = 5001
|
||||||
@ -204,7 +200,6 @@ const val ERROR_PODLASIE_API_NO_TOKEN = 630
|
|||||||
const val ERROR_PODLASIE_API_OTHER = 631
|
const val ERROR_PODLASIE_API_OTHER = 631
|
||||||
const val ERROR_PODLASIE_API_DATA_MISSING = 632
|
const val ERROR_PODLASIE_API_DATA_MISSING = 632
|
||||||
|
|
||||||
const val ERROR_USOS_OAUTH_LOGIN_REQUEST = 701
|
|
||||||
const val ERROR_USOS_OAUTH_GOT_DIFFERENT_TOKEN = 702
|
const val ERROR_USOS_OAUTH_GOT_DIFFERENT_TOKEN = 702
|
||||||
const val ERROR_USOS_OAUTH_INCOMPLETE_RESPONSE = 703
|
const val ERROR_USOS_OAUTH_INCOMPLETE_RESPONSE = 703
|
||||||
const val ERROR_USOS_NO_STUDENT_PROGRAMMES = 704
|
const val ERROR_USOS_NO_STUDENT_PROGRAMMES = 704
|
||||||
|
@ -16,6 +16,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.Librus
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.*
|
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.synergia.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.firstlogin.LibrusFirstLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.firstlogin.LibrusFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLogin
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
@ -162,6 +163,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||||
return object : EdziennikCallback {
|
return object : EdziennikCallback {
|
||||||
override fun onCompleted() { callback.onCompleted() }
|
override fun onCompleted() { callback.onCompleted() }
|
||||||
|
override fun onRequiresUserAction(event: UserActionRequiredEvent) { callback.onRequiresUserAction(event) }
|
||||||
override fun onProgress(step: Float) { callback.onProgress(step) }
|
override fun onProgress(step: Float) { callback.onProgress(step) }
|
||||||
override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) }
|
override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) }
|
||||||
override fun onError(apiError: ApiError) {
|
override fun onError(apiError: ApiError) {
|
||||||
|
@ -10,6 +10,7 @@ import im.wangchao.mhttp.callback.TextCallbackHandler
|
|||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
import pl.szczodrzynski.edziennik.data.api.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.ext.*
|
import pl.szczodrzynski.edziennik.ext.*
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
@ -148,12 +149,23 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
val error = if (response.code() == 200) null else
|
val error = if (response.code() == 200) null else
|
||||||
json.getJsonArray("errors")?.getString(0)
|
json.getJsonArray("errors")?.getString(0)
|
||||||
?: json.getJsonObject("errors")?.entrySet()?.firstOrNull()?.value?.asString
|
?: json.getJsonObject("errors")?.entrySet()?.firstOrNull()?.value?.asString
|
||||||
|
|
||||||
|
if (error?.contains("robotem") == true || json.getBoolean("captchaRequired") == true) {
|
||||||
|
data.requireUserAction(
|
||||||
|
type = UserActionRequiredEvent.Type.RECAPTCHA,
|
||||||
|
params = Bundle(
|
||||||
|
"siteKey" to LIBRUS_PORTAL_RECAPTCHA_KEY,
|
||||||
|
"referer" to LIBRUS_PORTAL_RECAPTCHA_REFERER,
|
||||||
|
),
|
||||||
|
errorText = R.string.notification_user_action_required_captcha_librus,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
error?.let { code ->
|
error?.let { code ->
|
||||||
when {
|
when {
|
||||||
code.contains("Sesja logowania wygasła") -> ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED
|
code.contains("Sesja logowania wygasła") -> ERROR_LOGIN_LIBRUS_PORTAL_CSRF_EXPIRED
|
||||||
code.contains("Upewnij się, że nie") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
|
code.contains("Upewnij się, że nie") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
|
||||||
// this doesn't work anyway: `errors` is an object with `g-recaptcha-response` set
|
|
||||||
code.contains("robotem") -> ERROR_CAPTCHA_LIBRUS_PORTAL
|
|
||||||
code.contains("Podany adres e-mail jest nieprawidłowy.") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
|
code.contains("Podany adres e-mail jest nieprawidłowy.") -> ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN
|
||||||
else -> ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR
|
else -> ERROR_LOGIN_LIBRUS_PORTAL_ACTION_ERROR
|
||||||
}.let { errorCode ->
|
}.let { errorCode ->
|
||||||
@ -163,12 +175,6 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (json.getBoolean("captchaRequired") == true) {
|
|
||||||
data.error(ApiError(TAG, ERROR_CAPTCHA_LIBRUS_PORTAL)
|
|
||||||
.withResponse(response)
|
|
||||||
.withApiResponse(json))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
authorize(json.getString("redirect", LIBRUS_AUTHORIZE_URL))
|
authorize(json.getString("redirect", LIBRUS_AUTHORIZE_URL))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.Mobidzien
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.*
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.firstlogin.MobidziennikFirstLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.firstlogin.MobidziennikFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLogin
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
@ -142,6 +143,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
|||||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||||
return object : EdziennikCallback {
|
return object : EdziennikCallback {
|
||||||
override fun onCompleted() { callback.onCompleted() }
|
override fun onCompleted() { callback.onCompleted() }
|
||||||
|
override fun onRequiresUserAction(event: UserActionRequiredEvent) { callback.onRequiresUserAction(event) }
|
||||||
override fun onProgress(step: Float) { callback.onProgress(step) }
|
override fun onProgress(step: Float) { callback.onProgress(step) }
|
||||||
override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) }
|
override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) }
|
||||||
override fun onError(apiError: ApiError) {
|
override fun onError(apiError: ApiError) {
|
||||||
|
@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.PodlasieData
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.firstlogin.PodlasieFirstLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.firstlogin.PodlasieFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.login.PodlasieLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.login.PodlasieLogin
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
@ -142,6 +143,10 @@ class Podlasie(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
callback.onCompleted()
|
callback.onCompleted()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRequiresUserAction(event: UserActionRequiredEvent) {
|
||||||
|
callback.onRequiresUserAction(event)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onProgress(step: Float) {
|
override fun onProgress(step: Float) {
|
||||||
callback.onProgress(step)
|
callback.onProgress(step)
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.template.data.TemplateData
|
import pl.szczodrzynski.edziennik.data.api.edziennik.template.data.TemplateData
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.template.firstlogin.TemplateFirstLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.template.firstlogin.TemplateFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLogin
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
@ -108,6 +109,10 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|
|||||||
callback.onCompleted()
|
callback.onCompleted()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRequiresUserAction(event: UserActionRequiredEvent) {
|
||||||
|
callback.onRequiresUserAction(event)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onProgress(step: Float) {
|
override fun onProgress(step: Float) {
|
||||||
callback.onProgress(step)
|
callback.onProgress(step)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.google.gson.JsonObject
|
|||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.firstlogin.UsosFirstLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.firstlogin.UsosFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.login.UsosLogin
|
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.login.UsosLogin
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
@ -88,6 +89,10 @@ class Usos(
|
|||||||
callback.onCompleted()
|
callback.onCompleted()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRequiresUserAction(event: UserActionRequiredEvent) {
|
||||||
|
callback.onRequiresUserAction(event)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onProgress(step: Float) {
|
override fun onProgress(step: Float) {
|
||||||
callback.onProgress(step)
|
callback.onProgress(step)
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.usos.login
|
package pl.szczodrzynski.edziennik.data.api.edziennik.usos.login
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.*
|
import pl.szczodrzynski.edziennik.data.api.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.DataUsos
|
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.DataUsos
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.data.UsosApi
|
import pl.szczodrzynski.edziennik.data.api.edziennik.usos.data.UsosApi
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.ext.Bundle
|
import pl.szczodrzynski.edziennik.ext.Bundle
|
||||||
import pl.szczodrzynski.edziennik.ext.fromQueryString
|
import pl.szczodrzynski.edziennik.ext.fromQueryString
|
||||||
@ -53,13 +55,16 @@ class UsosLoginApi(val data: DataUsos, val onSuccess: () -> Unit) {
|
|||||||
"interactivity" to "confirm_user",
|
"interactivity" to "confirm_user",
|
||||||
"oauth_token" to (data.oauthTokenKey ?: ""),
|
"oauth_token" to (data.oauthTokenKey ?: ""),
|
||||||
)
|
)
|
||||||
val params = Bundle(
|
data.requireUserAction(
|
||||||
|
type = UserActionRequiredEvent.Type.OAUTH,
|
||||||
|
params = Bundle(
|
||||||
"authorizeUrl" to "$authUrl?${authParams.toQueryString()}",
|
"authorizeUrl" to "$authUrl?${authParams.toQueryString()}",
|
||||||
"redirectUrl" to USOS_API_OAUTH_REDIRECT_URL,
|
"redirectUrl" to USOS_API_OAUTH_REDIRECT_URL,
|
||||||
"responseStoreKey" to "oauthLoginResponse",
|
"responseStoreKey" to "oauthLoginResponse",
|
||||||
"extras" to data.loginStore.data.toBundle(),
|
"extras" to data.loginStore.data.toBundle(),
|
||||||
|
),
|
||||||
|
errorText = R.string.notification_user_action_required_oauth_usos,
|
||||||
)
|
)
|
||||||
data.error(ApiError(TAG, ERROR_USOS_OAUTH_LOGIN_REQUEST).withParams(params))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +98,7 @@ class UsosLoginApi(val data: DataUsos, val onSuccess: () -> Unit) {
|
|||||||
data.oauthTokenKey = accessData["oauth_token"]
|
data.oauthTokenKey = accessData["oauth_token"]
|
||||||
data.oauthTokenSecret = accessData["oauth_token_secret"]
|
data.oauthTokenSecret = accessData["oauth_token_secret"]
|
||||||
data.oauthTokenIsUser = data.oauthTokenKey != null && data.oauthTokenSecret != null
|
data.oauthTokenIsUser = data.oauthTokenKey != null && data.oauthTokenSecret != null
|
||||||
|
data.loginStore.removeLoginData("oauthLoginResponse")
|
||||||
|
|
||||||
if (!data.oauthTokenIsUser)
|
if (!data.oauthTokenIsUser)
|
||||||
data.error(ApiError(TAG, ERROR_USOS_OAUTH_INCOMPLETE_RESPONSE)
|
data.error(ApiError(TAG, ERROR_USOS_OAUTH_INCOMPLETE_RESPONSE)
|
||||||
|
@ -17,6 +17,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLogin
|
|||||||
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
|
import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
|
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||||
@ -179,6 +180,7 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
|||||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||||
return object : EdziennikCallback {
|
return object : EdziennikCallback {
|
||||||
override fun onCompleted() { callback.onCompleted() }
|
override fun onCompleted() { callback.onCompleted() }
|
||||||
|
override fun onRequiresUserAction(event: UserActionRequiredEvent) { callback.onRequiresUserAction(event) }
|
||||||
override fun onProgress(step: Float) { callback.onProgress(step) }
|
override fun onProgress(step: Float) { callback.onProgress(step) }
|
||||||
override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) }
|
override fun onStartProgress(stringRes: Int) { callback.onStartProgress(stringRes) }
|
||||||
override fun onError(apiError: ApiError) {
|
override fun onError(apiError: ApiError) {
|
||||||
|
@ -6,12 +6,14 @@ package pl.szczodrzynski.edziennik.data.api.events
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
|
||||||
data class UserActionRequiredEvent(val profileId: Int, val type: Int, val params: Bundle?) {
|
data class UserActionRequiredEvent(
|
||||||
companion object {
|
val profileId: Int?,
|
||||||
const val LOGIN_DATA_MOBIDZIENNIK = 101
|
val type: Type,
|
||||||
const val LOGIN_DATA_LIBRUS = 102
|
val params: Bundle,
|
||||||
const val LOGIN_DATA_VULCAN = 104
|
val errorText: Int,
|
||||||
const val CAPTCHA_LIBRUS = 202
|
) {
|
||||||
const val OAUTH_USOS = 701
|
enum class Type {
|
||||||
|
RECAPTCHA,
|
||||||
|
OAUTH,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.interfaces
|
package pl.szczodrzynski.edziennik.data.api.interfaces
|
||||||
|
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Feature
|
import pl.szczodrzynski.edziennik.data.api.models.Feature
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
|
import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
|
||||||
|
|
||||||
@ -14,4 +15,5 @@ import pl.szczodrzynski.edziennik.data.api.models.LoginMethod
|
|||||||
*/
|
*/
|
||||||
interface EdziennikCallback : EndpointCallback {
|
interface EdziennikCallback : EndpointCallback {
|
||||||
fun onCompleted()
|
fun onCompleted()
|
||||||
|
fun onRequiresUserAction(event: UserActionRequiredEvent)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package pl.szczodrzynski.edziennik.data.api.models
|
package pl.szczodrzynski.edziennik.data.api.models
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
import android.util.LongSparseArray
|
import android.util.LongSparseArray
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import androidx.core.util.set
|
import androidx.core.util.set
|
||||||
@ -12,7 +13,8 @@ import pl.szczodrzynski.edziennik.BuildConfig
|
|||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_REQUEST_FAILURE
|
import pl.szczodrzynski.edziennik.data.api.ERROR_REQUEST_FAILURE
|
||||||
import pl.szczodrzynski.edziennik.data.api.Regexes.MESSAGE_META
|
import pl.szczodrzynski.edziennik.data.api.Regexes.MESSAGE_META
|
||||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EndpointCallback
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||||
import pl.szczodrzynski.edziennik.data.db.entity.*
|
import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||||
import pl.szczodrzynski.edziennik.ext.*
|
import pl.szczodrzynski.edziennik.ext.*
|
||||||
@ -37,7 +39,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
|
|||||||
/**
|
/**
|
||||||
* A callback passed to all [Feature]s and [LoginMethod]s
|
* A callback passed to all [Feature]s and [LoginMethod]s
|
||||||
*/
|
*/
|
||||||
lateinit var callback: EndpointCallback
|
lateinit var callback: EdziennikCallback
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of [LoginMethod]s *already fulfilled* during this sync.
|
* A list of [LoginMethod]s *already fulfilled* during this sync.
|
||||||
@ -374,6 +376,15 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
|
|||||||
callback.onError(apiError)
|
callback.onError(apiError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun requireUserAction(type: UserActionRequiredEvent.Type, params: Bundle, errorText: Int) {
|
||||||
|
callback.onRequiresUserAction(UserActionRequiredEvent(
|
||||||
|
profileId = profile?.id,
|
||||||
|
type = type,
|
||||||
|
params = params,
|
||||||
|
errorText = errorText,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
fun progress(step: Float) {
|
fun progress(step: Float) {
|
||||||
callback.onProgress(step)
|
callback.onProgress(step)
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,15 @@ fun Bundle?.getFloat(key: String, defaultValue: Float): Float {
|
|||||||
fun Bundle?.getString(key: String, defaultValue: String): String {
|
fun Bundle?.getString(key: String, defaultValue: String): String {
|
||||||
return this?.getString(key, defaultValue) ?: defaultValue
|
return this?.getString(key, defaultValue) ?: defaultValue
|
||||||
}
|
}
|
||||||
|
inline fun <reified E : Enum<E>> Bundle?.getEnum(key: String): E? {
|
||||||
|
return this?.getString(key)?.let {
|
||||||
|
try {
|
||||||
|
enumValueOf<E>(it)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Bundle?.getIntOrNull(key: String): Int? {
|
fun Bundle?.getIntOrNull(key: String): Int? {
|
||||||
return this?.get(key) as? Int
|
return this?.get(key) as? Int
|
||||||
@ -48,6 +57,7 @@ fun Bundle(vararg properties: Pair<String, Any?>): Bundle {
|
|||||||
is Bundle -> putBundle(property.first, property.second as Bundle)
|
is Bundle -> putBundle(property.first, property.second as Bundle)
|
||||||
is Parcelable -> putParcelable(property.first, property.second as Parcelable)
|
is Parcelable -> putParcelable(property.first, property.second as Parcelable)
|
||||||
is Array<*> -> putParcelableArray(property.first, property.second as Array<out Parcelable>)
|
is Array<*> -> putParcelableArray(property.first, property.second as Array<out Parcelable>)
|
||||||
|
is Enum<*> -> putString(property.first, (property.second as Enum<*>).name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,16 @@ import pl.szczodrzynski.edziennik.databinding.RecaptchaViewBinding
|
|||||||
import pl.szczodrzynski.edziennik.ext.onClick
|
import pl.szczodrzynski.edziennik.ext.onClick
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.base.BindingDialog
|
||||||
|
|
||||||
class LibrusCaptchaDialog(
|
class RecaptchaPromptDialog(
|
||||||
activity: AppCompatActivity,
|
activity: AppCompatActivity,
|
||||||
|
private val siteKey: String,
|
||||||
|
private val referer: String,
|
||||||
private val onSuccess: (recaptchaCode: String) -> Unit,
|
private val onSuccess: (recaptchaCode: String) -> Unit,
|
||||||
private val onFailure: (() -> Unit)?,
|
private val onCancel: (() -> Unit)?,
|
||||||
onShowListener: ((tag: String) -> Unit)? = null,
|
onShowListener: ((tag: String) -> Unit)? = null,
|
||||||
onDismissListener: ((tag: String) -> Unit)? = null,
|
onDismissListener: ((tag: String) -> Unit)? = null,
|
||||||
) : BindingDialog<RecaptchaViewBinding>(activity, onShowListener, onDismissListener) {
|
) : BindingDialog<RecaptchaViewBinding>(activity, onShowListener, onDismissListener) {
|
||||||
override val TAG = "LibrusCaptchaDialog"
|
override val TAG = "RecaptchaPromptDialog"
|
||||||
|
|
||||||
override fun getTitleRes(): Int? = null
|
override fun getTitleRes(): Int? = null
|
||||||
override fun inflate(layoutInflater: LayoutInflater) =
|
override fun inflate(layoutInflater: LayoutInflater) =
|
||||||
@ -46,8 +48,8 @@ class LibrusCaptchaDialog(
|
|||||||
b.progress.visibility = View.VISIBLE
|
b.progress.visibility = View.VISIBLE
|
||||||
RecaptchaDialog(
|
RecaptchaDialog(
|
||||||
activity,
|
activity,
|
||||||
siteKey = "6Lf48moUAAAAAB9ClhdvHr46gRWR-CN31CXQPG2U",
|
siteKey = siteKey,
|
||||||
referer = "https://portal.librus.pl/rodzina/login",
|
referer = referer,
|
||||||
onSuccess = { recaptchaCode ->
|
onSuccess = { recaptchaCode ->
|
||||||
b.checkbox.background = checkboxBackground
|
b.checkbox.background = checkboxBackground
|
||||||
b.checkbox.foreground = checkboxForeground
|
b.checkbox.foreground = checkboxForeground
|
||||||
@ -67,6 +69,6 @@ class LibrusCaptchaDialog(
|
|||||||
|
|
||||||
override fun onDismiss() {
|
override fun onDismiss() {
|
||||||
if (!success)
|
if (!success)
|
||||||
onFailure?.invoke()
|
onCancel?.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,7 +27,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
|||||||
import pl.szczodrzynski.edziennik.databinding.CardHomeDebugBinding
|
import pl.szczodrzynski.edziennik.databinding.CardHomeDebugBinding
|
||||||
import pl.szczodrzynski.edziennik.ext.dp
|
import pl.szczodrzynski.edziennik.ext.dp
|
||||||
import pl.szczodrzynski.edziennik.ext.onClick
|
import pl.szczodrzynski.edziennik.ext.onClick
|
||||||
import pl.szczodrzynski.edziennik.ui.captcha.LibrusCaptchaDialog
|
import pl.szczodrzynski.edziennik.ui.captcha.RecaptchaPromptDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.home.HomeCard
|
import pl.szczodrzynski.edziennik.ui.home.HomeCard
|
||||||
import pl.szczodrzynski.edziennik.ui.home.HomeCardAdapter
|
import pl.szczodrzynski.edziennik.ui.home.HomeCardAdapter
|
||||||
import pl.szczodrzynski.edziennik.ui.home.HomeFragment
|
import pl.szczodrzynski.edziennik.ui.home.HomeFragment
|
||||||
@ -85,11 +85,6 @@ class HomeDebugCard(
|
|||||||
app.startActivity(Chucker.getLaunchIntent(activity, 1));
|
app.startActivity(Chucker.getLaunchIntent(activity, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
b.librusCaptchaButton.onClick {
|
|
||||||
//app.startActivity(Intent(activity, LoginLibrusCaptchaActivity::class.java))
|
|
||||||
LibrusCaptchaDialog(activity, onSuccess = {}, onFailure = {}).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
b.getLogs.onClick {
|
b.getLogs.onClick {
|
||||||
val logs = HyperLog.getDeviceLogsInFile(activity, true)
|
val logs = HyperLog.getDeviceLogsInFile(activity, true)
|
||||||
val intent = Intent(Intent.ACTION_SEND)
|
val intent = Intent(Intent.ACTION_SEND)
|
||||||
|
@ -65,7 +65,6 @@ object LoginInfo {
|
|||||||
errorCodes = mapOf(
|
errorCodes = mapOf(
|
||||||
ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED to R.string.login_error_account_not_activated,
|
ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED to R.string.login_error_account_not_activated,
|
||||||
ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password,
|
ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN to R.string.login_error_incorrect_login_or_password,
|
||||||
ERROR_CAPTCHA_LIBRUS_PORTAL to R.string.error_3001_reason
|
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
/*Mode(
|
/*Mode(
|
||||||
|
@ -19,7 +19,7 @@ import org.greenrobot.eventbus.Subscribe
|
|||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_CAPTCHA_NEEDED
|
import pl.szczodrzynski.edziennik.data.api.ERROR_REQUIRES_USER_ACTION
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_NO_ARGUMENTS
|
import pl.szczodrzynski.edziennik.data.api.LOGIN_NO_ARGUMENTS
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
|
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskErrorEvent
|
||||||
@ -29,6 +29,7 @@ import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|||||||
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.entity.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.databinding.LoginProgressFragmentBinding
|
import pl.szczodrzynski.edziennik.databinding.LoginProgressFragmentBinding
|
||||||
import pl.szczodrzynski.edziennik.ext.joinNotNullStrings
|
import pl.szczodrzynski.edziennik.ext.joinNotNullStrings
|
||||||
|
import pl.szczodrzynski.edziennik.utils.managers.UserActionManager
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
@ -137,13 +138,21 @@ class LoginProgressFragment : Fragment(), CoroutineScope {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
app.userActionManager.execute(activity, event.profileId, event.type, event.params, onSuccess = { params ->
|
val callback = UserActionManager.UserActionCallback(
|
||||||
args.putAll(params)
|
onSuccess = { data ->
|
||||||
|
args.putAll(data)
|
||||||
doFirstLogin(args)
|
doFirstLogin(args)
|
||||||
}, onFailure = {
|
},
|
||||||
activity.error(ApiError(TAG, ERROR_CAPTCHA_NEEDED))
|
onFailure = {
|
||||||
|
activity.error(ApiError(TAG, ERROR_REQUIRES_USER_ACTION))
|
||||||
nav.navigateUp()
|
nav.navigateUp()
|
||||||
})
|
},
|
||||||
|
onCancel = {
|
||||||
|
nav.navigateUp()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
app.userActionManager.execute(activity, event, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
|
@ -16,13 +16,10 @@ import org.greenrobot.eventbus.ThreadMode
|
|||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.MainActivity
|
import pl.szczodrzynski.edziennik.MainActivity
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_CAPTCHA_LIBRUS_PORTAL
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.ERROR_USOS_OAUTH_LOGIN_REQUEST
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
import pl.szczodrzynski.edziennik.data.api.edziennik.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
import pl.szczodrzynski.edziennik.data.api.events.UserActionRequiredEvent
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
|
||||||
import pl.szczodrzynski.edziennik.ext.*
|
import pl.szczodrzynski.edziennik.ext.*
|
||||||
import pl.szczodrzynski.edziennik.ui.captcha.LibrusCaptchaDialog
|
import pl.szczodrzynski.edziennik.ui.captcha.RecaptchaPromptDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.login.oauth.OAuthLoginActivity
|
import pl.szczodrzynski.edziennik.ui.login.oauth.OAuthLoginActivity
|
||||||
import pl.szczodrzynski.edziennik.ui.login.oauth.OAuthLoginResult
|
import pl.szczodrzynski.edziennik.ui.login.oauth.OAuthLoginResult
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
@ -32,43 +29,31 @@ class UserActionManager(val app: App) {
|
|||||||
private const val TAG = "UserActionManager"
|
private const val TAG = "UserActionManager"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requiresUserAction(apiError: ApiError) = when (apiError.errorCode) {
|
fun sendToUser(event: UserActionRequiredEvent) {
|
||||||
ERROR_CAPTCHA_LIBRUS_PORTAL -> true
|
|
||||||
ERROR_USOS_OAUTH_LOGIN_REQUEST -> true
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendToUser(apiError: ApiError) {
|
|
||||||
val type = when (apiError.errorCode) {
|
|
||||||
ERROR_CAPTCHA_LIBRUS_PORTAL -> UserActionRequiredEvent.CAPTCHA_LIBRUS
|
|
||||||
ERROR_USOS_OAUTH_LOGIN_REQUEST -> UserActionRequiredEvent.OAUTH_USOS
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EventBus.getDefault().hasSubscriberForEvent(UserActionRequiredEvent::class.java)) {
|
if (EventBus.getDefault().hasSubscriberForEvent(UserActionRequiredEvent::class.java)) {
|
||||||
EventBus.getDefault().post(UserActionRequiredEvent(apiError.profileId ?: -1, type, apiError.params))
|
EventBus.getDefault().post(event)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val manager = app.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
val manager = app.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
val text = app.getString(event.errorText, event.profileId)
|
||||||
val text = app.getString(when (type) {
|
|
||||||
UserActionRequiredEvent.CAPTCHA_LIBRUS -> R.string.notification_user_action_required_captcha_librus
|
|
||||||
UserActionRequiredEvent.OAUTH_USOS -> R.string.notification_user_action_required_oauth_usos
|
|
||||||
else -> R.string.notification_user_action_required_text
|
|
||||||
}, apiError.profileId)
|
|
||||||
|
|
||||||
val intent = Intent(
|
val intent = Intent(
|
||||||
app,
|
app,
|
||||||
MainActivity::class.java,
|
MainActivity::class.java,
|
||||||
"action" to "userActionRequired",
|
"action" to "userActionRequired",
|
||||||
"profileId" to (apiError.profileId ?: -1),
|
"profileId" to event.profileId,
|
||||||
"type" to type,
|
"type" to event.type,
|
||||||
"params" to apiError.params,
|
"params" to event.params,
|
||||||
|
)
|
||||||
|
val pendingIntent = PendingIntent.getActivity(
|
||||||
|
app,
|
||||||
|
System.currentTimeMillis().toInt(),
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_ONE_SHOT or pendingIntentFlag(),
|
||||||
)
|
)
|
||||||
val pendingIntent = PendingIntent.getActivity(app, System.currentTimeMillis().toInt(), intent, PendingIntent.FLAG_ONE_SHOT or pendingIntentFlag())
|
|
||||||
|
|
||||||
val notification = NotificationCompat.Builder(app, app.notificationChannelsManager.userAttention.key)
|
val notification =
|
||||||
|
NotificationCompat.Builder(app, app.notificationChannelsManager.userAttention.key)
|
||||||
.setContentTitle(app.getString(R.string.notification_user_action_required_title))
|
.setContentTitle(app.getString(R.string.notification_user_action_required_title))
|
||||||
.setContentText(text)
|
.setContentText(text)
|
||||||
.setSmallIcon(R.drawable.ic_error_outline)
|
.setSmallIcon(R.drawable.ic_error_outline)
|
||||||
@ -84,70 +69,56 @@ class UserActionManager(val app: App) {
|
|||||||
manager.notify(System.currentTimeMillis().toInt(), notification)
|
manager.notify(System.currentTimeMillis().toInt(), notification)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UserActionCallback(
|
||||||
|
val onSuccess: ((data: Bundle) -> Unit)? = null,
|
||||||
|
val onFailure: (() -> Unit)? = null,
|
||||||
|
val onCancel: (() -> Unit)? = null,
|
||||||
|
)
|
||||||
|
|
||||||
fun execute(
|
fun execute(
|
||||||
activity: AppCompatActivity,
|
activity: AppCompatActivity,
|
||||||
profileId: Int?,
|
event: UserActionRequiredEvent,
|
||||||
type: Int,
|
callback: UserActionCallback,
|
||||||
params: Bundle? = null,
|
|
||||||
onSuccess: ((params: Bundle) -> Unit)? = null,
|
|
||||||
onFailure: (() -> Unit)? = null
|
|
||||||
) {
|
) {
|
||||||
d(TAG, "Running user action ($type) with params: ${params?.toJsonObject()}")
|
d(TAG, "Running user action (${event.type}) with params: ${event.params}")
|
||||||
val isSuccessful = when (type) {
|
val isSuccessful = when (event.type) {
|
||||||
UserActionRequiredEvent.CAPTCHA_LIBRUS -> executeLibrus(activity, profileId, params, onSuccess, onFailure)
|
UserActionRequiredEvent.Type.RECAPTCHA -> executeRecaptcha(activity, event, callback)
|
||||||
UserActionRequiredEvent.OAUTH_USOS -> executeOauth(activity, profileId, params, onSuccess, onFailure)
|
UserActionRequiredEvent.Type.OAUTH -> executeOauth(activity, event, callback)
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
if (!isSuccessful) {
|
|
||||||
onFailure?.invoke()
|
|
||||||
}
|
}
|
||||||
|
if (!isSuccessful)
|
||||||
|
callback.onFailure?.invoke()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun executeLibrus(
|
private fun executeRecaptcha(
|
||||||
activity: AppCompatActivity,
|
activity: AppCompatActivity,
|
||||||
profileId: Int?,
|
event: UserActionRequiredEvent,
|
||||||
params: Bundle?,
|
callback: UserActionCallback,
|
||||||
onSuccess: ((params: Bundle) -> Unit)?,
|
|
||||||
onFailure: (() -> Unit)?,
|
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (profileId == null)
|
val siteKey = event.params.getString("siteKey") ?: return false
|
||||||
return false
|
val referer = event.params.getString("referer") ?: return false
|
||||||
val extras = params?.getBundle("extras")
|
RecaptchaPromptDialog(
|
||||||
// show captcha dialog
|
|
||||||
// use passed onSuccess listener, else sync profile
|
|
||||||
LibrusCaptchaDialog(
|
|
||||||
activity = activity,
|
activity = activity,
|
||||||
|
siteKey = siteKey,
|
||||||
|
referer = referer,
|
||||||
onSuccess = { code ->
|
onSuccess = { code ->
|
||||||
val args = Bundle(
|
finishAction(activity, event, callback, Bundle(
|
||||||
"recaptchaCode" to code,
|
"recaptchaCode" to code,
|
||||||
"recaptchaTime" to System.currentTimeMillis(),
|
"recaptchaTime" to System.currentTimeMillis(),
|
||||||
)
|
))
|
||||||
if (extras != null)
|
|
||||||
args.putAll(extras)
|
|
||||||
|
|
||||||
if (onSuccess != null)
|
|
||||||
onSuccess(args)
|
|
||||||
else
|
|
||||||
EdziennikTask.syncProfile(profileId, arguments = args.toJsonObject()).enqueue(activity)
|
|
||||||
},
|
},
|
||||||
onFailure = onFailure,
|
onCancel = callback.onCancel,
|
||||||
).show()
|
).show()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun executeOauth(
|
private fun executeOauth(
|
||||||
activity: AppCompatActivity,
|
activity: AppCompatActivity,
|
||||||
profileId: Int?,
|
event: UserActionRequiredEvent,
|
||||||
params: Bundle?,
|
callback: UserActionCallback,
|
||||||
onSuccess: ((params: Bundle) -> Unit)?,
|
|
||||||
onFailure: (() -> Unit)?,
|
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (profileId == null || params == null)
|
val storeKey = event.params.getString("responseStoreKey") ?: return false
|
||||||
return false
|
event.params.getString("authorizeUrl") ?: return false
|
||||||
val extras = params.getBundle("extras")
|
event.params.getString("redirectUrl") ?: return false
|
||||||
val storeKey = params.getString("responseStoreKey") ?: return false
|
|
||||||
params.getString("authorizeUrl") ?: return false
|
|
||||||
params.getString("redirectUrl") ?: return false
|
|
||||||
|
|
||||||
var listener: Any? = null
|
var listener: Any? = null
|
||||||
listener = object {
|
listener = object {
|
||||||
@ -155,26 +126,41 @@ class UserActionManager(val app: App) {
|
|||||||
fun onOAuthLoginResult(result: OAuthLoginResult) {
|
fun onOAuthLoginResult(result: OAuthLoginResult) {
|
||||||
EventBus.getDefault().unregister(listener)
|
EventBus.getDefault().unregister(listener)
|
||||||
when {
|
when {
|
||||||
result.isError -> onFailure?.invoke()
|
result.isError -> callback.onFailure?.invoke()
|
||||||
result.responseUrl != null -> {
|
result.responseUrl != null -> {
|
||||||
val args = Bundle(
|
finishAction(activity, event, callback, Bundle(
|
||||||
storeKey to result.responseUrl,
|
storeKey to result.responseUrl,
|
||||||
)
|
))
|
||||||
if (extras != null)
|
|
||||||
args.putAll(extras)
|
|
||||||
|
|
||||||
if (onSuccess != null)
|
|
||||||
onSuccess(args)
|
|
||||||
else
|
|
||||||
EdziennikTask.syncProfile(profileId, arguments = args.toJsonObject()).enqueue(activity)
|
|
||||||
}
|
}
|
||||||
|
else -> callback.onCancel?.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EventBus.getDefault().register(listener)
|
EventBus.getDefault().register(listener)
|
||||||
|
|
||||||
val intent = Intent(activity, OAuthLoginActivity::class.java).putExtras(params)
|
val intent = Intent(activity, OAuthLoginActivity::class.java).putExtras(event.params)
|
||||||
activity.startActivity(intent)
|
activity.startActivity(intent)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun finishAction(
|
||||||
|
activity: AppCompatActivity,
|
||||||
|
event: UserActionRequiredEvent,
|
||||||
|
callback: UserActionCallback,
|
||||||
|
data: Bundle,
|
||||||
|
) {
|
||||||
|
val extras = event.params.getBundle("extras")
|
||||||
|
if (extras != null)
|
||||||
|
data.putAll(extras)
|
||||||
|
|
||||||
|
if (callback.onSuccess != null)
|
||||||
|
callback.onSuccess.invoke(data)
|
||||||
|
else if (event.profileId != null)
|
||||||
|
EdziennikTask.syncProfile(
|
||||||
|
profileId = event.profileId,
|
||||||
|
arguments = data.toJsonObject(),
|
||||||
|
).enqueue(activity)
|
||||||
|
else
|
||||||
|
callback.onFailure?.invoke()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,13 +25,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Save Debug Logs" />
|
android:text="Save Debug Logs" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/librusCaptchaButton"
|
|
||||||
style="@style/Widget.MaterialComponents.Button"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="LIBRUS® Captcha" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/refreshWidget"
|
android:id="@+id/refreshWidget"
|
||||||
style="@style/Widget.MaterialComponents.Button"
|
style="@style/Widget.MaterialComponents.Button"
|
||||||
|
@ -31,11 +31,6 @@
|
|||||||
<string name="error_112" translatable="false">ERROR_NOT_IMPLEMENTED</string>
|
<string name="error_112" translatable="false">ERROR_NOT_IMPLEMENTED</string>
|
||||||
<string name="error_113" translatable="false">ERROR_FILE_DOWNLOAD</string>
|
<string name="error_113" translatable="false">ERROR_FILE_DOWNLOAD</string>
|
||||||
|
|
||||||
<string name="error_115" translatable="false">ERROR_NO_STUDENTS_IN_ACCOUNT</string>
|
|
||||||
|
|
||||||
<string name="error_3000" translatable="false">ERROR_CAPTCHA_NEEDED</string>
|
|
||||||
<string name="error_3001" translatable="false">ERROR_CAPTCHA_LIBRUS_PORTAL</string>
|
|
||||||
|
|
||||||
<string name="error_5000" translatable="false">ERROR_API_PDO_ERROR</string>
|
<string name="error_5000" translatable="false">ERROR_API_PDO_ERROR</string>
|
||||||
<string name="error_5001" translatable="false">ERROR_API_INVALID_CLIENT</string>
|
<string name="error_5001" translatable="false">ERROR_API_INVALID_CLIENT</string>
|
||||||
<string name="error_5002" translatable="false">ERROR_API_INVALID_ARGUMENT</string>
|
<string name="error_5002" translatable="false">ERROR_API_INVALID_ARGUMENT</string>
|
||||||
@ -174,8 +169,6 @@
|
|||||||
<string name="error_631" translatable="false">ERROR_PODLASIE_API_OTHER</string>
|
<string name="error_631" translatable="false">ERROR_PODLASIE_API_OTHER</string>
|
||||||
<string name="error_632" translatable="false">ERROR_PODLASIE_API_DATA_MISSING</string>
|
<string name="error_632" translatable="false">ERROR_PODLASIE_API_DATA_MISSING</string>
|
||||||
|
|
||||||
<string name="error_701" translatable="false">ERROR_USOS_OAUTH_LOGIN_REQUEST</string>
|
|
||||||
|
|
||||||
<string name="error_801" translatable="false">ERROR_TEMPLATE_WEB_OTHER</string>
|
<string name="error_801" translatable="false">ERROR_TEMPLATE_WEB_OTHER</string>
|
||||||
|
|
||||||
<string name="error_900" translatable="false">EXCEPTION_API_TASK</string>
|
<string name="error_900" translatable="false">EXCEPTION_API_TASK</string>
|
||||||
@ -223,11 +216,6 @@
|
|||||||
<string name="error_112_reason">Nie zaimplementowano</string>
|
<string name="error_112_reason">Nie zaimplementowano</string>
|
||||||
<string name="error_113_reason">Wystąpił błąd podczas pobierania pliku. Dziennik może być przeciążony lub mieć przerwę techniczną.</string>
|
<string name="error_113_reason">Wystąpił błąd podczas pobierania pliku. Dziennik może być przeciążony lub mieć przerwę techniczną.</string>
|
||||||
|
|
||||||
<string name="error_115_reason">Brak uczniów przypisanych do konta</string>
|
|
||||||
|
|
||||||
<string name="error_3000_reason">Wymagane rozwiązanie zadania Captcha</string>
|
|
||||||
<string name="error_3001_reason">LIBRUS®️: wymagane rozwiązanie zadania Captcha</string>
|
|
||||||
|
|
||||||
<string name="error_5000_reason">ERROR_API_PDO_ERROR</string>
|
<string name="error_5000_reason">ERROR_API_PDO_ERROR</string>
|
||||||
<string name="error_5001_reason">Nieprawidłowy ID klienta API</string>
|
<string name="error_5001_reason">Nieprawidłowy ID klienta API</string>
|
||||||
<string name="error_5002_reason">API: nieprawidłowy argument</string>
|
<string name="error_5002_reason">API: nieprawidłowy argument</string>
|
||||||
@ -366,8 +354,6 @@
|
|||||||
<string name="error_631_reason">ERROR_PODLASIE_API_OTHER</string>
|
<string name="error_631_reason">ERROR_PODLASIE_API_OTHER</string>
|
||||||
<string name="error_632_reason">Brak danych. Zgłoś błąd programiście.</string>
|
<string name="error_632_reason">Brak danych. Zgłoś błąd programiście.</string>
|
||||||
|
|
||||||
<string name="error_701_reason">Wymagane logowanie w przeglądarce</string>
|
|
||||||
|
|
||||||
<string name="error_801_reason">ERROR_TEMPLATE_WEB_OTHER</string>
|
<string name="error_801_reason">ERROR_TEMPLATE_WEB_OTHER</string>
|
||||||
|
|
||||||
<string name="error_900_reason">Błąd synchronizacji. Upewnij się, że masz połączenie z internetem, a następnie zgłoś błąd.</string>
|
<string name="error_900_reason">Błąd synchronizacji. Upewnij się, że masz połączenie z internetem, a następnie zgłoś błąd.</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user