Skip to content

Commit 9f8d31a

Browse files
authored
Fix pinning option semantics (#3668)
1 parent 23d3951 commit 9f8d31a

File tree

3 files changed

+78
-30
lines changed

3 files changed

+78
-30
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type" : "bugfix",
3+
"description" : "Fix issue where the \"Do not ask again\" option is not respected when switching connections on CodeWhisperer/CodeCatalyst"
4+
}

jetbrains-core/src/software/aws/toolkits/jetbrains/core/credentials/pinning/ConnectionPinningManager.kt

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ class DefaultConnectionPinningManager :
5656
ConnectionPinningManager,
5757
PersistentStateComponent<ConnectionPinningManagerState>,
5858
Disposable {
59-
private var doNotPromptForPinning: Boolean = false
59+
@VisibleForTesting
60+
internal var shouldPinConnections: Boolean? = null
61+
6062
private val pinnedConnections = ConcurrentHashMap<String, ToolkitConnection>()
6163

6264
init {
@@ -108,14 +110,14 @@ class DefaultConnectionPinningManager :
108110
}
109111

110112
override fun getState() = ConnectionPinningManagerState(
111-
doNotPromptForPinning,
113+
shouldPinConnections,
112114
pinnedConnections.entries.associate { (k, v) -> k to v.id }
113115
)
114116

115117
override fun loadState(state: ConnectionPinningManagerState) {
116118
val authManager = ToolkitAuthManager.getInstance()
117119

118-
doNotPromptForPinning = state.doNotPromptForPinning
120+
shouldPinConnections = state.shouldPinConnections
119121

120122
pinnedConnections.clear()
121123
pinnedConnections.putAll(
@@ -129,35 +131,37 @@ class DefaultConnectionPinningManager :
129131

130132
@VisibleForTesting
131133
internal fun showDialogIfNeeded(oldConnection: ToolkitConnection?, newConnection: ToolkitConnection, featuresString: String, project: Project? = null) =
132-
if (!doNotPromptForPinning) {
133-
val bearerTokenConnectionName = bearerTokenConnectionString(oldConnection, newConnection)
134-
135-
computeOnEdt(ModalityState.defaultModalityState()) {
136-
MessageDialogBuilder.yesNo(
137-
message("credentials.switch.confirmation.title", featuresString, bearerTokenConnectionName),
138-
message("credentials.switch.confirmation.comment", featuresString, bearerTokenConnectionName, message("iam.name"))
139-
)
140-
.yesText(message("credentials.switch.confirmation.yes"))
141-
.noText(message("credentials.switch.confirmation.no"))
142-
.doNotAsk(object : com.intellij.openapi.ui.DoNotAskOption.Adapter() {
143-
override fun rememberChoice(isSelected: Boolean, exitCode: Int) {
144-
if (isSelected && exitCode == DialogWrapper.OK_EXIT_CODE) {
145-
doNotPromptForPinning = true
134+
shouldPinConnections.let { shouldPinConnections ->
135+
if (shouldPinConnections == null) {
136+
val bearerTokenConnectionName = bearerTokenConnectionString(oldConnection, newConnection)
137+
138+
computeOnEdt(ModalityState.defaultModalityState()) {
139+
MessageDialogBuilder.yesNo(
140+
message("credentials.switch.confirmation.title", featuresString, bearerTokenConnectionName),
141+
message("credentials.switch.confirmation.comment", featuresString, bearerTokenConnectionName, message("iam.name"))
142+
)
143+
.yesText(message("credentials.switch.confirmation.yes"))
144+
.noText(message("credentials.switch.confirmation.no"))
145+
.doNotAsk(object : com.intellij.openapi.ui.DoNotAskOption.Adapter() {
146+
override fun rememberChoice(isSelected: Boolean, exitCode: Int) {
147+
if (isSelected) {
148+
this@DefaultConnectionPinningManager.shouldPinConnections = exitCode == DialogWrapper.OK_EXIT_CODE
149+
}
150+
}
151+
})
152+
.icon(AllIcons.General.QuestionDialog)
153+
.help(HelpIds.EXPLORER_CREDS_HELP.id)
154+
.ask(project).apply {
155+
if (this) {
156+
UiTelemetry.click(project, "connection_multiple_auths_yes")
157+
} else {
158+
UiTelemetry.click(project, "connection_multiple_auths_no")
146159
}
147160
}
148-
})
149-
.icon(AllIcons.General.QuestionDialog)
150-
.help(HelpIds.EXPLORER_CREDS_HELP.id)
151-
.ask(project).apply {
152-
if (this) {
153-
UiTelemetry.click(project, "connection_multiple_auths_yes")
154-
} else {
155-
UiTelemetry.click(project, "connection_multiple_auths_no")
156-
}
157-
}
161+
}
162+
} else {
163+
shouldPinConnections
158164
}
159-
} else {
160-
false
161165
}
162166

163167
private fun bearerTokenConnectionString(oldConnection: ToolkitConnection?, newConnection: ToolkitConnection): String {
@@ -167,6 +171,6 @@ class DefaultConnectionPinningManager :
167171
}
168172

169173
data class ConnectionPinningManagerState(
170-
var doNotPromptForPinning: Boolean = false,
174+
var shouldPinConnections: Boolean? = null,
171175
var pinnedConnections: Map<String, String> = emptyMap()
172176
)

jetbrains-core/tst/software/aws/toolkits/jetbrains/core/credentials/pinning/ConnectionPinningManagerTest.kt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import org.mockito.kotlin.doReturn
1818
import org.mockito.kotlin.mock
1919
import org.mockito.kotlin.spy
2020
import org.mockito.kotlin.stub
21+
import org.mockito.kotlin.verifyNoInteractions
2122
import org.mockito.kotlin.whenever
2223
import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
2324
import software.aws.toolkits.jetbrains.core.credentials.AwsCredentialConnection
@@ -188,4 +189,43 @@ class ConnectionPinningManagerTest {
188189

189190
assertThat(sut.getPinnedConnection(feature)).isEqualTo(connection)
190191
}
192+
193+
@Test
194+
fun `respects pinning prompt = yes`() {
195+
val connection = mock<AwsBearerTokenConnection>() {
196+
on { id } doReturn "connId"
197+
}
198+
val dialogMock = mock<TestDialog>()
199+
TestDialogManager.setTestDialog(dialogMock)
200+
201+
sut.shouldPinConnections = true
202+
assertThat(sut.showDialogIfNeeded(connection, connection, "feature")).isTrue()
203+
verifyNoInteractions(dialogMock)
204+
}
205+
206+
@Test
207+
fun `respects pinning prompt = no`() {
208+
val connection = mock<AwsBearerTokenConnection>() {
209+
on { id } doReturn "connId"
210+
}
211+
val dialogMock = mock<TestDialog>()
212+
TestDialogManager.setTestDialog(dialogMock)
213+
214+
sut.shouldPinConnections = false
215+
assertThat(sut.showDialogIfNeeded(connection, connection, "feature")).isFalse()
216+
verifyNoInteractions(dialogMock)
217+
}
218+
219+
@Test
220+
fun `prompts for pinning`() {
221+
val connection = mock<AwsBearerTokenConnection>() {
222+
on { id } doReturn "connId"
223+
}
224+
225+
sut.shouldPinConnections = null
226+
TestDialogManager.setTestDialog(TestDialog.YES)
227+
assertThat(sut.showDialogIfNeeded(connection, connection, "feature")).isTrue()
228+
TestDialogManager.setTestDialog(TestDialog.NO)
229+
assertThat(sut.showDialogIfNeeded(connection, connection, "feature")).isFalse()
230+
}
191231
}

0 commit comments

Comments
 (0)