[API/Szkolny] Fix user/device registration after API errors. (#111)

This commit is contained in:
Kuba Szczodrzyński 2021-10-28 12:11:00 +02:00 committed by GitHub
parent e02246f97d
commit 8745d7d526
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 51 deletions

View File

@ -28,6 +28,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage
import pl.szczodrzynski.edziennik.data.db.entity.Notification
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.ext.keys
import pl.szczodrzynski.edziennik.ext.md5
import pl.szczodrzynski.edziennik.ext.toApiError
import pl.szczodrzynski.edziennik.ext.toErrorCode
@ -126,7 +127,10 @@ class SzkolnyApi(val app: App) : CoroutineScope {
* or null if it's a HTTP call error.
*/
@Throws(Exception::class)
private inline fun <reified T> parseResponse(response: Response<ApiResponse<T>>): T {
private inline fun <reified T> parseResponse(
response: Response<ApiResponse<T>>,
updateDeviceHash: Boolean = false,
): T {
app.config.update = response.body()?.update?.let { update ->
if (update.versionCode > BuildConfig.VERSION_CODE) {
if (update.updateMandatory
@ -144,6 +148,14 @@ class SzkolnyApi(val app: App) : CoroutineScope {
}
if (response.isSuccessful && response.body()?.success == true) {
// update the device's hash on success
if (updateDeviceHash) {
val hash = getDevice()?.toString()?.md5()
if (hash != null) {
app.config.hash = hash
}
}
if (Unit is T) {
return Unit
}
@ -168,7 +180,6 @@ class SzkolnyApi(val app: App) : CoroutineScope {
throw SzkolnyApiException(body?.errors?.firstOrNull())
}
@Throws(Exception::class)
private fun getDevice() = run {
val config = app.config
val device = Device(
@ -181,51 +192,50 @@ class SzkolnyApi(val app: App) : CoroutineScope {
appVersionCode = BuildConfig.VERSION_CODE,
syncInterval = app.config.sync.interval
)
device.toString().md5().let {
if (it == config.hash)
null
else {
config.hash = it
device
}
}
val hash = device.toString().md5()
if (hash == config.hash)
return@run null
return@run device
}
@Throws(Exception::class)
fun getEvents(profiles: List<Profile>, notifications: List<Notification>, blacklistedIds: List<Long>, lastSyncTime: Long): List<EventFull> {
val teams = app.db.teamDao().allNow
val users = profiles.mapNotNull { profile ->
val config = app.config.getFor(profile.id)
val user = ServerSyncRequest.User(
profile.userCode,
profile.studentNameLong,
profile.studentNameShort,
profile.loginStoreType,
teams.filter { it.profileId == profile.id }.map { it.code }
)
val hash = user.toString().md5()
if (hash == config.hash)
return@mapNotNull null
return@mapNotNull user to config
}
val response = api.serverSync(ServerSyncRequest(
deviceId = app.deviceId,
device = getDevice(),
userCodes = profiles.map { it.userCode },
users = profiles.mapNotNull { profile ->
val config = app.config.getFor(profile.id)
val user = ServerSyncRequest.User(
profile.userCode,
profile.studentNameLong,
profile.studentNameShort,
profile.loginStoreType,
teams.filter { it.profileId == profile.id }.map { it.code }
)
user.toString().md5().let {
if (it == config.hash)
null
else {
config.hash = it
user
}
}
},
users = users.keys(),
lastSync = lastSyncTime,
notifications = notifications.map { ServerSyncRequest.Notification(it.profileName ?: "", it.type, it.text) }
)).execute()
val (events, hasBrowsers) = parseResponse(response)
val (events, hasBrowsers) = parseResponse(response, updateDeviceHash = true)
hasBrowsers?.let {
app.config.sync.webPushEnabled = it
}
// update users' hashes on success
users.forEach { (user, config) ->
config.hash = user.toString().md5()
}
val eventList = mutableListOf<EventFull>()
events.forEach { event ->
@ -270,7 +280,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
shareTeamCode = team.code,
event = event
)).execute()
parseResponse(response)
parseResponse(response, updateDeviceHash = true)
}
@Throws(Exception::class)
@ -284,7 +294,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
unshareTeamCode = team.code,
eventId = event.id
)).execute()
parseResponse(response)
parseResponse(response, updateDeviceHash = true)
}
/*fun eventEditRequest(requesterName: String, event: Event): ApiResponse<Nothing>? {
@ -301,7 +311,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
pairToken = pairToken
)).execute()
return parseResponse(response).browsers
return parseResponse(response, updateDeviceHash = true).browsers
}
@Throws(Exception::class)
@ -312,7 +322,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
action = "listBrowsers"
)).execute()
return parseResponse(response).browsers
return parseResponse(response, updateDeviceHash = true).browsers
}
@Throws(Exception::class)
@ -324,7 +334,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
browserId = browserId
)).execute()
return parseResponse(response).browsers
return parseResponse(response, updateDeviceHash = true).browsers
}
@Throws(Exception::class)
@ -335,7 +345,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
appVersion = BuildConfig.VERSION_NAME,
errors = errors
)).execute()
parseResponse(response)
parseResponse(response, updateDeviceHash = true)
}
@Throws(Exception::class)
@ -345,7 +355,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
device = getDevice(),
userCode = userCode
)).execute()
parseResponse(response)
parseResponse(response, updateDeviceHash = true)
}
@Throws(Exception::class)
@ -364,7 +374,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
text = text
)).execute()
return parseResponse(response).message
return parseResponse(response, updateDeviceHash = true).message
}
@Throws(Exception::class)

View File

@ -59,20 +59,8 @@ fun SparseIntArray.values(): List<Int> {
return result
}
fun <K, V> List<Pair<K, V>>.keys(): List<K> {
val result = mutableListOf<K>()
forEach { pair ->
result += pair.first
}
return result
}
fun <K, V> List<Pair<K, V>>.values(): List<V> {
val result = mutableListOf<V>()
forEach { pair ->
result += pair.second
}
return result
}
fun <K, V> List<Pair<K, V>>.keys() = map { it.first }
fun <K, V> List<Pair<K, V>>.values() = map { it.second }
fun <T> List<T>.toSparseArray(destination: SparseArray<T>, key: (T) -> Int) {
forEach {