mirror of
https://github.com/wulkanowy/wulkanowy.git
synced 2025-02-21 19:24:44 +01:00
Add a custom error message for ssl errors due to invalid clock setting (#1742)
This commit is contained in:
parent
8877322357
commit
aff1a7030d
@ -16,15 +16,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import io.github.wulkanowy.R
|
import io.github.wulkanowy.R
|
||||||
import io.github.wulkanowy.databinding.DialogErrorBinding
|
import io.github.wulkanowy.databinding.DialogErrorBinding
|
||||||
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.ServiceUnavailableException
|
|
||||||
import io.github.wulkanowy.utils.*
|
import io.github.wulkanowy.utils.*
|
||||||
import okhttp3.internal.http2.StreamResetException
|
|
||||||
import java.io.InterruptedIOException
|
|
||||||
import java.net.ConnectException
|
|
||||||
import java.net.SocketTimeoutException
|
|
||||||
import java.net.UnknownHostException
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
@ -67,7 +59,7 @@ class ErrorDialog : DialogFragment() {
|
|||||||
|
|
||||||
private fun DialogErrorBinding.bindErrorDetails(error: Throwable) {
|
private fun DialogErrorBinding.bindErrorDetails(error: Throwable) {
|
||||||
return with(this) {
|
return with(this) {
|
||||||
errorDialogHumanizedMessage.text = resources.getString(error)
|
errorDialogHumanizedMessage.text = resources.getErrorString(error)
|
||||||
errorDialogErrorMessage.text = error.localizedMessage
|
errorDialogErrorMessage.text = error.localizedMessage
|
||||||
errorDialogErrorMessage.isGone = error.localizedMessage.isNullOrBlank()
|
errorDialogErrorMessage.isGone = error.localizedMessage.isNullOrBlank()
|
||||||
errorDialogContent.text = error.stackTraceToString()
|
errorDialogContent.text = error.stackTraceToString()
|
||||||
@ -77,22 +69,10 @@ class ErrorDialog : DialogFragment() {
|
|||||||
|
|
||||||
private fun AlertDialog.enableReportButtonIfErrorIsReportable(error: Throwable) {
|
private fun AlertDialog.enableReportButtonIfErrorIsReportable(error: Throwable) {
|
||||||
setOnShowListener {
|
setOnShowListener {
|
||||||
getButton(AlertDialog.BUTTON_NEUTRAL).isEnabled = isErrorShouldBeReported(error)
|
getButton(AlertDialog.BUTTON_NEUTRAL).isEnabled = error.isShouldBeReported()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isErrorShouldBeReported(error: Throwable): Boolean = when (error) {
|
|
||||||
is UnknownHostException,
|
|
||||||
is InterruptedIOException,
|
|
||||||
is ConnectException,
|
|
||||||
is StreamResetException,
|
|
||||||
is SocketTimeoutException,
|
|
||||||
is ServiceUnavailableException,
|
|
||||||
is FeatureDisabledException,
|
|
||||||
is FeatureNotAvailableException -> false
|
|
||||||
else -> true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun copyErrorToClipboard(errorStacktrace: String) {
|
private fun copyErrorToClipboard(errorStacktrace: String) {
|
||||||
val clip = ClipData.newPlainText("Error details", errorStacktrace)
|
val clip = ClipData.newPlainText("Error details", errorStacktrace)
|
||||||
requireActivity().getSystemService<ClipboardManager>()?.setPrimaryClip(clip)
|
requireActivity().getSystemService<ClipboardManager>()?.setPrimaryClip(clip)
|
||||||
|
@ -5,7 +5,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
|||||||
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
import io.github.wulkanowy.data.exceptions.NoCurrentStudentException
|
||||||
import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
|
import io.github.wulkanowy.sdk.scrapper.login.BadCredentialsException
|
||||||
import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException
|
import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException
|
||||||
import io.github.wulkanowy.utils.getString
|
import io.github.wulkanowy.utils.getErrorString
|
||||||
import io.github.wulkanowy.utils.security.ScramblerException
|
import io.github.wulkanowy.utils.security.ScramblerException
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -26,7 +26,7 @@ open class ErrorHandler @Inject constructor(@ApplicationContext protected val co
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun proceed(error: Throwable) {
|
protected open fun proceed(error: Throwable) {
|
||||||
showErrorMessage(context.resources.getString(error), error)
|
showErrorMessage(context.resources.getErrorString(error), error)
|
||||||
when (error) {
|
when (error) {
|
||||||
is PasswordChangeRequiredException -> onPasswordChangeRequired(error.redirectUrl)
|
is PasswordChangeRequiredException -> onPasswordChangeRequired(error.redirectUrl)
|
||||||
is ScramblerException, is BadCredentialsException -> onSessionExpired()
|
is ScramblerException, is BadCredentialsException -> onSessionExpired()
|
||||||
|
@ -28,10 +28,7 @@ import io.github.wulkanowy.ui.modules.message.MessageFragment
|
|||||||
import io.github.wulkanowy.ui.modules.notificationscenter.NotificationsCenterFragment
|
import io.github.wulkanowy.ui.modules.notificationscenter.NotificationsCenterFragment
|
||||||
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
|
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
|
||||||
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
|
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
|
||||||
import io.github.wulkanowy.utils.capitalise
|
import io.github.wulkanowy.utils.*
|
||||||
import io.github.wulkanowy.utils.getThemeAttrColor
|
|
||||||
import io.github.wulkanowy.utils.openInternetBrowser
|
|
||||||
import io.github.wulkanowy.utils.toFormattedString
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -178,8 +175,8 @@ class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragme
|
|||||||
binding.dashboardErrorContainer.isVisible = show
|
binding.dashboardErrorContainer.isVisible = show
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setErrorDetails(message: String) {
|
override fun setErrorDetails(error: Throwable) {
|
||||||
binding.dashboardErrorMessage.text = message
|
binding.dashboardErrorMessage.text = requireContext().resources.getErrorString(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun resetView() {
|
override fun resetView() {
|
||||||
|
@ -714,6 +714,7 @@ class DashboardPresenter @Inject constructor(
|
|||||||
if ((forceRefresh && wasGeneralError) || !forceRefresh) {
|
if ((forceRefresh && wasGeneralError) || !forceRefresh) {
|
||||||
showContent(false)
|
showContent(false)
|
||||||
showErrorView(true)
|
showErrorView(true)
|
||||||
|
setErrorDetails(lastError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ interface DashboardView : BaseView {
|
|||||||
|
|
||||||
fun showErrorView(show: Boolean)
|
fun showErrorView(show: Boolean)
|
||||||
|
|
||||||
fun setErrorDetails(message: String)
|
fun setErrorDetails(error: Throwable)
|
||||||
|
|
||||||
fun resetView()
|
fun resetView()
|
||||||
|
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
package io.github.wulkanowy.utils
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
|
import io.github.wulkanowy.R
|
||||||
|
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.exception.ScrapperException
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.exception.ServiceUnavailableException
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.login.NotLoggedInException
|
||||||
|
import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException
|
||||||
|
import okhttp3.internal.http2.StreamResetException
|
||||||
|
import java.io.InterruptedIOException
|
||||||
|
import java.net.ConnectException
|
||||||
|
import java.net.SocketException
|
||||||
|
import java.net.SocketTimeoutException
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
import java.security.cert.CertificateExpiredException
|
||||||
|
import java.security.cert.CertificateNotYetValidException
|
||||||
|
import javax.net.ssl.SSLHandshakeException
|
||||||
|
|
||||||
|
fun Resources.getErrorString(error: Throwable): String = when (error) {
|
||||||
|
is UnknownHostException -> R.string.error_no_internet
|
||||||
|
is SocketException,
|
||||||
|
is SocketTimeoutException,
|
||||||
|
is InterruptedIOException,
|
||||||
|
is ConnectException,
|
||||||
|
is StreamResetException -> R.string.error_timeout
|
||||||
|
is NotLoggedInException -> R.string.error_login_failed
|
||||||
|
is PasswordChangeRequiredException -> R.string.error_password_change_required
|
||||||
|
is ServiceUnavailableException -> R.string.error_service_unavailable
|
||||||
|
is FeatureDisabledException -> R.string.error_feature_disabled
|
||||||
|
is FeatureNotAvailableException -> R.string.error_feature_not_available
|
||||||
|
is VulcanException -> R.string.error_unknown_uonet
|
||||||
|
is ScrapperException -> R.string.error_unknown_app
|
||||||
|
is SSLHandshakeException -> when {
|
||||||
|
error.isCausedByCertificateNotValidNow() -> R.string.error_invalid_device_datetime
|
||||||
|
else -> R.string.error_timeout
|
||||||
|
}
|
||||||
|
else -> R.string.error_unknown
|
||||||
|
}.let { getString(it) }
|
||||||
|
|
||||||
|
fun Throwable.isShouldBeReported(): Boolean = when (this) {
|
||||||
|
is UnknownHostException,
|
||||||
|
is SocketException,
|
||||||
|
is SocketTimeoutException,
|
||||||
|
is InterruptedIOException,
|
||||||
|
is ConnectException,
|
||||||
|
is StreamResetException,
|
||||||
|
is ServiceUnavailableException,
|
||||||
|
is FeatureDisabledException,
|
||||||
|
is FeatureNotAvailableException -> false
|
||||||
|
is SSLHandshakeException -> when {
|
||||||
|
isCausedByCertificateNotValidNow() -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Throwable?.isCausedByCertificateNotValidNow(): Boolean {
|
||||||
|
var exception = this
|
||||||
|
do {
|
||||||
|
if (exception.isCertificateNotValidNow()) return true
|
||||||
|
|
||||||
|
exception = exception?.cause
|
||||||
|
} while (exception != null)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Throwable?.isCertificateNotValidNow(): Boolean {
|
||||||
|
val isNotYetValid = this is CertificateNotYetValidException
|
||||||
|
val isExpired = this is CertificateExpiredException
|
||||||
|
return isNotYetValid || isExpired
|
||||||
|
}
|
@ -1,34 +0,0 @@
|
|||||||
package io.github.wulkanowy.utils
|
|
||||||
|
|
||||||
import android.content.res.Resources
|
|
||||||
import io.github.wulkanowy.R
|
|
||||||
import io.github.wulkanowy.sdk.exception.FeatureNotAvailableException
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.FeatureDisabledException
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.ScrapperException
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.ServiceUnavailableException
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.exception.VulcanException
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.login.NotLoggedInException
|
|
||||||
import io.github.wulkanowy.sdk.scrapper.login.PasswordChangeRequiredException
|
|
||||||
import okhttp3.internal.http2.StreamResetException
|
|
||||||
import java.io.InterruptedIOException
|
|
||||||
import java.net.ConnectException
|
|
||||||
import java.net.SocketException
|
|
||||||
import java.net.SocketTimeoutException
|
|
||||||
import java.net.UnknownHostException
|
|
||||||
|
|
||||||
fun Resources.getString(error: Throwable) = when (error) {
|
|
||||||
is UnknownHostException -> getString(R.string.error_no_internet)
|
|
||||||
is SocketException,
|
|
||||||
is SocketTimeoutException,
|
|
||||||
is InterruptedIOException,
|
|
||||||
is ConnectException,
|
|
||||||
is StreamResetException -> getString(R.string.error_timeout)
|
|
||||||
is NotLoggedInException -> getString(R.string.error_login_failed)
|
|
||||||
is PasswordChangeRequiredException -> getString(R.string.error_password_change_required)
|
|
||||||
is ServiceUnavailableException -> getString(R.string.error_service_unavailable)
|
|
||||||
is FeatureDisabledException -> getString(R.string.error_feature_disabled)
|
|
||||||
is FeatureNotAvailableException -> getString(R.string.error_feature_not_available)
|
|
||||||
is VulcanException -> getString(R.string.error_unknown_uonet)
|
|
||||||
is ScrapperException -> getString(R.string.error_unknown_app)
|
|
||||||
else -> getString(R.string.error_unknown)
|
|
||||||
}
|
|
@ -767,6 +767,7 @@
|
|||||||
|
|
||||||
<!--Errors-->
|
<!--Errors-->
|
||||||
<string name="error_no_internet">No internet connection</string>
|
<string name="error_no_internet">No internet connection</string>
|
||||||
|
<string name="error_invalid_device_datetime">An error occurred. Check your device clock</string>
|
||||||
<string name="error_timeout">Connection to register failed. Servers can be overloaded. Please try again later</string>
|
<string name="error_timeout">Connection to register failed. Servers can be overloaded. Please try again later</string>
|
||||||
<string name="error_login_failed">Loading data failed. Please try again later</string>
|
<string name="error_login_failed">Loading data failed. Please try again later</string>
|
||||||
<string name="error_password_change_required">Register password change required</string>
|
<string name="error_password_change_required">Register password change required</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user