Skip to content
Merged
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 @@ -18,6 +18,7 @@
TextColorWeak("--mynah-color-text-weak"),
TextColorLink("--mynah-color-text-link"),
TextColorInput("--mynah-color-text-input"),
TextColorDisabled("--mynah-color-text-disabled"),

Check warning on line 21 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/theme/CssVariable.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/theme/CssVariable.kt#L21

Added line #L21 was not covered by tests

Background("--mynah-color-bg"),
BackgroundAlt("--mynah-color-bg-alt"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
append(CssVariable.TextColorInput, theme.textFieldForeground)
append(CssVariable.TextColorLink, theme.linkText)
append(CssVariable.TextColorWeak, theme.inactiveText)
append(CssVariable.TextColorDisabled, theme.inactiveText)

Check warning on line 43 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/theme/ThemeBrowserAdapter.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/theme/ThemeBrowserAdapter.kt#L43

Added line #L43 was not covered by tests

append(CssVariable.Background, theme.background)
append(CssVariable.BackgroundAlt, theme.background)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import software.aws.toolkits.core.utils.error
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.core.utils.info
import software.aws.toolkits.core.utils.warn
import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnectionManager
import software.aws.toolkits.jetbrains.core.credentials.pinning.QConnection
import software.aws.toolkits.jetbrains.services.amazonq.lsp.flareChat.AsyncChatUiListener
Expand All @@ -43,7 +42,6 @@ import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.OpenF
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ShowSaveFileDialogParams
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.chat.ShowSaveFileDialogResult
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.ConnectionMetadata
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.SsoProfileData
import software.aws.toolkits.jetbrains.services.amazonq.lsp.util.TelemetryParsingUtil
import software.aws.toolkits.jetbrains.services.codewhisperer.customization.CodeWhispererModelConfigurator
import software.aws.toolkits.jetbrains.services.telemetry.TelemetryService
Expand Down Expand Up @@ -155,19 +153,7 @@ class AmazonQLanguageClientImpl(private val project: Project) : AmazonQLanguageC
val connection = ToolkitConnectionManager.getInstance(project)
.activeConnectionForFeature(QConnection.getInstance())

when (connection) {
is AwsBearerTokenConnection -> {
ConnectionMetadata(
SsoProfileData(connection.startUrl)
)
}
else -> {
// If no connection or not a bearer token connection return default builderID start url
ConnectionMetadata(
SsoProfileData(AmazonQLspConstants.AWS_BUILDER_ID_URL)
)
}
}
connection?.let { ConnectionMetadata.fromConnection(it) }
}

override fun openTab(params: LSPAny): CompletableFuture<LSPAny> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
package software.aws.toolkits.jetbrains.services.amazonq.lsp.auth

import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
import java.util.concurrent.CompletableFuture

interface AuthCredentialsService {
fun updateTokenCredentials(accessToken: String, encrypted: Boolean): CompletableFuture<ResponseMessage>
fun updateTokenCredentials(connection: ToolkitConnection, encrypted: Boolean): CompletableFuture<ResponseMessage>
fun deleteTokenCredentials(): CompletableFuture<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.LspServerConfigurations
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.UpdateConfigurationParams
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.BearerCredentials
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.ConnectionMetadata
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.UpdateCredentialsPayload
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.UpdateCredentialsPayloadData
import software.aws.toolkits.jetbrains.services.amazonq.profile.QRegionProfile
Expand All @@ -46,7 +47,7 @@

private val scheduler: ScheduledExecutorService = AppExecutorUtil.getAppScheduledExecutorService()
private var tokenSyncTask: ScheduledFuture<*>? = null
private val tokenSyncIntervalSeconds = 900L
private val tokenSyncIntervalMinutes = 5L

Check warning on line 50 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt#L50

Added line #L50 was not covered by tests

init {
project.messageBus.connect(serverInstance).apply {
Expand Down Expand Up @@ -98,14 +99,18 @@
LOG.warn(e) { "Failed to sync bearer token to Flare" }
}
},
tokenSyncIntervalSeconds,
tokenSyncIntervalSeconds,
TimeUnit.SECONDS
tokenSyncIntervalMinutes,
tokenSyncIntervalMinutes,
TimeUnit.MINUTES

Check warning on line 104 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt#L102-L104

Added lines #L102 - L104 were not covered by tests
)
}

override fun updateTokenCredentials(accessToken: String, encrypted: Boolean): CompletableFuture<ResponseMessage> {
val payload = createUpdateCredentialsPayload(accessToken, encrypted)
override fun updateTokenCredentials(connection: ToolkitConnection, encrypted: Boolean): CompletableFuture<ResponseMessage> {
val payload = try {
createUpdateCredentialsPayload(connection, encrypted)
} catch (e: Exception) {
return CompletableFuture.failedFuture(e)

Check warning on line 112 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt#L109-L112

Added lines #L109 - L112 were not covered by tests
}

return AmazonQLspService.executeIfRunning(project) { server ->
server.updateTokenCredentials(payload)
Expand Down Expand Up @@ -142,35 +147,39 @@
}

private fun updateTokenFromConnection(connection: ToolkitConnection): CompletableFuture<ResponseMessage> =
(connection.getConnectionSettings() as? TokenConnectionSettings)
updateTokenCredentials(connection, true)

Check warning on line 150 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt#L150

Added line #L150 was not covered by tests

override fun invalidate(providerId: String) {
deleteTokenCredentials()
}

Check warning on line 154 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt#L153-L154

Added lines #L153 - L154 were not covered by tests

private fun createUpdateCredentialsPayload(connection: ToolkitConnection, encrypted: Boolean): UpdateCredentialsPayload {
val token = (connection.getConnectionSettings() as? TokenConnectionSettings)
?.tokenProvider
?.delegate
?.let { it as? BearerTokenProvider }
?.currentToken()
?.accessToken
?.let { token -> updateTokenCredentials(token, true) }
?: CompletableFuture.failedFuture(IllegalStateException("Unable to get token from connection"))
?: error("Unable to get token from connection")

Check warning on line 163 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt#L163

Added line #L163 was not covered by tests

override fun invalidate(providerId: String) {
deleteTokenCredentials()
}

private fun createUpdateCredentialsPayload(token: String, encrypted: Boolean): UpdateCredentialsPayload =
if (encrypted) {
return if (encrypted) {
UpdateCredentialsPayload(
data = encryptionManager.encrypt(
UpdateCredentialsPayloadData(
BearerCredentials(token)
)
),
metadata = ConnectionMetadata.fromConnection(connection),

Check warning on line 172 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt#L172

Added line #L172 was not covered by tests
encrypted = true
)
} else {
UpdateCredentialsPayload(
data = token,
metadata = ConnectionMetadata.fromConnection(connection),

Check warning on line 178 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/auth/DefaultAuthCredentialsService.kt#L178

Added line #L178 was not covered by tests
encrypted = false
)
}
}

override fun onProfileSelected(project: Project, profile: QRegionProfile?) {
updateConfiguration()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,29 @@

package software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials

import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
import software.aws.toolkits.jetbrains.core.credentials.ToolkitConnection
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspConstants

data class ConnectionMetadata(
val sso: SsoProfileData,
)
) {
companion object {
fun fromConnection(connection: ToolkitConnection) = when (connection) {

Check warning on line 14 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/ConnectionMetadata.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/ConnectionMetadata.kt#L14

Added line #L14 was not covered by tests
is AwsBearerTokenConnection -> {
ConnectionMetadata(
SsoProfileData(connection.startUrl)

Check warning on line 17 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/ConnectionMetadata.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/ConnectionMetadata.kt#L16-L17

Added lines #L16 - L17 were not covered by tests
)
}
else -> {
// If no connection or not a bearer token connection return default builderID start url
ConnectionMetadata(
SsoProfileData(AmazonQLspConstants.AWS_BUILDER_ID_URL)

Check warning on line 23 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/ConnectionMetadata.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/ConnectionMetadata.kt#L22-L23

Added lines #L22 - L23 were not covered by tests
)
}
}

Check warning on line 26 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/ConnectionMetadata.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/ConnectionMetadata.kt#L26

Added line #L26 was not covered by tests
}
}

data class SsoProfileData(
val startUrl: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

data class UpdateCredentialsPayload(
val data: String,
val metadata: ConnectionMetadata,

Check warning on line 8 in plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/UpdateCredentialsPayload.kt

View check run for this annotation

Codecov / codecov/patch

plugins/amazonq/shared/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/lsp/model/aws/credentials/UpdateCredentialsPayload.kt#L8

Added line #L8 was not covered by tests
val encrypted: Boolean,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ class AmazonQLanguageClientImplTest {
every { mockConnectionManager.activeConnectionForFeature(QConnection.getInstance()) } returns null

assertThat(sut.getConnectionMetadata().get())
.isEqualTo(ConnectionMetadata(SsoProfileData(AmazonQLspConstants.AWS_BUILDER_ID_URL)))
.isEqualTo(null)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.InteractiveBe
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLanguageServer
import software.aws.toolkits.jetbrains.services.amazonq.lsp.AmazonQLspService
import software.aws.toolkits.jetbrains.services.amazonq.lsp.encryption.JwtEncryptionManager
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.ConnectionMetadata
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.SsoProfileData
import software.aws.toolkits.jetbrains.services.amazonq.lsp.model.aws.credentials.UpdateCredentialsPayload
import software.aws.toolkits.jetbrains.utils.isQConnected
import software.aws.toolkits.jetbrains.utils.isQExpired
Expand Down Expand Up @@ -112,6 +114,7 @@ class DefaultAuthCredentialsServiceTest {
connectionId: String = "test-connection-id",
): AwsBearerTokenConnection = mockk {
every { id } returns connectionId
every { startUrl } returns "startUrl"
every { getConnectionSettings() } returns createMockTokenSettings(accessToken)
}

Expand Down Expand Up @@ -192,17 +195,18 @@ class DefaultAuthCredentialsServiceTest {

@Test
fun `test updateTokenCredentials unencrypted success`() {
sut = DefaultAuthCredentialsService(project, mockEncryptionManager, mockk())

val token = "unencryptedToken"
val isEncrypted = false
sut = DefaultAuthCredentialsService(project, mockEncryptionManager, mockk())

sut.updateTokenCredentials(token, isEncrypted)
sut.updateTokenCredentials(mockConnection, isEncrypted)

verify(exactly = 1) {
mockLanguageServer.updateTokenCredentials(
UpdateCredentialsPayload(
token,
"test-access-token",
ConnectionMetadata(
SsoProfileData("startUrl")
),
isEncrypted
)
)
Expand All @@ -214,17 +218,19 @@ class DefaultAuthCredentialsServiceTest {
sut = DefaultAuthCredentialsService(project, mockEncryptionManager, mockk())

val encryptedToken = "encryptedToken"
val decryptedToken = "decryptedToken"
val isEncrypted = true

every { mockEncryptionManager.encrypt(any()) } returns encryptedToken

sut.updateTokenCredentials(decryptedToken, isEncrypted)
sut.updateTokenCredentials(mockConnection, isEncrypted)

verify(atLeast = 1) {
mockLanguageServer.updateTokenCredentials(
UpdateCredentialsPayload(
encryptedToken,
ConnectionMetadata(
SsoProfileData("startUrl")
),
isEncrypted
)
)
Expand Down
Loading