From 93baeb7092da2014577cdef21ec21a4bd7338af9 Mon Sep 17 00:00:00 2001 From: joelgaspard <4029620+joelgaspard@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:17:16 +0200 Subject: [PATCH 1/5] feat: authetication by api key in synchronization --- .../fr/enedis/chutney/kotlin/authentication/AuthMethod.kt | 2 ++ .../kotlin/fr/enedis/chutney/kotlin/util/ChutneyServerInfo.kt | 1 + .../main/kotlin/fr/enedis/chutney/kotlin/util/HttpClient.kt | 3 +++ 3 files changed, 6 insertions(+) diff --git a/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/authentication/AuthMethod.kt b/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/authentication/AuthMethod.kt index 7fc3b7062..a28d36463 100644 --- a/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/authentication/AuthMethod.kt +++ b/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/authentication/AuthMethod.kt @@ -13,4 +13,6 @@ sealed interface AuthMethod { val password: String): AuthMethod data class Bearer(val token: String): AuthMethod + + data class ApiKey(val token: String): AuthMethod } diff --git a/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/util/ChutneyServerInfo.kt b/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/util/ChutneyServerInfo.kt index ad96744ab..ae975627a 100644 --- a/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/util/ChutneyServerInfo.kt +++ b/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/util/ChutneyServerInfo.kt @@ -70,6 +70,7 @@ data class ChutneyServerInfo( fun isBasicAuth(): Boolean = auth is AuthMethod.Basic fun isTokenAuth(): Boolean = auth is AuthMethod.Bearer + fun isApiKeyAuth(): Boolean = auth is AuthMethod.ApiKey } private enum class ProxyProtocol { http, https } diff --git a/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/util/HttpClient.kt b/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/util/HttpClient.kt index b9b76d8ea..d04869c8e 100644 --- a/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/util/HttpClient.kt +++ b/kotlin-dsl/src/main/kotlin/fr/enedis/chutney/kotlin/util/HttpClient.kt @@ -159,6 +159,9 @@ object HttpClient { if(serverInfo.isTokenAuth()) { httpRequest.addHeader("Authorization", "Bearer " + (serverInfo.auth as AuthMethod.Bearer).token) } + if(serverInfo.isApiKeyAuth()) { + httpRequest.addHeader("X-API-KEY", (serverInfo.auth as AuthMethod.ApiKey).token) + } return httpRequest } From 02d58b097e7a6986d8c26e2cc72c9b016a173394 Mon Sep 17 00:00:00 2001 From: joelgaspard <4029620+joelgaspard@users.noreply.github.com> Date: Wed, 15 Jul 2026 15:11:25 +0200 Subject: [PATCH 2/5] feat: authentication by api key in idea plugin --- .../chutney/idea/settings/AuthMethodEnum.kt | 14 +++++++++ .../chutney/idea/settings/ChutneySettings.kt | 9 ++++-- .../settings/ChutneySettingsConfigurable.kt | 31 +++++++++++++------ 3 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/AuthMethodEnum.kt diff --git a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/AuthMethodEnum.kt b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/AuthMethodEnum.kt new file mode 100644 index 000000000..e10bdb304 --- /dev/null +++ b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/AuthMethodEnum.kt @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2017-2026 Enedis + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +package fr.enedis.chutney.idea.settings + +enum class AuthMethodEnum { + BASIC, + BEARER, + API_KEY +} \ No newline at end of file diff --git a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettings.kt b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettings.kt index 1be996425..103970090 100755 --- a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettings.kt +++ b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettings.kt @@ -24,7 +24,7 @@ class ChutneySettings : PersistentStateComponent AuthMethod.Basic(user.orEmpty(), password.orEmpty()) + AuthMethodEnum.BEARER -> AuthMethod.Bearer(token.orEmpty()) + AuthMethodEnum.API_KEY -> AuthMethod.ApiKey(token.orEmpty()) + }, proxyUrl = proxyUrl.takeIf { ! it.isNullOrBlank() }, proxyUser = proxyUser.takeIf { ! it.isNullOrBlank() }, proxyPassword = proxyPassword.takeIf { ! it.isNullOrBlank() } diff --git a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt index 6163a52c7..ad1ec2c6f 100755 --- a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt +++ b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt @@ -43,7 +43,8 @@ class ChutneySettingsConfigurable : val authModeLabel: JLabel = JLabel("Authentication mode") val basicAuthButton = JBRadioButton("Basic") - val tokenAuthButton = JBRadioButton("Token") + val bearerAuthButton = JBRadioButton("Bearer") + val apiKeyAuthButton = JBRadioButton("API Key") val authButtonsGroup = ButtonGroup() val chutneySettings: ChutneySettings = ChutneySettings.getInstance() @@ -88,7 +89,8 @@ class ChutneySettingsConfigurable : private fun stateFromFields() = ChutneySettings.ChutneySettingsState( url = url.text, - basicAuth = basicAuthButton.isSelected, + auth = if(basicAuthButton.isSelected) AuthMethodEnum.BASIC + else if(bearerAuthButton.isSelected) AuthMethodEnum.BEARER else AuthMethodEnum.API_KEY , user = user.text, password = String(password.password), token = token.text, @@ -100,16 +102,21 @@ class ChutneySettingsConfigurable : private fun initFields() { val serverInfo = chutneySettings.state.serverInfo() url.text = serverInfo?.url - basicAuthButton.isSelected = chutneySettings.state.basicAuth == true - tokenAuthButton.isSelected = chutneySettings.state.basicAuth == false + basicAuthButton.isSelected = chutneySettings.state.auth == AuthMethodEnum.BASIC + bearerAuthButton.isSelected = chutneySettings.state.auth == AuthMethodEnum.BEARER + apiKeyAuthButton.isSelected = chutneySettings.state.auth == AuthMethodEnum.API_KEY user.text = if(serverInfo?.auth is AuthMethod.Basic) (serverInfo.auth as AuthMethod.Basic).user else "" password.text = if(serverInfo?.auth is AuthMethod.Basic) (serverInfo.auth as AuthMethod.Basic).password else "" - token.text = if(serverInfo?.auth is AuthMethod.Bearer) (serverInfo.auth as AuthMethod.Bearer).token else "" + if(serverInfo?.auth is AuthMethod.Bearer) { + token.text = (serverInfo.auth as AuthMethod.Bearer).token + } else if(serverInfo?.auth is AuthMethod.ApiKey) { + token.text = (serverInfo.auth as AuthMethod.ApiKey).token + } proxyUrl.text = serverInfo?.proxyUrl proxyUser.text = serverInfo?.proxyUser proxyPassword.text = serverInfo?.proxyPassword - updateAuthFields(isBasic = basicAuthButton.isSelected, isToken = tokenAuthButton.isSelected) + updateAuthFields(isBasic = basicAuthButton.isSelected, isToken = bearerAuthButton.isSelected || apiKeyAuthButton.isSelected) } override fun createComponent(): JComponent { @@ -123,7 +130,8 @@ class ChutneySettingsConfigurable : val serverInfo = ChutneyServerInfo( url.text, if(basicAuthButton.isSelected) AuthMethod.Basic(user.text, String(password.password)) - else AuthMethod.Bearer(token.text), + else if(bearerAuthButton.isSelected) AuthMethod.Bearer(token.text) + else AuthMethod.ApiKey(token.text), proxyUrl.text.ifBlank { null }, proxyUser.text.ifBlank { null }, String(proxyPassword.password).ifBlank { null } @@ -139,11 +147,13 @@ class ChutneySettingsConfigurable : } authButtonsGroup.add(basicAuthButton) - authButtonsGroup.add(tokenAuthButton) + authButtonsGroup.add(bearerAuthButton) + authButtonsGroup.add(apiKeyAuthButton) val authButtonsPanel = JPanel(BorderLayout()) authButtonsPanel.add(basicAuthButton, BorderLayout.WEST) - authButtonsPanel.add(tokenAuthButton, BorderLayout.CENTER) + authButtonsPanel.add(bearerAuthButton, BorderLayout.CENTER) + authButtonsPanel.add(apiKeyAuthButton, BorderLayout.EAST) val myWrapper = JPanel(BorderLayout()) val centerPanel = @@ -164,7 +174,8 @@ class ChutneySettingsConfigurable : .panel basicAuthButton.addActionListener { basicButtonSelected() } - tokenAuthButton.addActionListener { tokenButtonSelected() } + bearerAuthButton.addActionListener { tokenButtonSelected() } + apiKeyAuthButton.addActionListener { tokenButtonSelected() } myWrapper.add(centerPanel, BorderLayout.NORTH) return myWrapper From afbb00a21c21cd880d9a393c64566f718a6054ce Mon Sep 17 00:00:00 2001 From: jgaspard <4029620+explorer11@users.noreply.github.com> Date: Tue, 21 Jul 2026 11:18:28 +0200 Subject: [PATCH 3/5] fix: compilation --- .../kotlin/fr/enedis/chutney/idea/settings/ChutneySettings.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettings.kt b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettings.kt index 103970090..fdc864f69 100755 --- a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettings.kt +++ b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettings.kt @@ -24,7 +24,7 @@ class ChutneySettings : PersistentStateComponent Date: Tue, 21 Jul 2026 14:03:17 +0200 Subject: [PATCH 4/5] fix: check connection button --- .../settings/ChutneySettingsConfigurable.kt | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt index ad1ec2c6f..00334171f 100755 --- a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt +++ b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt @@ -21,6 +21,7 @@ import fr.enedis.chutney.kotlin.util.ChutneyServerInfo import fr.enedis.chutney.kotlin.util.HttpClient import java.awt.BorderLayout import java.awt.Color +import java.awt.GridLayout import javax.swing.* @@ -44,9 +45,11 @@ class ChutneySettingsConfigurable : val authModeLabel: JLabel = JLabel("Authentication mode") val basicAuthButton = JBRadioButton("Basic") val bearerAuthButton = JBRadioButton("Bearer") - val apiKeyAuthButton = JBRadioButton("API Key") + val apiKeyAuthButton = JBRadioButton("API-Key") val authButtonsGroup = ButtonGroup() + val checkConnectionButton = JButton("Check connection") + val chutneySettings: ChutneySettings = ChutneySettings.getInstance() override fun isModified(): Boolean { @@ -70,14 +73,18 @@ class ChutneySettingsConfigurable : } private fun basicButtonSelected() { - updateAuthFields(isBasic = true, isToken = false) + updateAuthFields(isBasic = true, isToken = false, isApiKey = false) } private fun tokenButtonSelected() { - updateAuthFields(isBasic = false, isToken = true) + updateAuthFields(isBasic = false, isToken = true, isApiKey = false) + } + + private fun apiKeyButtonSelected() { + updateAuthFields(isBasic = false, isToken = false, isApiKey = true) } - private fun updateAuthFields(isBasic: Boolean, isToken: Boolean) { + private fun updateAuthFields(isBasic: Boolean, isToken: Boolean, isApiKey: Boolean) { user.isVisible = isBasic userLabel.isVisible = isBasic password.isVisible = isBasic @@ -85,6 +92,8 @@ class ChutneySettingsConfigurable : token.isVisible = isToken tokenLabel.isVisible = isToken + + checkConnectionButton.isVisible = isBasic || isToken } private fun stateFromFields() = ChutneySettings.ChutneySettingsState( @@ -116,13 +125,12 @@ class ChutneySettingsConfigurable : proxyUser.text = serverInfo?.proxyUser proxyPassword.text = serverInfo?.proxyPassword - updateAuthFields(isBasic = basicAuthButton.isSelected, isToken = bearerAuthButton.isSelected || apiKeyAuthButton.isSelected) + updateAuthFields(isBasic = basicAuthButton.isSelected, isToken = bearerAuthButton.isSelected, isApiKey = apiKeyAuthButton.isSelected) } override fun createComponent(): JComponent { initFields() - val checkConnectionButton = JButton("Check connection") val checkLabel = JBLabel("").apply { isVisible = false } checkConnectionButton.addActionListener { @@ -150,10 +158,10 @@ class ChutneySettingsConfigurable : authButtonsGroup.add(bearerAuthButton) authButtonsGroup.add(apiKeyAuthButton) - val authButtonsPanel = JPanel(BorderLayout()) - authButtonsPanel.add(basicAuthButton, BorderLayout.WEST) - authButtonsPanel.add(bearerAuthButton, BorderLayout.CENTER) - authButtonsPanel.add(apiKeyAuthButton, BorderLayout.EAST) + val authButtonsPanel = JPanel(GridLayout(1, 3)) + authButtonsPanel.add(basicAuthButton) + authButtonsPanel.add(bearerAuthButton) + authButtonsPanel.add(apiKeyAuthButton) val myWrapper = JPanel(BorderLayout()) val centerPanel = @@ -175,7 +183,7 @@ class ChutneySettingsConfigurable : basicAuthButton.addActionListener { basicButtonSelected() } bearerAuthButton.addActionListener { tokenButtonSelected() } - apiKeyAuthButton.addActionListener { tokenButtonSelected() } + apiKeyAuthButton.addActionListener { apiKeyButtonSelected() } myWrapper.add(centerPanel, BorderLayout.NORTH) return myWrapper From fe9e337506fd646167cff8b7e902b0ed96fb3e16 Mon Sep 17 00:00:00 2001 From: jgaspard <4029620+explorer11@users.noreply.github.com> Date: Tue, 21 Jul 2026 14:04:56 +0200 Subject: [PATCH 5/5] fix: simplify code --- .../idea/settings/ChutneySettingsConfigurable.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt index 00334171f..0e7d85de1 100755 --- a/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt +++ b/idea-plugin/src/main/kotlin/fr/enedis/chutney/idea/settings/ChutneySettingsConfigurable.kt @@ -73,18 +73,18 @@ class ChutneySettingsConfigurable : } private fun basicButtonSelected() { - updateAuthFields(isBasic = true, isToken = false, isApiKey = false) + updateAuthFields(isBasic = true, isToken = false) } private fun tokenButtonSelected() { - updateAuthFields(isBasic = false, isToken = true, isApiKey = false) + updateAuthFields(isBasic = false, isToken = true) } private fun apiKeyButtonSelected() { - updateAuthFields(isBasic = false, isToken = false, isApiKey = true) + updateAuthFields(isBasic = false, isToken = false) } - private fun updateAuthFields(isBasic: Boolean, isToken: Boolean, isApiKey: Boolean) { + private fun updateAuthFields(isBasic: Boolean, isToken: Boolean) { user.isVisible = isBasic userLabel.isVisible = isBasic password.isVisible = isBasic @@ -125,7 +125,7 @@ class ChutneySettingsConfigurable : proxyUser.text = serverInfo?.proxyUser proxyPassword.text = serverInfo?.proxyPassword - updateAuthFields(isBasic = basicAuthButton.isSelected, isToken = bearerAuthButton.isSelected, isApiKey = apiKeyAuthButton.isSelected) + updateAuthFields(isBasic = basicAuthButton.isSelected, isToken = bearerAuthButton.isSelected) } override fun createComponent(): JComponent {