Implement V1 authentication

This commit is contained in:
Kirill Kamakin
2022-10-29 19:55:40 +02:00
parent 3d267f319f
commit 9bf9146a40
4 changed files with 30 additions and 9 deletions

View File

@@ -1,6 +1,10 @@
package gq.kirmanak.mealient.datasource package gq.kirmanak.mealient.datasource
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import okhttp3.ResponseBody
/** /**
* Like [runCatching] but rethrows [CancellationException] to support * Like [runCatching] but rethrows [CancellationException] to support
@@ -13,3 +17,6 @@ inline fun <T> runCatchingExceptCancel(block: () -> T): Result<T> = try {
} catch (e: Throwable) { } catch (e: Throwable) {
Result.failure(e) Result.failure(e)
} }
@OptIn(ExperimentalSerializationApi::class)
inline fun <reified R> ResponseBody.decode(json: Json): R = json.decodeFromStream(byteStream())

View File

@@ -2,13 +2,11 @@ package gq.kirmanak.mealient.datasource.v0
import gq.kirmanak.mealient.datasource.NetworkError import gq.kirmanak.mealient.datasource.NetworkError
import gq.kirmanak.mealient.datasource.NetworkRequestWrapper import gq.kirmanak.mealient.datasource.NetworkRequestWrapper
import gq.kirmanak.mealient.datasource.decode
import gq.kirmanak.mealient.datasource.v0.models.* import gq.kirmanak.mealient.datasource.v0.models.*
import gq.kirmanak.mealient.logging.Logger import gq.kirmanak.mealient.logging.Logger
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerializationException import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.decodeFromStream
import okhttp3.ResponseBody
import retrofit2.HttpException import retrofit2.HttpException
import java.net.ConnectException import java.net.ConnectException
import java.net.SocketTimeoutException import java.net.SocketTimeoutException
@@ -43,7 +41,7 @@ class MealieDataSourceV0Impl @Inject constructor(
logParameters = { "baseUrl = $baseUrl, username = $username, password = $password" } logParameters = { "baseUrl = $baseUrl, username = $username, password = $password" }
).map { it.accessToken }.getOrElse { ).map { it.accessToken }.getOrElse {
val errorBody = (it as? HttpException)?.response()?.errorBody() ?: throw it val errorBody = (it as? HttpException)?.response()?.errorBody() ?: throw it
val errorDetailV0 = errorBody.decode<ErrorDetailV0>() val errorDetailV0 = errorBody.decode<ErrorDetailV0>(json)
throw if (errorDetailV0.detail == "Unauthorized") NetworkError.Unauthorized(it) else it throw if (errorDetailV0.detail == "Unauthorized") NetworkError.Unauthorized(it) else it
} }
@@ -81,7 +79,4 @@ class MealieDataSourceV0Impl @Inject constructor(
logMethod = { "requestRecipeInfo" }, logMethod = { "requestRecipeInfo" },
logParameters = { "baseUrl = $baseUrl, token = $token, slug = $slug" } logParameters = { "baseUrl = $baseUrl, token = $token, slug = $slug" }
) )
@OptIn(ExperimentalSerializationApi::class)
private inline fun <reified R> ResponseBody.decode(): R = json.decodeFromStream(byteStream())
} }

View File

@@ -2,7 +2,9 @@ package gq.kirmanak.mealient.datasource.v1
import gq.kirmanak.mealient.datasource.NetworkError import gq.kirmanak.mealient.datasource.NetworkError
import gq.kirmanak.mealient.datasource.NetworkRequestWrapper import gq.kirmanak.mealient.datasource.NetworkRequestWrapper
import gq.kirmanak.mealient.datasource.decode
import gq.kirmanak.mealient.datasource.v0.models.AddRecipeRequestV0 import gq.kirmanak.mealient.datasource.v0.models.AddRecipeRequestV0
import gq.kirmanak.mealient.datasource.v1.models.ErrorDetailV1
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeResponseV1 import gq.kirmanak.mealient.datasource.v1.models.GetRecipeResponseV1
import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSummaryResponseV1 import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSummaryResponseV1
import gq.kirmanak.mealient.datasource.v1.models.VersionResponseV1 import gq.kirmanak.mealient.datasource.v1.models.VersionResponseV1
@@ -29,8 +31,18 @@ class MealieDataSourceV1Impl @Inject constructor(
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override suspend fun authenticate(baseUrl: String, username: String, password: String): String { override suspend fun authenticate(
TODO("Not yet implemented") baseUrl: String,
username: String,
password: String,
): String = networkRequestWrapper.makeCall(
block = { service.getToken("$baseUrl/api/auth/token", username, password) },
logMethod = { "authenticate" },
logParameters = { "baseUrl = $baseUrl, username = $username, password = $password" }
).map { it.accessToken }.getOrElse {
val errorBody = (it as? HttpException)?.response()?.errorBody() ?: throw it
val errorDetailV0 = errorBody.decode<ErrorDetailV1>(json)
throw if (errorDetailV0.detail == "Unauthorized") NetworkError.Unauthorized(it) else it
} }
override suspend fun getVersionInfo( override suspend fun getVersionInfo(

View File

@@ -0,0 +1,7 @@
package gq.kirmanak.mealient.datasource.v1.models
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class ErrorDetailV1(@SerialName("detail") val detail: String? = null)