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

View File

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