Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import javax.inject.Singleton
@Singleton
class ServerConfigProvider @Inject constructor() {

fun getDefaultServerConfig(managedServerConfig: ManagedServerConfig? = null): ServerConfig.Links {
fun getDefaultServerConfigOrNull(managedServerConfig: ManagedServerConfig? = null): ServerConfig.Links? {
return if (managedServerConfig != null) {
with(managedServerConfig) {
ServerConfig.Links(
Expand All @@ -38,9 +38,12 @@ class ServerConfigProvider @Inject constructor() {
website = endpoints.websiteURL,
title = title,
isOnPremises = true, // EMM configuration always treated as on-premises
apiProxy = null
apiProxy = null,
supportEmail = supportEmail,
)
}
} else if (!BuildConfig.DEFAULT_BACKEND_ENABLED) {
null
} else {
ServerConfig.Links(
api = BuildConfig.DEFAULT_BACKEND_URL_BASE_API,
Expand All @@ -55,6 +58,23 @@ class ServerConfigProvider @Inject constructor() {
)
}
}

fun getDefaultServerConfig(managedServerConfig: ManagedServerConfig? = null): ServerConfig.Links =
getDefaultServerConfigOrNull(managedServerConfig) ?: EmptyServerConfig

companion object {
val EmptyServerConfig = ServerConfig.Links(
api = "",
accounts = "",
webSocket = "",
teams = "",
blackList = "",
website = "",
title = "",
isOnPremises = false,
apiProxy = null
)
}
}

private val staticServerConfigProvider = ServerConfigProvider()
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/kotlin/com/wire/android/datastore/GlobalDataStore.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class GlobalDataStore @Inject constructor(@ApplicationContext private val contex

private fun userDoubleTapToastStatusKey(userId: String): Preferences.Key<Boolean> =
booleanPreferencesKey("$SHOW_CALLING_DOUBLE_TAP_TOAST$userId")

private fun backendSupportEmailKey(backendApiUrl: String): Preferences.Key<String> =
stringPreferencesKey("backend_support_email_${backendApiUrl.sha256()}")
}

suspend fun clear() {
Expand Down Expand Up @@ -213,4 +216,26 @@ class GlobalDataStore @Inject constructor(@ApplicationContext private val contex
suspend fun setPersistentWebSocketEnforcedByMDM(enforced: Boolean) {
context.dataStore.edit { it[PERSISTENT_WEBSOCKET_ENFORCED_BY_MDM] = enforced }
}

suspend fun setBackendSupportEmail(backendApiUrl: String, supportEmail: String?) {
if (backendApiUrl.isBlank()) return

context.dataStore.edit {
val key = backendSupportEmailKey(backendApiUrl)
val normalizedSupportEmail = supportEmail?.trim().orEmpty()
if (normalizedSupportEmail.isBlank()) {
it.remove(key)
} else {
it[key] = normalizedSupportEmail
}
}
}

suspend fun getBackendSupportEmail(backendApiUrl: String): String? =
if (backendApiUrl.isBlank()) {
null
} else {
context.dataStore.data.firstOrNull()?.get(backendSupportEmailKey(backendApiUrl))
?.takeIf { it.isNotBlank() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,25 @@ class ManagedConfigurationsModule {
): ServerConfig.Links {
return if (BuildConfig.EMM_SUPPORT_ENABLED) {
// Returns the current resolved server configuration links, which could be either managed or default
managedConfigurationsManager.currentServerConfig
managedConfigurationsManager.currentServerConfig ?: ServerConfigProvider.EmptyServerConfig
} else {
// If EMM support is disabled, always return the static default server configuration links
provideServerConfigProvider().getDefaultServerConfig(null)
}
}

@Provides
@Named("isDefaultBackendConfigured")
fun provideIsDefaultBackendConfigured(
managedConfigurationsManager: ManagedConfigurationsManager
): Boolean {
return if (BuildConfig.EMM_SUPPORT_ENABLED) {
managedConfigurationsManager.currentServerConfig != null
} else {
BuildConfig.DEFAULT_BACKEND_ENABLED
}
}

@Provides
@Named("ssoCodeConfig")
fun provideCurrentSSOCodeConfig(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import android.content.RestrictionsManager
import com.wire.android.appLogger
import com.wire.android.config.ServerConfigProvider
import com.wire.android.datastore.GlobalDataStore
import com.wire.android.util.BackendSupportConfig
import com.wire.android.util.EMPTY
import com.wire.android.util.dispatchers.DispatcherProvider
import com.wire.kalium.logic.configuration.server.ServerConfig
Expand All @@ -40,7 +41,7 @@ interface ManagedConfigurationsManager {
*
* @see refreshServerConfig
*/
val currentServerConfig: ServerConfig.Links
val currentServerConfig: ServerConfig.Links?

/**
* Current SSO code if provided via managed configurations, empty string otherwise.
Expand All @@ -53,10 +54,10 @@ interface ManagedConfigurationsManager {
* This should be called when the app starts, resumes, or when broadcast receiver triggers.
*
* The result indicates whether a valid config was found or if there was an error.
* Nevertheless, the config is either updated or defaulted to [ServerConfigProvider.getDefaultServerConfig()].
* Nevertheless, the config is either updated or defaulted to [ServerConfigProvider.getDefaultServerConfigOrNull()].
*
* @return result of the update attempt, either success with the config,
* default [ServerConfigProvider.getDefaultServerConfig()] if no config found or cleared, or failure with reason.
* default [ServerConfigProvider.getDefaultServerConfigOrNull()] if no config found or cleared, or failure with reason.
*/
suspend fun refreshServerConfig(): ServerConfigResult

Expand Down Expand Up @@ -105,8 +106,8 @@ internal class ManagedConfigurationsManagerImpl(
MutableStateFlow(runBlocking { globalDataStore.isPersistentWebSocketEnforcedByMDM().first() })
}

override val currentServerConfig: ServerConfig.Links
get() = _currentServerConfig.get() ?: serverConfigProvider.getDefaultServerConfig()
override val currentServerConfig: ServerConfig.Links?
get() = _currentServerConfig.get() ?: serverConfigProvider.getDefaultServerConfigOrNull()

override val currentSSOCodeConfig: String
get() = _currentSSOCodeConfig.get()
Expand All @@ -116,15 +117,16 @@ internal class ManagedConfigurationsManagerImpl(

override suspend fun refreshServerConfig(): ServerConfigResult = withContext(dispatchers.io()) {
val managedServerConfig = getServerConfig()
val serverConfig: ServerConfig.Links = when (managedServerConfig) {
val serverConfig: ServerConfig.Links? = when (managedServerConfig) {
is ServerConfigResult.Empty,
is ServerConfigResult.Failure -> serverConfigProvider.getDefaultServerConfig(null)
is ServerConfigResult.Failure -> serverConfigProvider.getDefaultServerConfigOrNull(null)

is ServerConfigResult.Success -> serverConfigProvider.getDefaultServerConfig(
is ServerConfigResult.Success -> serverConfigProvider.getDefaultServerConfigOrNull(
managedServerConfig.config
)
}
_currentServerConfig.set(serverConfig)
serverConfig?.let { BackendSupportConfig.storeFromServerLinks(globalDataStore, it) }
logger.i("Server config refreshed: $serverConfig")
managedServerConfig
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ data class ManagedServerConfig(
@SerialName("title")
val title: String,
@SerialName("endpoints")
val endpoints: ManagedServerLinks
val endpoints: ManagedServerLinks,
@SerialName("supportEmail")
val supportEmail: String? = null
)

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ val Direction.baseRoute: String

fun Direction.handleNavigation(context: Context, handleOtherDirection: (Direction) -> Unit) = when (this) {
is ExternalUriDirection -> CustomTabsHelper.launchUri(context, this.uri)
is ExternalUriStringResDirection -> CustomTabsHelper.launchUri(context, this.getUri(context.resources))
is ExternalUriStringResDirection -> CustomTabsHelper.launchUrl(context, this.getUriString(context.resources))
is IntentDirection -> context.startActivity(this.intent(context))
else -> handleOtherDirection(this)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import com.ramcosta.composedestinations.spec.Direction
import com.wire.android.BuildConfig
import com.wire.android.R
import com.wire.android.util.EmailComposer
import com.wire.android.util.SupportPage
import com.wire.android.util.SupportUrlResolver
import com.wire.android.util.getDeviceIdString
import com.wire.android.util.getGitBuildId
import com.wire.android.util.getUrisOfFilesInDirectory
Expand Down Expand Up @@ -53,16 +55,33 @@ interface ExternalUriStringResDirection : Direction {
override val route: String
get() = "android.resource://${BuildConfig.APPLICATION_ID}/$uriStringRes"

fun getUri(resources: Resources): Uri = Uri.parse(resources.getString(uriStringRes))
fun getUriString(resources: Resources): String = resources.getString(uriStringRes)

fun getUri(resources: Resources): Uri = Uri.parse(getUriString(resources))
}

interface ExternalSupportUriStringResDirection : ExternalUriStringResDirection {
val supportPage: SupportPage

override val uriStringRes: Int
get() = supportPage.hardcodedUrlRes

override fun getUriString(resources: Resources): String =
SupportUrlResolver.resolve(resources, supportPage)
}

interface IntentDirection : Direction {
fun intent(context: Context): Intent
}

object SupportScreenDestination : ExternalUriStringResDirection {
override val uriStringRes: Int
get() = R.string.url_support
object SupportScreenDestination : ExternalSupportUriStringResDirection {
override val supportPage: SupportPage
get() = SupportPage.SUPPORT
}

object ReportMisuseScreenDestination : ExternalSupportUriStringResDirection {
override val supportPage: SupportPage
get() = SupportPage.REPORT_MISUSE
}

data object TeamManagementScreenDestination : ExternalDirectionLess
Expand Down Expand Up @@ -127,9 +146,9 @@ object ReportBugDestination : IntentDirection {
get() = "wire-intent:report-bug"
}

object WelcomeToNewAndroidAppDestination : ExternalUriStringResDirection {
override val uriStringRes: Int
get() = R.string.url_welcome_to_new_android
object WelcomeToNewAndroidAppDestination : ExternalSupportUriStringResDirection {
override val supportPage: SupportPage
get() = SupportPage.WELCOME_ANDROID
}

object AndroidReleaseNotesDestination : ExternalUriStringResDirection {
Expand Down
32 changes: 31 additions & 1 deletion app/src/main/kotlin/com/wire/android/ui/WireActivityViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,11 @@ import com.wire.android.ui.common.dialogs.CustomServerNoNetworkDialogState
import com.wire.android.ui.joinConversation.JoinConversationViaCodeState
import com.wire.android.ui.theme.Accent
import com.wire.android.ui.theme.ThemeOption
import com.wire.android.util.BackendSupportConfig
import com.wire.android.util.CurrentScreen
import com.wire.android.util.CurrentScreenManager
import com.wire.android.util.CustomTabsHelper
import com.wire.android.util.SupportUrlResolver
import com.wire.android.util.deeplink.DeepLinkProcessor
import com.wire.android.util.deeplink.DeepLinkResult
import com.wire.android.util.deeplink.LoginType
Expand Down Expand Up @@ -82,6 +85,7 @@ import com.wire.kalium.logic.feature.session.DoesValidSessionExistResult
import com.wire.kalium.logic.feature.session.DoesValidSessionExistUseCase
import com.wire.kalium.logic.feature.session.GetAllSessionsResult
import com.wire.kalium.logic.feature.session.ObserveSessionsUseCase
import com.wire.kalium.logic.feature.user.SelfServerConfigUseCase
import com.wire.kalium.logic.feature.user.screenshotCensoring.ObserveScreenshotCensoringConfigResult
import com.wire.kalium.logic.feature.user.webSocketStatus.ObservePersistentWebSocketConnectionStatusUseCase
import com.wire.kalium.util.DateTimeUtil.toIsoDateTimeString
Expand Down Expand Up @@ -168,6 +172,7 @@ class WireActivityViewModel @Inject constructor(
observeAppThemeState()
observeSelectedAccent()
observeLogoutState()
observeBackendWebsiteUrl()
resetNewRegistrationAnalyticsState()
viewModelScope.launch(dispatchers.io()) { monitorSyncWorkUseCase() }
}
Expand Down Expand Up @@ -203,6 +208,27 @@ class WireActivityViewModel @Inject constructor(
}
}

private fun observeBackendWebsiteUrl() {
viewModelScope.launch(dispatchers.io()) {
observeCurrentValidUserId.collectLatest { userId ->
val serverLinks = userId?.let {
runCatching {
when (val result = coreLogic.get().getSessionScope(it).users.serverLinks()) {
is SelfServerConfigUseCase.Result.Success -> result.serverLinks.links
is SelfServerConfigUseCase.Result.Failure -> null
}
}.getOrNull()
}
serverLinks?.let(BackendSupportConfig::setCurrentBackend)
val websiteUrl = serverLinks?.website
?: managedConfigurationsManager.currentServerConfig?.website

CustomTabsHelper.setBackendWebsiteUrl(websiteUrl)
SupportUrlResolver.setBaseUrl(websiteUrl)
}
}
}

private fun observeSyncState() {
viewModelScope.launch(dispatchers.io()) {
observeCurrentValidUserId
Expand Down Expand Up @@ -456,7 +482,11 @@ class WireActivityViewModel @Inject constructor(

private suspend fun loadServerConfig(url: String): ServerConfig.Links? =
when (val result = getServerConfigUseCase.get().invoke(url)) {
is GetServerConfigResult.Success -> result.serverConfigLinks
is GetServerConfigResult.Success -> result.serverConfigLinks.also {
CustomTabsHelper.setBackendWebsiteUrl(it.website)
SupportUrlResolver.setBaseUrl(it.website)
BackendSupportConfig.storeFromServerLinks(globalDataStore.get(), it)
}
is GetServerConfigResult.Failure.Generic -> {
appLogger.e("something went wrong during handling the custom server deep link: ${result.genericFailure}")
null
Expand Down
Loading
Loading