2021-04-22 11:47:18 +02:00
|
|
|
package org.pixeldroid.app.utils.di
|
2020-07-26 20:56:01 +02:00
|
|
|
|
2021-04-22 11:47:18 +02:00
|
|
|
import org.pixeldroid.app.utils.api.PixelfedAPI
|
|
|
|
import org.pixeldroid.app.utils.api.objects.Token
|
|
|
|
import org.pixeldroid.app.utils.db.AppDatabase
|
|
|
|
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
2020-07-26 20:56:01 +02:00
|
|
|
import dagger.Module
|
|
|
|
import dagger.Provides
|
2024-02-10 18:43:07 +01:00
|
|
|
import dagger.hilt.InstallIn
|
|
|
|
import dagger.hilt.components.SingletonComponent
|
2020-12-29 19:34:48 +01:00
|
|
|
import kotlinx.coroutines.runBlocking
|
2020-11-29 20:19:25 +01:00
|
|
|
import okhttp3.*
|
2021-08-19 14:35:14 +02:00
|
|
|
import org.pixeldroid.app.utils.api.PixelfedAPI.Companion.apiForUser
|
2020-07-26 20:56:01 +02:00
|
|
|
import javax.inject.Singleton
|
|
|
|
|
|
|
|
@Module
|
2024-02-10 18:43:07 +01:00
|
|
|
@InstallIn(SingletonComponent::class)
|
|
|
|
class APIModule {
|
2020-07-26 20:56:01 +02:00
|
|
|
|
|
|
|
@Provides
|
|
|
|
@Singleton
|
|
|
|
fun providesAPIHolder(db: AppDatabase): PixelfedAPIHolder {
|
2020-12-29 19:34:48 +01:00
|
|
|
return PixelfedAPIHolder(db)
|
2020-07-26 20:56:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-18 22:32:50 +02:00
|
|
|
class TokenAuthenticator(val user: UserDatabaseEntity, val db: AppDatabase, val apiHolder: PixelfedAPIHolder) : Authenticator {
|
2020-11-29 20:19:25 +01:00
|
|
|
|
2020-12-26 12:10:54 +01:00
|
|
|
private val pixelfedAPI = PixelfedAPI.createFromUrl(user.instance_uri)
|
2020-11-29 20:19:25 +01:00
|
|
|
|
2021-04-18 22:32:50 +02:00
|
|
|
// Returns the number of tries for this response by walking through the priorResponses
|
|
|
|
private fun Response.responseCount(): Int {
|
|
|
|
var result = 1
|
|
|
|
var response: Response? = priorResponse
|
|
|
|
|
|
|
|
while (response != null) {
|
|
|
|
result++
|
|
|
|
response = response.priorResponse
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-29 20:19:25 +01:00
|
|
|
override fun authenticate(route: Route?, response: Response): Request? {
|
|
|
|
|
2021-04-18 22:32:50 +02:00
|
|
|
if (response.responseCount() > 3) {
|
|
|
|
return null // Give up, we've already failed to authenticate a couple times
|
2020-11-29 20:19:25 +01:00
|
|
|
}
|
|
|
|
// Refresh the access_token using a synchronous api request
|
2021-04-18 22:32:50 +02:00
|
|
|
val newAccessToken: Token = try {
|
2020-12-29 19:34:48 +01:00
|
|
|
runBlocking {
|
|
|
|
pixelfedAPI.obtainToken(
|
|
|
|
scope = "",
|
|
|
|
grant_type = "refresh_token",
|
|
|
|
refresh_token = user.refreshToken,
|
|
|
|
client_id = user.clientId,
|
|
|
|
client_secret = user.clientSecret
|
2021-04-18 22:32:50 +02:00
|
|
|
)
|
2020-12-29 19:34:48 +01:00
|
|
|
}
|
2024-02-10 18:43:07 +01:00
|
|
|
} catch (e: Exception){
|
2021-04-18 22:32:50 +02:00
|
|
|
return null
|
2020-12-29 19:34:48 +01:00
|
|
|
}
|
|
|
|
|
2021-04-18 22:32:50 +02:00
|
|
|
// Save the new access token and refresh token
|
|
|
|
if (newAccessToken.access_token != null && newAccessToken.refresh_token != null) {
|
|
|
|
db.userDao().updateAccessToken(
|
|
|
|
newAccessToken.access_token,
|
|
|
|
newAccessToken.refresh_token,
|
|
|
|
user.user_id, user.instance_uri
|
|
|
|
)
|
2021-04-20 14:07:18 +02:00
|
|
|
apiHolder.setToCurrentUser()
|
2020-12-29 19:34:48 +01:00
|
|
|
}
|
2020-11-29 20:19:25 +01:00
|
|
|
|
|
|
|
// Add new header to rejected request and retry it
|
|
|
|
return response.request.newBuilder()
|
2021-04-18 22:32:50 +02:00
|
|
|
.header("Authorization", "Bearer ${newAccessToken.access_token.orEmpty()}")
|
2020-11-29 20:19:25 +01:00
|
|
|
.build()
|
|
|
|
}
|
|
|
|
}
|
2020-07-26 20:56:01 +02:00
|
|
|
|
2021-04-20 14:07:18 +02:00
|
|
|
class PixelfedAPIHolder(private val db: AppDatabase){
|
2021-04-18 22:32:50 +02:00
|
|
|
|
2020-12-29 19:34:48 +01:00
|
|
|
var api: PixelfedAPI? =
|
2021-04-20 14:07:18 +02:00
|
|
|
db.userDao().getActiveUser()?.let {
|
|
|
|
setToCurrentUser(it)
|
2020-12-29 19:34:48 +01:00
|
|
|
}
|
2020-07-26 20:56:01 +02:00
|
|
|
|
2021-04-20 14:07:18 +02:00
|
|
|
fun setToCurrentUser(
|
2020-12-29 19:34:48 +01:00
|
|
|
user: UserDatabaseEntity = db.userDao().getActiveUser()!!
|
|
|
|
): PixelfedAPI {
|
2021-08-19 14:35:14 +02:00
|
|
|
val newAPI = apiForUser(user, db, this)
|
2020-07-26 20:56:01 +02:00
|
|
|
api = newAPI
|
|
|
|
return newAPI
|
|
|
|
}
|
|
|
|
}
|