diff --git a/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/DataSourceExtensions.kt b/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/DataSourceExtensions.kt index 6a10001..4b7f291 100644 --- a/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/DataSourceExtensions.kt +++ b/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/DataSourceExtensions.kt @@ -1,6 +1,10 @@ package gq.kirmanak.mealient.datasource 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 @@ -13,3 +17,6 @@ inline fun runCatchingExceptCancel(block: () -> T): Result = try { } catch (e: Throwable) { Result.failure(e) } + +@OptIn(ExperimentalSerializationApi::class) +inline fun ResponseBody.decode(json: Json): R = json.decodeFromStream(byteStream()) diff --git a/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v0/MealieDataSourceV0Impl.kt b/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v0/MealieDataSourceV0Impl.kt index d8fd7b8..641fb12 100644 --- a/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v0/MealieDataSourceV0Impl.kt +++ b/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v0/MealieDataSourceV0Impl.kt @@ -2,13 +2,11 @@ package gq.kirmanak.mealient.datasource.v0 import gq.kirmanak.mealient.datasource.NetworkError import gq.kirmanak.mealient.datasource.NetworkRequestWrapper +import gq.kirmanak.mealient.datasource.decode import gq.kirmanak.mealient.datasource.v0.models.* import gq.kirmanak.mealient.logging.Logger -import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.SerializationException import kotlinx.serialization.json.Json -import kotlinx.serialization.json.decodeFromStream -import okhttp3.ResponseBody import retrofit2.HttpException import java.net.ConnectException import java.net.SocketTimeoutException @@ -43,7 +41,7 @@ class MealieDataSourceV0Impl @Inject constructor( logParameters = { "baseUrl = $baseUrl, username = $username, password = $password" } ).map { it.accessToken }.getOrElse { val errorBody = (it as? HttpException)?.response()?.errorBody() ?: throw it - val errorDetailV0 = errorBody.decode() + val errorDetailV0 = errorBody.decode(json) throw if (errorDetailV0.detail == "Unauthorized") NetworkError.Unauthorized(it) else it } @@ -81,7 +79,4 @@ class MealieDataSourceV0Impl @Inject constructor( logMethod = { "requestRecipeInfo" }, logParameters = { "baseUrl = $baseUrl, token = $token, slug = $slug" } ) - - @OptIn(ExperimentalSerializationApi::class) - private inline fun ResponseBody.decode(): R = json.decodeFromStream(byteStream()) } diff --git a/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v1/MealieDataSourceV1Impl.kt b/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v1/MealieDataSourceV1Impl.kt index 965e1f7..0857a91 100644 --- a/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v1/MealieDataSourceV1Impl.kt +++ b/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v1/MealieDataSourceV1Impl.kt @@ -2,7 +2,9 @@ package gq.kirmanak.mealient.datasource.v1 import gq.kirmanak.mealient.datasource.NetworkError 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.v1.models.ErrorDetailV1 import gq.kirmanak.mealient.datasource.v1.models.GetRecipeResponseV1 import gq.kirmanak.mealient.datasource.v1.models.GetRecipeSummaryResponseV1 import gq.kirmanak.mealient.datasource.v1.models.VersionResponseV1 @@ -29,8 +31,18 @@ class MealieDataSourceV1Impl @Inject constructor( TODO("Not yet implemented") } - override suspend fun authenticate(baseUrl: String, username: String, password: String): String { - TODO("Not yet implemented") + override suspend fun authenticate( + 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(json) + throw if (errorDetailV0.detail == "Unauthorized") NetworkError.Unauthorized(it) else it } override suspend fun getVersionInfo( diff --git a/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v1/models/ErrorDetailV1.kt b/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v1/models/ErrorDetailV1.kt new file mode 100644 index 0000000..b3f1810 --- /dev/null +++ b/datasource/src/main/kotlin/gq/kirmanak/mealient/datasource/v1/models/ErrorDetailV1.kt @@ -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) \ No newline at end of file