All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.features.auth.KtorAuthFeature.kt Maven / Gradle / Ivy

The newest version!
//package dev.inmo.time_tracker.lib.features.auth
//
//import dev.inmo.kslog.common.d
//import dev.inmo.kslog.common.logger
//import dev.inmo.micro_utils.common.Either
//import dev.inmo.micro_utils.common.either
//import dev.inmo.micro_utils.coroutines.SmartRWLocker
//import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
//import dev.inmo.micro_utils.coroutines.withReadAcquire
//import dev.inmo.micro_utils.coroutines.withWriteLock
//import dev.inmo.time_tracker.common.models.auth.Credentials
//import dev.inmo.time_tracker.common.models.user.RegisteredUser
//import dev.inmo.time_tracker.common.models.user.Username
//import io.ktor.client.*
//import io.ktor.client.call.*
//import io.ktor.client.plugins.*
//import io.ktor.client.request.*
//import io.ktor.http.*
//import io.ktor.http.HttpHeaders
//import kotlinx.coroutines.CoroutineScope
//import kotlinx.coroutines.Job
//import kotlinx.coroutines.sync.Mutex
//import kotlinx.coroutines.sync.withLock
//
//private object RequireRerequestRefreshException : Exception()
//
//class KtorAuthFeature(
//    private val credsRepo: CredsRepo,
//    private val baseUrl: String,
//    baseClient: HttpClient,
//    private val scope: CoroutineScope
//) : AuthFeature {
//    private val Log = logger
//    private val requestsLocker = SmartRWLocker()
//    private val anyAuthUrlPart = "$baseUrl/${AuthConstants.authRootPathPart}"
//    private val refreshUrl = "$baseUrl/${AuthConstants.authRootPathPart}/${AuthConstants.refreshPathPart}"
//    private val loginUrl = "$baseUrl/${AuthConstants.authRootPathPart}/${AuthConstants.loginPathPart}"
//    private val getMeUrl = "$baseUrl/${AuthConstants.authRootPathPart}/${AuthConstants.getMePathPart}"
//
//    internal val resultClient = baseClient.apply {
//        plugin(HttpSend).intercept { request ->
//            var serverAvailability = true
//            var resultCall: HttpClientCall? = null
//            val urlString = request.url.toString()
//            while (resultCall == null) {
//                if (requestsLocker.writeMutex.isLocked && (urlString.contains(anyAuthUrlPart))) {
//                    Log.d { "$urlString is some blocking auth request, pass response as is" }
//                    return@intercept execute(request)
//                }
//                resultCall = requestsLocker.withReadAcquire {
//                    val token = credsRepo.getCreds()
//                    if (token != null) {
//                        request.header(HttpHeaders.Authorization, token.token)
//                    }
//
//                    val originalCall = execute(request)
//                    val httpResponse = originalCall.response
//                    val httpRequest = originalCall.request
//
//                    val url = originalCall.request.url.toString()
//
//                    val apiUrlGetterValue = baseUrl
//
//                    when {
//
//                        url.replace(apiUrlGetterValue, "") == url -> {
//                            Log.d { "For response $httpResponse APIUrlGetter returned url not equal to the url with new base url, throwing an error" }
//                            null
//                        }
//
//                        httpResponse.status.value > HttpStatusCode.OK.value && httpResponse.status.value < HttpStatusCode.MultipleChoices.value -> {
//                            Log.d { "$httpResponse is ok or some other success answer, pass as is" }
//                            null
//                        }
//
//                        url.contains("${baseUrl}/${AuthConstants.authRootPathPart}") -> {
//                            Log.d { "$url is some auth request, pass response as is" }
//                            null
//                        }
//
//                        httpResponse.status.value >= 500 -> {
//                            if (url.contains("${baseUrl}/${AuthConstants.authRootPathPart}/${AuthConstants.refreshPathPart}")) {
//                                throw RequireRerequestRefreshException
//                            }
//                            Log.d { "$httpResponse is server error response, retry" }
//                            serverAvailability = when (httpResponse.status) {
//                                HttpStatusCode.BadGateway,
//                                HttpStatusCode.ServiceUnavailable,
//                                HttpStatusCode.GatewayTimeout -> false
//
//                                else -> true
//                            }
//                            originalCall
//                        }
//
//                        httpResponse.status != HttpStatusCode.Unauthorized -> {
//                            Log.d { "$httpResponse is not unauthorized response, pass response as is" }
//                            null
//                        }
//
//                        !httpRequest.headers.contains(HttpHeaders.Authorization) && token != null -> {
//                            Log.d { "$httpResponse is unauthorized, but request contains not token when token is presented locally" }
//                            null
//                        }
//
//                        else -> {
//                            Log.d { "$httpResponse is unauthorized response, retry" }
//                            triggerRefreshTokenJob()
//                            originalCall
//                        }
//                    }
//                }
//            }
//
//            resultCall
//        }
//    }
//
//    private var refreshTokenJob: Job? = null
//    private val refreshTokenMutex = Mutex()
//    private fun triggerRefreshTokenJob() {
//        scope.launchSafelyWithoutExceptions {
//            refreshTokenMutex.withLock {
//                if (refreshTokenJob == null) {
//                    refreshTokenJob = scope.launchSafelyWithoutExceptions {
//                        requestsLocker.withWriteLock {
//                            val token = credsRepo.getCreds() ?: return@launchSafelyWithoutExceptions
//                            val response = resultClient.post(
//                                refreshUrl
//                            ) {
//                                setBody(token.refresh.string)
//                            }.body()
//                            if (response != null) {
//                                credsRepo.saveCreds(response)
//                            } else {
//                                credsRepo.clearCreds()
//                            }
//                        }
//
//                        refreshTokenMutex.withLock {
//                            refreshTokenJob = null
//                        }
//                    }
//                }
//            }
//        }
//    }
//
//    override suspend fun getMe(): RegisteredUser? {
//        return resultClient.get(getMeUrl).body()
//    }
//
//    override suspend fun auth(username: Username, password: String): Either? {
//        refreshTokenMutex.withLock {
//            refreshTokenJob ?.cancel()
//        }
//        val token = resultClient.post(loginUrl) {
//            Credentials.Basic(username, password)
//        }.body()
//        return getMe() ?.either() ?: error("")
//    }
//
//    override suspend fun register(
//        username: Username,
//        password: String
//    ): Either? {
//        TODO("Not yet implemented")
//    }
//
//    override suspend fun logout(): Boolean {
//        TODO("Not yet implemented")
//    }
//}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy