From e8172ae615d25eb95262176ae45fc0e05b9d5500 Mon Sep 17 00:00:00 2001 From: Sergey Pak Date: Tue, 8 Apr 2025 21:48:53 +0200 Subject: [PATCH] [settingsSync] use actionRequired if lacking authorization in CloudConfigServerCommunicator GitOrigin-RevId: a47d1639ed6cec290b99543055f7ff98186a3925 --- .../messages/SettingsSyncBundle.properties | 4 ++- .../core/SettingsSyncStatusTracker.kt | 7 ++-- .../core/config/SettingsSyncConfigurable.kt | 11 ++++-- .../messages/SettingsSyncJbaBundle.properties | 1 + .../jba/CloudConfigServerCommunicator.kt | 34 ++++++++++++------- .../settingsSync/SettingsSyncAuthTest.kt | 5 +-- 6 files changed, 41 insertions(+), 21 deletions(-) diff --git a/platform/settings-sync-core/resources/messages/SettingsSyncBundle.properties b/platform/settings-sync-core/resources/messages/SettingsSyncBundle.properties index 947c4e21bc94..ab50fc2cf3fb 100644 --- a/platform/settings-sync-core/resources/messages/SettingsSyncBundle.properties +++ b/platform/settings-sync-core/resources/messages/SettingsSyncBundle.properties @@ -108,8 +108,10 @@ sync.notification.restart.message.list.entry.plugin.disable=Disable {0,choice,1# sync.restart.notification.submessage.plugins={0} plugin(s): {1}\u2026 # {0} - IDE name, i.e. Android Studio, MPS, etc. sync.restart.notification.action=Restart {0} -sync.status.enabled=Backup and Sync enabled for +sync.status.enabled=Backup and Sync is enabled +sync.status.will.enable=Backup and Sync will be enabled sync.status.disabled=Backup and Sync disabled +sync.status.will.disable=Backup and Sync will be disabled sync.status.action.required=Action required: {0} sync.status.failed=Sync failed: {0} sync.status.login.message=Login to enable Backup and Sync diff --git a/platform/settings-sync-core/src/com/intellij/settingsSync/core/SettingsSyncStatusTracker.kt b/platform/settings-sync-core/src/com/intellij/settingsSync/core/SettingsSyncStatusTracker.kt index faece35c1000..75d94f9bdd4c 100644 --- a/platform/settings-sync-core/src/com/intellij/settingsSync/core/SettingsSyncStatusTracker.kt +++ b/platform/settings-sync-core/src/com/intellij/settingsSync/core/SettingsSyncStatusTracker.kt @@ -5,6 +5,7 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.diagnostic.logger import com.intellij.util.EventDispatcher import org.jetbrains.annotations.Nls +import java.awt.Component import java.util.* @Service @@ -53,7 +54,7 @@ class SettingsSyncStatusTracker { eventDispatcher.multicaster.syncStatusChanged() } - fun setActionRequired(message: @Nls String, actionTitle: @Nls String, action: suspend () -> Unit) { + fun setActionRequired(message: @Nls String, actionTitle: @Nls String, action: suspend (Component?) -> Unit) { lastSyncTime = -1 state = SyncStatus.ActionRequired(message, actionTitle, action) eventDispatcher.multicaster.syncStatusChanged() @@ -93,8 +94,8 @@ class SettingsSyncStatusTracker { */ class ActionRequired(val message: @Nls String, val actionTitle: @Nls String, - private val action: suspend() -> Unit): SyncStatus() { - suspend fun execute() = action() + private val action: suspend(Component?) -> Unit): SyncStatus() { + suspend fun execute(component: Component?) = action(component) } } } \ No newline at end of file diff --git a/platform/settings-sync-core/src/com/intellij/settingsSync/core/config/SettingsSyncConfigurable.kt b/platform/settings-sync-core/src/com/intellij/settingsSync/core/config/SettingsSyncConfigurable.kt index a0b9b31690e5..b7e2a33a869b 100644 --- a/platform/settings-sync-core/src/com/intellij/settingsSync/core/config/SettingsSyncConfigurable.kt +++ b/platform/settings-sync-core/src/com/intellij/settingsSync/core/config/SettingsSyncConfigurable.kt @@ -305,7 +305,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco if (SettingsSyncStatusTracker.getInstance().currentStatus is SettingsSyncStatusTracker.SyncStatus.ActionRequired) { val actionRequired = SettingsSyncStatusTracker.getInstance().currentStatus as SettingsSyncStatusTracker.SyncStatus.ActionRequired runWithModalProgressBlocking(ModalTaskOwner.component(configPanel), actionRequired.actionTitle) { - actionRequired.execute() + actionRequired.execute(syncConfigPanel) } return } @@ -328,7 +328,10 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco return@runWithModalProgressBlocking } if (checkServerState(syncPanelHolder, remoteCommunicator, provider.authService.crossSyncSupported())) { - triggerUpdateConfigurable() + withContext(Dispatchers.EDT) { + triggerUpdateConfigurable() + } + cellDropDownLink.comment?.text = message("sync.status.will.enable") } else { enableCheckbox.isSelected = false } @@ -338,6 +341,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco val syncDisableOption = showDisableSyncDialog() if (syncDisableOption != DisableSyncType.DONT_DISABLE) { disableSyncOption.set(syncDisableOption) + cellDropDownLink.comment?.text = message("sync.status.will.disable") } else { enableCheckbox.isSelected = true } @@ -589,7 +593,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco //statusLabel.icon = AllIcons.General.Error } is SettingsSyncStatusTracker.SyncStatus.ActionRequired -> { - actionRequiredAction = { currentStatus.execute() } + actionRequiredAction = { currentStatus.execute(syncConfigPanel) } actionRequiredLabel.text = currentStatus.message actionRequiredButton.text = currentStatus.actionTitle //actionRequiredData = Pair(currentStatus.message, currentStatus.actionTitle) @@ -609,6 +613,7 @@ internal class SettingsSyncConfigurable(private val coroutineScope: CoroutineSco } // triggers fake action, which causes SettingEditor to update and check if configurable was modified + // must be called on EDT private fun triggerUpdateConfigurable() { val dumbAwareAction = DumbAwareAction.create(Consumer { _: AnActionEvent? -> // do nothing diff --git a/plugins/settings-sync/jba/resources/messages/SettingsSyncJbaBundle.properties b/plugins/settings-sync/jba/resources/messages/SettingsSyncJbaBundle.properties index e5a68317ed2e..16d23839b2f6 100644 --- a/plugins/settings-sync/jba/resources/messages/SettingsSyncJbaBundle.properties +++ b/plugins/settings-sync/jba/resources/messages/SettingsSyncJbaBundle.properties @@ -1,6 +1,7 @@ action.settingsSync.troubleShoot.text=Backup and Sync Troubleshooting login.title=Please Log in Via The Opened Browser\u2026 login.troubles.message=In case you have problems, try to Log in manually +action.settingsSync.authRequired=Authorization Required troubleshooting.loading.info.progress.dialog.title=Loading information about Backup and Sync\u2026 troubleshooting.dialog.title=Backup and Sync Troubleshooting diff --git a/plugins/settings-sync/jba/src/com/intellij/settingsSync/jba/CloudConfigServerCommunicator.kt b/plugins/settings-sync/jba/src/com/intellij/settingsSync/jba/CloudConfigServerCommunicator.kt index c32478794fab..0ddfb7aa7497 100644 --- a/plugins/settings-sync/jba/src/com/intellij/settingsSync/jba/CloudConfigServerCommunicator.kt +++ b/plugins/settings-sync/jba/src/com/intellij/settingsSync/jba/CloudConfigServerCommunicator.kt @@ -4,10 +4,10 @@ import com.intellij.ide.plugins.PluginManagerCore.isRunningFromSources import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.util.JDOMUtil import com.intellij.settingsSync.core.AbstractServerCommunicator +import com.intellij.settingsSync.core.SettingsSyncBundle import com.intellij.settingsSync.core.SettingsSyncEventListener import com.intellij.settingsSync.core.SettingsSyncEvents -import com.intellij.settingsSync.core.SettingsSyncLocalSettings -import com.intellij.settingsSync.core.SettingsSyncSettings +import com.intellij.settingsSync.core.SettingsSyncStatusTracker import com.intellij.settingsSync.jba.auth.JBAAuthService import com.intellij.util.io.HttpRequests import com.jetbrains.cloudconfig.CloudConfigFileClientV2 @@ -95,9 +95,9 @@ internal open class CloudConfigServerCommunicator(private val serverUrl: String? } else if (e is UnauthorizedException) { _currentIdTokenVar?.also { - jbaAuthService.invalidateJBA(it) LOG.warn("Got \"Unauthorized\" from Settings Sync server. Settings Sync will be disabled. Please login to JBA again") - SettingsSyncSettings.getInstance().syncEnabled = false + setAuthActionRequired() + jbaAuthService.invalidateJBA(it) } } else { @@ -158,20 +158,30 @@ internal open class CloudConfigServerCommunicator(private val serverUrl: String? val idToken = jbaAuthService.idToken _currentIdTokenVar = idToken if (idToken == null) { - if (System.getProperty("settings.sync.allow.user.without.token") == "true") - return null - else - if (jbaAuthService.getAccountInfoService()?.userData != null) { - SettingsSyncSettings.getInstance().syncEnabled = false - SettingsSyncLocalSettings.getInstance().userId = null - SettingsSyncLocalSettings.getInstance().providerCode = null - } + if (jbaAuthService.getAccountInfoService()?.userData != null) { + setAuthActionRequired() + } + return null } else { configuration.auth(JbaJwtTokenAuthProvider(idToken)) } return configuration } + private fun setAuthActionRequired() { + if (SettingsSyncStatusTracker.getInstance().currentStatus is SettingsSyncStatusTracker.SyncStatus.ActionRequired) + return + SettingsSyncStatusTracker.getInstance().setActionRequired( + SettingsSyncJbaBundle.message("action.settingsSync.authRequired"), + SettingsSyncBundle.message("config.button.login")) { + val userData = jbaAuthService.login(it) + if (userData != null) { + SettingsSyncStatusTracker.getInstance().clearActionRequired() + SettingsSyncStatusTracker.getInstance().updateOnSuccess() + } + } + } + companion object { private const val URL_PROVIDER = "https://www.jetbrains.com/config/IdeaCloudConfig.xml" private const val DEFAULT_PRODUCTION_URL = "https://cloudconfig.jetbrains.com/cloudconfig" diff --git a/plugins/settings-sync/jba/test/com/intellij/settingsSync/SettingsSyncAuthTest.kt b/plugins/settings-sync/jba/test/com/intellij/settingsSync/SettingsSyncAuthTest.kt index 6863ec919255..0e0cc8df062e 100644 --- a/plugins/settings-sync/jba/test/com/intellij/settingsSync/SettingsSyncAuthTest.kt +++ b/plugins/settings-sync/jba/test/com/intellij/settingsSync/SettingsSyncAuthTest.kt @@ -4,6 +4,7 @@ import com.intellij.idea.TestFor import com.intellij.openapi.application.ApplicationManager import com.intellij.settingsSync.core.SettingsSyncMain import com.intellij.settingsSync.core.SettingsSyncSettings +import com.intellij.settingsSync.core.SettingsSyncStatusTracker import com.intellij.settingsSync.core.auth.SettingsSyncAuthService import com.intellij.settingsSync.jba.CloudConfigServerCommunicator import com.intellij.settingsSync.jba.CloudConfigVersionContext @@ -89,7 +90,7 @@ internal class SettingsSyncAuthTest : BasePlatformTestCase() { @Test @TestFor(issues = ["IDEA-343073"]) - fun `disable setting sync logged out on invalid idToken`() { + fun `setting sync set action required on invalid idToken`() { SettingsSyncSettings.getInstance().syncEnabled = true assertTrue(SettingsSyncSettings.getInstance().syncEnabled) @@ -120,7 +121,7 @@ internal class SettingsSyncAuthTest : BasePlatformTestCase() { communicator.checkServerState() //assertFalse(authServiceSpy.isLoggedIn()) - assertFalse(SettingsSyncSettings.getInstance().syncEnabled) + assertTrue(SettingsSyncStatusTracker.getInstance().currentStatus is SettingsSyncStatusTracker.SyncStatus.ActionRequired) } @Test