mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-03 06:55:41 +00:00
Move the :libraries:wellknown logic into enterprise modules (#7429)
* Extract `IsEnterpriseBuild` use case Having it inside `EnterpriseService` made having DI cycles with the `BuildMeta` provider too easy * Rename `EnterpriseService.defaultHomeserverList()` to `homeserverAllowList()` This seems more aligned with the way this list works * Move most of the logic from `:libraries:wellknown` to `:enterprise:feature:enterprise`, both `shared` and `impl` modules Ideally I would have added everything into `impl`, but some of the classes needed to be shared between the different `:enterprise:features` modules, and those are in the `shared` module, lacking a better name/strategy * Add `EnterpriseService.isElementProEnforced` With this, we don't need to provide the `RemoteEnterpriseConfig` anymore to any consumers, everything goes through `EnterpriseService` or other providers * Remove `EnterpriseService.overriddenElementWellKnown` This leaks the remote enterprise config/element well known contents to the app in a public interface. * Create `CustomMapTilerConfigProvider` to avoid leaking the `RemoteEnterpriseConfig` in public APIs This commit also starts moving some of the well-known related values to the enterprise modules * Add missing docs to `EnterpriseService` and `SessionEnterpriseService` * Fix tests * Fix lint issues * Bump enterprise module
This commit is contained in:
committed by
GitHub
parent
f94566e44f
commit
8b2c207728
+13
-13
@@ -12,7 +12,6 @@ import androidx.compose.ui.graphics.Color
|
||||
import io.element.android.compound.colors.SemanticColorsLightDark
|
||||
import io.element.android.libraries.matrix.api.UrlContentFetcher
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.wellknown.api.ElementWellKnown
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
@@ -21,9 +20,6 @@ import kotlinx.coroutines.flow.Flow
|
||||
* On a standard build this reports permissive defaults, so callers do not need to branch on the build type themselves.
|
||||
*/
|
||||
interface EnterpriseService {
|
||||
/** Whether this build is an enterprise one; `false` for the public app. */
|
||||
val isEnterpriseBuild: Boolean
|
||||
|
||||
/**
|
||||
* Whether the given session belongs to an enterprise deployment, which can be true even on a standard build.
|
||||
*
|
||||
@@ -41,17 +37,26 @@ interface EnterpriseService {
|
||||
suspend fun tweakMasUrl(url: String, homeserver: String, urlContentFetcher: UrlContentFetcher): String
|
||||
|
||||
/**
|
||||
* The homeservers the user is allowed to sign in to; an empty list, or one containing [ANY_ACCOUNT_PROVIDER], means no restriction.
|
||||
* Returns the list of homeservers the user is allowed to sign in to.
|
||||
*
|
||||
* If the list is empty or contains the special value [ANY_ACCOUNT_PROVIDER], the user is allowed to sign in to any homeserver.
|
||||
*/
|
||||
fun defaultHomeserverList(): List<String>
|
||||
fun homeserverAllowList(): List<String>
|
||||
|
||||
/**
|
||||
* Whether the user is allowed to sign in to a given homeserver, according to [defaultHomeserverList].
|
||||
* Whether the user is allowed to sign in to a given homeserver, according to [homeserverAllowList].
|
||||
*
|
||||
* @param homeserverUrl the server the user is trying to use.
|
||||
*/
|
||||
suspend fun isAllowedToConnectToHomeserver(homeserverUrl: String): Boolean
|
||||
|
||||
/**
|
||||
* Whether the given homeserver enforces the use of Element Pro or a derived app.
|
||||
*
|
||||
* @param homeserverUrl the homeserver to check.
|
||||
*/
|
||||
suspend fun isElementProEnforced(homeserverUrl: String): Boolean
|
||||
|
||||
/**
|
||||
* Override the brand color.
|
||||
* @param sessionId the session to override the brand color for, or null to set the brand color to use when there is no session.
|
||||
@@ -94,11 +99,6 @@ interface EnterpriseService {
|
||||
*/
|
||||
fun getNoisyNotificationChannelId(sessionId: SessionId): String?
|
||||
|
||||
/**
|
||||
* Gets the overridden Element Well-Known data if it has been set, or null if not set.
|
||||
*/
|
||||
fun overriddenElementWellKnown(): ElementWellKnown?
|
||||
|
||||
/**
|
||||
* Gets the Element Server Suite (ESS) config endpoint URL for the given domain.
|
||||
* Returns `null` when this build does not read its configuration from an ESS deployment.
|
||||
@@ -113,7 +113,7 @@ interface EnterpriseService {
|
||||
}
|
||||
|
||||
fun EnterpriseService.canConnectToAnyHomeserver(): Boolean {
|
||||
return defaultHomeserverList().let {
|
||||
return homeserverAllowList().let {
|
||||
it.isEmpty() || it.contains(EnterpriseService.ANY_ACCOUNT_PROVIDER)
|
||||
}
|
||||
}
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.enterprise.api
|
||||
|
||||
/**
|
||||
* A use case to check if this build of the app is an enterprise build.
|
||||
*/
|
||||
fun interface IsEnterpriseBuild {
|
||||
/**
|
||||
* Returns `true` if this build of the app is an enterprise build, `false` otherwise.
|
||||
*/
|
||||
operator fun invoke(): Boolean
|
||||
}
|
||||
+3
-3
@@ -14,6 +14,9 @@ package io.element.android.features.enterprise.api
|
||||
* [init] must have run before the other members return meaningful answers.
|
||||
*/
|
||||
interface SessionEnterpriseService {
|
||||
/** Loads the deployment configuration of this session; to be called once when the session starts. */
|
||||
suspend fun init()
|
||||
|
||||
/** Whether Element Call may be used on this session, which a deployment can turn off. */
|
||||
suspend fun isElementCallAvailable(): Boolean
|
||||
|
||||
@@ -26,7 +29,4 @@ interface SessionEnterpriseService {
|
||||
|
||||
/** Whether the homeserver forbids creating encrypted rooms, in which case the app must not offer the option. */
|
||||
suspend fun isEncryptionDisabledByHomeserver(): Boolean
|
||||
|
||||
/** Loads the deployment configuration of this session; to be called once when the session starts. */
|
||||
suspend fun init()
|
||||
}
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.enterprise.api.remoteconfig
|
||||
|
||||
/**
|
||||
* A provider of a runtime-fetched MapTiler configuration, which can be used to override the default MapTiler configuration.
|
||||
*/
|
||||
fun interface CustomMapTilerConfigProvider {
|
||||
suspend fun get(): Result<MapTilerConfig?>
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.enterprise.api.remoteconfig
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
/**
|
||||
* A `MapTiler` configuration received from the server. This configuration is used to display maps in the app.
|
||||
*/
|
||||
@Immutable
|
||||
data class MapTilerConfig(
|
||||
/** The API key to use with MapTiler. This is always not null, but can be empty/blank. */
|
||||
val apiKey: String,
|
||||
/** The style ID to use for light mode. This is optional and can be null. */
|
||||
val lightStyleId: String?,
|
||||
/** The style ID to use for light mode. This is optional and can be null. */
|
||||
val darkStyleId: String?,
|
||||
/** The base URL to use for MapTiler. This is optional and can be null. */
|
||||
val baseUrl: String?,
|
||||
)
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.enterprise.api.remoteconfig
|
||||
|
||||
import io.element.android.libraries.wellknown.api.ElementWellKnown
|
||||
|
||||
/**
|
||||
* Typealias for the well-known configuration used for enterprise features.
|
||||
*
|
||||
* This will allow for easier refactoring in the future when we'll want to move as much of its logic as possible to this module.
|
||||
*/
|
||||
typealias RemoteEnterpriseConfig = ElementWellKnown
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.enterprise.api.remoteconfig
|
||||
|
||||
import io.element.android.libraries.matrix.api.UrlContentFetcher
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.wellknown.api.WellknownRetrieverResult
|
||||
|
||||
/**
|
||||
* Wrapper to fetch the remote enterprise configuration for a given [SessionId], either from a local cache or from a remote source.
|
||||
*/
|
||||
interface RemoteEnterpriseConfigProvider {
|
||||
/**
|
||||
* Returns the configuration of a session, served from the cache when possible.
|
||||
* A stale entry is reported as outdated while a refresh runs in the background, so this rarely waits on the network.
|
||||
*
|
||||
* @param sessionId the session whose configuration is requested.
|
||||
*/
|
||||
suspend fun get(sessionId: SessionId): WellknownRetrieverResult<RemoteEnterpriseConfig>
|
||||
|
||||
/**
|
||||
* Creates a provider, which needs a fetcher because the configuration is read over HTTP.
|
||||
*/
|
||||
interface Factory {
|
||||
/**
|
||||
* @param urlContentFetcher used to perform the request; a client that is not authenticated yet also works.
|
||||
*/
|
||||
fun create(urlContentFetcher: UrlContentFetcher): RemoteEnterpriseConfigProvider
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.enterprise.api.remoteconfig
|
||||
|
||||
sealed interface RemoteEnterpriseConfigResult<out T> {
|
||||
/**
|
||||
* Well-known data has been successfully retrieved.
|
||||
*/
|
||||
data class Success<out T>(val data: T) : RemoteEnterpriseConfigResult<T>
|
||||
|
||||
/**
|
||||
* Well-known data has been retrieved from the local cache but is outdated and a manual refresh has been launched.
|
||||
*/
|
||||
data class Outdated<out T>(val data: T) : RemoteEnterpriseConfigResult<T>
|
||||
|
||||
/**
|
||||
* Well-known data is not found (file does not exist server side, we got a 404).
|
||||
*/
|
||||
data object NotFound : RemoteEnterpriseConfigResult<Nothing>
|
||||
|
||||
/**
|
||||
* Any other error.
|
||||
*/
|
||||
data class Error(val exception: Exception) : RemoteEnterpriseConfigResult<Nothing>
|
||||
|
||||
fun dataOrNull(): T? = when (this) {
|
||||
is Success<T> -> data
|
||||
is Outdated<T> -> data
|
||||
is Error -> null
|
||||
NotFound -> null
|
||||
}
|
||||
|
||||
fun upToDateDataOrNull(): T? = when (this) {
|
||||
is Success<T> -> data
|
||||
is Outdated<T> -> null
|
||||
is Error -> null
|
||||
NotFound -> null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user