Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Custom api environment #127

Merged
merged 9 commits into from
Dec 17, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Infomaniak SwissTransfer - Multiplatform
* Copyright (C) 2024 Infomaniak Network SA
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.infomaniak.multiplatform_swisstransfer.common.utils

sealed class ApiEnvironment(val baseUrl: String) {
data object Preprod : ApiEnvironment("https://swisstransfer.preprod.dev.infomaniak.ch")
data object Prod : ApiEnvironment("https://swisstransfer.com")
data class Custom(private val url: String) : ApiEnvironment(url)
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.infomaniak.multiplatform_swisstransfer

import com.infomaniak.multiplatform_swisstransfer.common.exceptions.RealmException
import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment
import com.infomaniak.multiplatform_swisstransfer.database.controllers.TransferController
import com.infomaniak.multiplatform_swisstransfer.database.controllers.UploadController
import com.infomaniak.multiplatform_swisstransfer.network.utils.SharedApiRoutes
Expand All @@ -27,12 +28,13 @@ import kotlin.coroutines.cancellation.CancellationException
* Utility class responsible for creating API URLs for shared routes.
*/
class SharedApiUrlCreator internal constructor(
private val environment: ApiEnvironment,
private val transferController: TransferController,
private val uploadController: UploadController,
) {
val createUploadContainerUrl: String = SharedApiRoutes.createUploadContainer
val createUploadContainerUrl: String = SharedApiRoutes.createUploadContainer(environment)

fun shareTransferUrl(transferUUID: String) = SharedApiRoutes.shareTransfer(transferUUID)
fun shareTransferUrl(transferUUID: String) = SharedApiRoutes.shareTransfer(environment, transferUUID)

@Throws(RealmException::class, CancellationException::class)
suspend fun downloadFilesUrl(transferUUID: String): String? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.infomaniak.multiplatform_swisstransfer

import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment
import com.infomaniak.multiplatform_swisstransfer.database.RealmProvider
import com.infomaniak.multiplatform_swisstransfer.database.controllers.*
import com.infomaniak.multiplatform_swisstransfer.managers.*
Expand All @@ -33,6 +34,7 @@ import com.infomaniak.multiplatform_swisstransfer.utils.EmailLanguageUtils
*
* This class serves as the main access point.
*
* @property environment Customize client api base url, for example [ApiEnvironment.Prod]
* @property userAgent Customize client api userAgent.
* @property transferManager A manager used to orchestrate transfer operations.
* @property appSettingsManager A manager used to orchestrate AppSettings operations.
Expand All @@ -42,14 +44,15 @@ import com.infomaniak.multiplatform_swisstransfer.utils.EmailLanguageUtils
* @property sharedApiUrlCreator An utils to help use shared routes.
*/
class SwissTransferInjection(
private val environment: ApiEnvironment,
private val userAgent: String,
) {

private val realmProvider by lazy { RealmProvider() }
private val apiClientProvider by lazy { ApiClientProvider(userAgent) }

private val uploadRepository by lazy { UploadRepository(apiClientProvider) }
private val transferRepository by lazy { TransferRepository(apiClientProvider) }
private val uploadRepository by lazy { UploadRepository(apiClientProvider, environment) }
private val transferRepository by lazy { TransferRepository(apiClientProvider, environment) }

private val appSettingsController by lazy { AppSettingsController(realmProvider) }
private val emailTokensController by lazy { EmailTokensController(realmProvider) }
Expand Down Expand Up @@ -86,5 +89,5 @@ class SwissTransferInjection(
val uploadManager by lazy { UploadManager(uploadController, uploadRepository, transferManager, emailLanguageUtils) }

/** An utils to help use shared routes */
val sharedApiUrlCreator by lazy { SharedApiUrlCreator(transferController, uploadController) }
val sharedApiUrlCreator by lazy { SharedApiUrlCreator(environment, transferController, uploadController) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.infomaniak.multiplatform_swisstransfer.network.repositories

import com.infomaniak.multiplatform_swisstransfer.common.exceptions.UnknownException
import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment
import com.infomaniak.multiplatform_swisstransfer.network.ApiClientProvider
import com.infomaniak.multiplatform_swisstransfer.network.exceptions.ApiException
import com.infomaniak.multiplatform_swisstransfer.network.exceptions.NetworkException
Expand All @@ -32,13 +33,15 @@ import kotlin.coroutines.cancellation.CancellationException
class TransferRepository internal constructor(private val transferRequest: TransferRequest) {

// for Obj-C https://youtrack.jetbrains.com/issue/KT-68288/KMP-Support-Kotlin-default-parameters-into-Swift-default-parameters-and-Objective-C-somehow-possibly-a-JvmOverloads-like
constructor() : this(ApiClientProvider())
constructor(apiClientProvider: ApiClientProvider = ApiClientProvider()) : this(
constructor(environment: ApiEnvironment) : this(ApiClientProvider(), environment)
constructor(apiClientProvider: ApiClientProvider = ApiClientProvider(), environment: ApiEnvironment) : this(
environment = environment,
json = apiClientProvider.json,
httpClient = apiClientProvider.httpClient,
)

internal constructor(json: Json, httpClient: HttpClient) : this(TransferRequest(json, httpClient))
internal constructor(environment: ApiEnvironment, json: Json, httpClient: HttpClient) :
this(TransferRequest(environment, json, httpClient))

@Throws(
CancellationException::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.infomaniak.multiplatform_swisstransfer.network.repositories

import com.infomaniak.multiplatform_swisstransfer.common.exceptions.UnknownException
import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment
import com.infomaniak.multiplatform_swisstransfer.network.ApiClientProvider
import com.infomaniak.multiplatform_swisstransfer.network.exceptions.*
import com.infomaniak.multiplatform_swisstransfer.network.exceptions.ContainerErrorsException.Companion.toContainerErrorsException
Expand All @@ -39,13 +40,16 @@ import kotlin.coroutines.cancellation.CancellationException
class UploadRepository internal constructor(private val uploadRequest: UploadRequest) {

// for Obj-C https://youtrack.jetbrains.com/issue/KT-68288/KMP-Support-Kotlin-default-parameters-into-Swift-default-parameters-and-Objective-C-somehow-possibly-a-JvmOverloads-like
constructor() : this(ApiClientProvider())
constructor(apiClientProvider: ApiClientProvider = ApiClientProvider()) : this(
apiClientProvider.json,
apiClientProvider.httpClient,
constructor(environment: ApiEnvironment) : this(ApiClientProvider(), environment)
constructor(apiClientProvider: ApiClientProvider = ApiClientProvider(), environment: ApiEnvironment) : this(
environment = environment,
json = apiClientProvider.json,
httpClient = apiClientProvider.httpClient,
)

internal constructor(json: Json, httpClient: HttpClient) : this(UploadRequest(json, httpClient))
internal constructor(environment: ApiEnvironment, json: Json, httpClient: HttpClient) : this(
UploadRequest(environment, json, httpClient)
)

@Throws(
CancellationException::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package com.infomaniak.multiplatform_swisstransfer.network.requests

import com.infomaniak.multiplatform_swisstransfer.common.exceptions.UnknownException
import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment
import com.infomaniak.multiplatform_swisstransfer.network.exceptions.ApiException
import com.infomaniak.multiplatform_swisstransfer.network.exceptions.NetworkException
import com.infomaniak.multiplatform_swisstransfer.network.exceptions.UnexpectedApiErrorFormatException
Expand All @@ -29,10 +30,14 @@ import io.ktor.client.statement.HttpResponse
import io.ktor.http.*
import kotlinx.serialization.json.Json

internal open class BaseRequest(protected val json: Json, protected val httpClient: HttpClient) {
internal open class BaseRequest(
private val environment: ApiEnvironment,
protected val json: Json,
protected val httpClient: HttpClient,
) {

protected fun createUrl(path: String, vararg queries: Pair<String, String>): Url {
val baseUrl = Url(ApiRoutes.API_BASE_URL + path)
val baseUrl = Url(ApiRoutes.apiBaseUrl(environment) + path)
return URLBuilder(baseUrl).apply {
queries.forEach { parameters.append(it.first, it.second) }
}.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.infomaniak.multiplatform_swisstransfer.network.requests

import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment
import com.infomaniak.multiplatform_swisstransfer.network.models.ApiResponse
import com.infomaniak.multiplatform_swisstransfer.network.models.transfer.TransferApi
import com.infomaniak.multiplatform_swisstransfer.network.utils.ApiRoutes
Expand All @@ -26,7 +27,11 @@ import kotlinx.serialization.json.Json
import kotlin.io.encoding.Base64
import kotlin.io.encoding.ExperimentalEncodingApi

internal class TransferRequest(json: Json, httpClient: HttpClient) : BaseRequest(json, httpClient) {
internal class TransferRequest(
environment: ApiEnvironment,
json: Json,
httpClient: HttpClient,
) : BaseRequest(environment, json, httpClient) {

@OptIn(ExperimentalEncodingApi::class)
suspend fun getTransfer(linkUUID: String, password: String? = null): ApiResponse<TransferApi> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.infomaniak.multiplatform_swisstransfer.network.requests

import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment
import com.infomaniak.multiplatform_swisstransfer.network.models.upload.request.FinishUploadBody
import com.infomaniak.multiplatform_swisstransfer.network.models.upload.request.InitUploadBody
import com.infomaniak.multiplatform_swisstransfer.network.models.upload.request.ResendEmailCodeBody
Expand All @@ -38,7 +39,11 @@ import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject

internal class UploadRequest(json: Json, httpClient: HttpClient) : BaseRequest(json, httpClient) {
internal class UploadRequest(
environment: ApiEnvironment,
json: Json,
httpClient: HttpClient,
) : BaseRequest(environment, json, httpClient) {

suspend fun initUpload(
initUploadBody: InitUploadBody,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,11 @@
*/
package com.infomaniak.multiplatform_swisstransfer.network.utils

import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment

internal object ApiRoutes {

private const val PROD_URL = "https://www.swisstransfer.com"
private const val PREPROD_BASE_URL = "https://swisstransfer.preprod.dev.infomaniak.ch"
const val BASE_URL = PREPROD_BASE_URL
const val API_BASE_URL = "$BASE_URL/api/"
fun apiBaseUrl(environment: ApiEnvironment) = "${environment.baseUrl}/api/"

//region Transfer
fun getTransfer(linkUUID: String): String = "links/$linkUUID"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
*/
package com.infomaniak.multiplatform_swisstransfer.network.utils

import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment

object SharedApiRoutes {

const val createUploadContainer: String = "${ApiRoutes.API_BASE_URL}${ApiRoutes.initUpload}"
fun createUploadContainer(environment: ApiEnvironment): String = "${ApiRoutes.apiBaseUrl(environment)}${ApiRoutes.initUpload}"

fun shareTransfer(linkUUID: String): String = "${ApiRoutes.BASE_URL}/d/$linkUUID"
fun shareTransfer(environment: ApiEnvironment, linkUUID: String): String = "${environment.baseUrl}/d/$linkUUID"

fun downloadFiles(downloadHost: String, linkUUID: String): String = "https://$downloadHost/api/download/$linkUUID"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
package com.infomaniak.multiplatform_swisstransfer.network

import com.infomaniak.multiplatform_swisstransfer.common.utils.ApiEnvironment
import com.infomaniak.multiplatform_swisstransfer.network.models.ApiResponse
import com.infomaniak.multiplatform_swisstransfer.network.models.transfer.TransferApi
import com.infomaniak.multiplatform_swisstransfer.network.repositories.TransferRepository
Expand All @@ -27,7 +28,7 @@ import kotlin.test.*
class TransferRepositoryTest {

private val apiClientProvider = ApiClientProvider()
private val transferRepository = TransferRepository(apiClientProvider) // TODO: Use mock client
private val transferRepository = TransferRepository(apiClientProvider, ApiEnvironment.Preprod) // TODO: Use mock client

@Test
fun canExtractLinkUUIDFromUrl() {
Expand Down
Loading