diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt index 10ce0829d0..9898923003 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt @@ -19,7 +19,12 @@ package org.matrix.android.sdk.api.session.terms interface TermsService { enum class ServiceType { IntegrationManager, - IdentityService + IdentityService, + + /** + * It's only possible to use this value for [getTerms] + */ + Homeserver } suspend fun getTerms(serviceType: ServiceType, baseUrl: String): GetTermsResponse diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt index d40fd8d076..5cdef3db0a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt @@ -18,10 +18,13 @@ package org.matrix.android.sdk.internal.session.terms import dagger.Lazy import okhttp3.OkHttpClient +import org.matrix.android.sdk.api.auth.data.LoginFlowTypes +import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.terms.GetTermsResponse import org.matrix.android.sdk.api.session.terms.TermsService +import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate import org.matrix.android.sdk.internal.network.NetworkConstants import org.matrix.android.sdk.internal.network.RetrofitFactory @@ -48,11 +51,49 @@ internal class DefaultTermsService @Inject constructor( override suspend fun getTerms(serviceType: TermsService.ServiceType, baseUrl: String): GetTermsResponse { - val url = buildUrl(baseUrl, serviceType) - val termsResponse = executeRequest(null) { - termsAPI.getTerms("${url}terms") + return if (serviceType == TermsService.ServiceType.Homeserver) { + getHomeserverTerms(baseUrl) + } else { + val url = buildUrl(baseUrl, serviceType) + val termsResponse = executeRequest(null) { + termsAPI.getTerms("${url}terms") + } + GetTermsResponse(termsResponse, getAlreadyAcceptedTermUrlsFromAccountData()) } - return GetTermsResponse(termsResponse, getAlreadyAcceptedTermUrlsFromAccountData()) + } + + /** + * We use a trick here to get the homeserver T&C, we use the register API + */ + private suspend fun getHomeserverTerms(baseUrl: String): GetTermsResponse { + return try { + executeRequest(null) { + termsAPI.register(baseUrl + NetworkConstants.URI_API_PREFIX_PATH_R0 + "register") + } + // Return empty result if it succeed, but it should never happen + buildEmptyGetTermsResponse() + } catch (throwable: Throwable) { + @Suppress("UNCHECKED_CAST") + ((throwable.toRegistrationFlowResponse() + ?.params?.get(LoginFlowTypes.TERMS) as? JsonDict) + ?.get("policies") as? JsonDict) + ?.let { dict -> + GetTermsResponse( + serverResponse = TermsResponse( + policies = dict + ), + alreadyAcceptedTermUrls = emptySet() + ) + } + ?: buildEmptyGetTermsResponse() + } + } + + private fun buildEmptyGetTermsResponse(): GetTermsResponse { + return GetTermsResponse( + serverResponse = TermsResponse(), + alreadyAcceptedTermUrls = emptySet() + ) } override suspend fun agreeToTerms(serviceType: TermsService.ServiceType, @@ -91,7 +132,9 @@ internal class DefaultTermsService @Inject constructor( private fun buildUrl(baseUrl: String, serviceType: TermsService.ServiceType): String { val servicePath = when (serviceType) { TermsService.ServiceType.IntegrationManager -> NetworkConstants.URI_INTEGRATION_MANAGER_PATH - TermsService.ServiceType.IdentityService -> NetworkConstants.URI_IDENTITY_PATH_V2 + TermsService.ServiceType.IdentityService -> NetworkConstants.URI_IDENTITY_PATH_V2 + TermsService.ServiceType.Homeserver -> + error("You cannot use this API with parameter TermsService.ServiceType.Homeserver") } return "${baseUrl.ensureTrailingSlash()}$servicePath" } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt index 91d27030de..fb6aff5a9e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.internal.session.terms +import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.api.util.emptyJsonDict import org.matrix.android.sdk.internal.network.HttpHeaders import retrofit2.http.Body import retrofit2.http.GET @@ -37,4 +39,12 @@ internal interface TermsAPI { suspend fun agreeToTerms(@Url url: String, @Body params: AcceptTermsBody, @Header(HttpHeaders.Authorization) token: String) + + /** + * API to retrieve the terms for a homeserver. The API /terms does not exist yet, so retrieve the terms from the login flow. + * We do not care about the result (Credentials) + */ + @POST + suspend fun register(@Url url: String, + @Body body: JsonDict = emptyJsonDict) } diff --git a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt index 119e544414..08712f6e68 100644 --- a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt +++ b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt @@ -29,7 +29,7 @@ suspend fun Session.fetchIdentityServerWithTerms(userLanguage: String): Identity suspend fun Session.fetchHomeserverWithTerms(userLanguage: String): IdentityServerWithTerms { val homeserverUrl = sessionParams.homeServerUrl - return fetchTerms(homeserverUrl, TermsService.ServiceType.IdentityService, userLanguage) + return fetchTerms(homeserverUrl, TermsService.ServiceType.Homeserver, userLanguage) } private suspend fun Session.fetchTerms(serviceUrl: String, diff --git a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt index cb76e5b31f..6381854433 100644 --- a/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/terms/ReviewTermsFragment.kt @@ -53,6 +53,7 @@ class ReviewTermsFragment @Inject constructor( termsController.description = when (reviewTermsViewModel.termsArgs.type) { TermsService.ServiceType.IdentityService -> getString(R.string.terms_description_for_identity_server) TermsService.ServiceType.IntegrationManager -> getString(R.string.terms_description_for_integration_manager) + TermsService.ServiceType.Homeserver -> error("Homeserver is not supported here") } termsController.listener = this