diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/Icons.kt b/src/main/kotlin/com/jetpackduba/gitnuro/Icons.kt index 6ff652f..f3e5fb9 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/Icons.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/Icons.kt @@ -49,6 +49,7 @@ object AppIcons { const val REMOVE_DONE = "remove_done.svg" const val REVERT = "revert.svg" const val SEARCH = "search.svg" + const val SECURITY = "security.svg" const val SETTINGS = "settings.svg" const val SIGN = "sign.svg" const val SOURCE = "source.svg" diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/credentials/HttpCredentialsProvider.kt b/src/main/kotlin/com/jetpackduba/gitnuro/credentials/HttpCredentialsProvider.kt index 0239bd6..d432066 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/credentials/HttpCredentialsProvider.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/credentials/HttpCredentialsProvider.kt @@ -2,13 +2,18 @@ package com.jetpackduba.gitnuro.credentials import com.jetpackduba.gitnuro.exceptions.NotSupportedHelper import com.jetpackduba.gitnuro.git.remote_operations.CredentialsCache +import com.jetpackduba.gitnuro.logging.printLog import com.jetpackduba.gitnuro.managers.IShellManager import com.jetpackduba.gitnuro.preferences.AppSettings import dagger.assisted.Assisted import dagger.assisted.AssistedInject import org.eclipse.jgit.api.Git +import org.eclipse.jgit.internal.JGitText import org.eclipse.jgit.lib.Config import org.eclipse.jgit.transport.CredentialItem +import org.eclipse.jgit.transport.CredentialItem.Password +import org.eclipse.jgit.transport.CredentialItem.Username +import org.eclipse.jgit.transport.CredentialItem.YesNoType import org.eclipse.jgit.transport.CredentialsProvider import org.eclipse.jgit.transport.URIish import java.io.* @@ -16,6 +21,7 @@ import java.util.concurrent.TimeUnit import kotlin.coroutines.cancellation.CancellationException private const val TIMEOUT_MIN = 1L +private const val TAG = "HttpCredentialsProvider" class HttpCredentialsProvider @AssistedInject constructor( private val credentialsStateManager: CredentialsStateManager, @@ -33,22 +39,42 @@ class HttpCredentialsProvider @AssistedInject constructor( override fun supports(vararg items: CredentialItem?): Boolean { val fields = items.map { credentialItem -> credentialItem?.promptText } - return if (fields.isEmpty()) { - true - } else - fields.size == 2 && - fields.contains("Username") && - fields.contains("Password") + val isEmpty = fields.isEmpty() + + val isUserPasswordAuth = fields.size == 2 && + fields.contains("Username") && + fields.contains("Password") + + val isAskingForSslDisable = items.any { it is YesNoType } + + return isEmpty || isUserPasswordAuth || isAskingForSslDisable } override fun get(uri: URIish, vararg items: CredentialItem): Boolean { - val userItem = items.firstOrNull { it.promptText == "Username" } - val passwordItem = items.firstOrNull { it.promptText == "Password" } + val itemsMap = items.map { "${it::class.simpleName} - ${it.promptText}" } - if (userItem !is CredentialItem.Username || passwordItem !is CredentialItem.Password) { + printLog(TAG, "Items are $itemsMap") + + val sslTrustNowItem = items + .filterIsInstance() + .firstOrNull { it.promptText.contains(JGitText.get().sslTrustNow) } + + val userItem = items + .filterIsInstance() + .firstOrNull() + + val passwordItem = items + .filterIsInstance() + .firstOrNull() + + if (userItem == null || passwordItem == null) { return false } + if (sslTrustNowItem != null) { + sslTrustNowItem.value = appSettings.verifySsl + } + val externalCredentialsHelper = getExternalCredentialsHelper(uri, git) if (externalCredentialsHelper == null) { diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/preferences/AppSettings.kt b/src/main/kotlin/com/jetpackduba/gitnuro/preferences/AppSettings.kt index cb2790a..04fc446 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/preferences/AppSettings.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/preferences/AppSettings.kt @@ -45,10 +45,13 @@ private const val PREF_GIT_FF_MERGE = "gitFFMerge" private const val PREF_GIT_PULL_REBASE = "gitPullRebase" private const val PREF_GIT_PUSH_WITH_LEASE = "gitPushWithLease" +private const val PREF_VERIFY_SSL = "verifySsl" + private const val DEFAULT_COMMITS_LIMIT = 1000 private const val DEFAULT_COMMITS_LIMIT_ENABLED = true private const val DEFAULT_SWAP_UNCOMMITTED_CHANGES = false private const val DEFAULT_CACHE_CREDENTIALS_IN_MEMORY = true +private const val DEFAULT_VERIFY_SSL = true const val DEFAULT_UI_SCALE = -1f @Singleton @@ -67,6 +70,9 @@ class AppSettings @Inject constructor() { private val _cacheCredentialsInMemoryFlow = MutableStateFlow(cacheCredentialsInMemory) val cacheCredentialsInMemoryFlow = _cacheCredentialsInMemoryFlow.asStateFlow() + private val _verifySslFlow = MutableStateFlow(cacheCredentialsInMemory) + val verifySslFlow = _cacheCredentialsInMemoryFlow.asStateFlow() + private val _ffMergeFlow = MutableStateFlow(ffMerge) val ffMergeFlow = _ffMergeFlow.asStateFlow() @@ -168,6 +174,15 @@ class AppSettings @Inject constructor() { _cacheCredentialsInMemoryFlow.value = value } + var verifySsl: Boolean + get() { + return preferences.getBoolean(PREF_VERIFY_SSL, DEFAULT_VERIFY_SSL) + } + set(value) { + preferences.putBoolean(PREF_VERIFY_SSL, value) + _verifySslFlow.value = value + } + var scaleUi: Float get() { return preferences.getFloat(PREF_UI_SCALE, DEFAULT_UI_SCALE) diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/settings/SettingsDialog.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/settings/SettingsDialog.kt index 9f0f3a5..61c93e9 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/settings/SettingsDialog.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/settings/SettingsDialog.kt @@ -49,6 +49,7 @@ val settings = listOf( SettingsEntry.Section("Network"), SettingsEntry.Entry(AppIcons.NETWORK, "Proxy") { Proxy(it) }, SettingsEntry.Entry(AppIcons.PASSWORD, "Authentication") { Authentication(it) }, + SettingsEntry.Entry(AppIcons.SECURITY, "Security") { Security(it) }, SettingsEntry.Section("Tools"), SettingsEntry.Entry(AppIcons.TERMINAL, "Terminal") { Terminal(it) }, @@ -355,6 +356,20 @@ private fun Authentication(settingsViewModel: SettingsViewModel) { ) } +@Composable +private fun Security(settingsViewModel: SettingsViewModel) { + val verifySsl by settingsViewModel.verifySslFlow.collectAsState() + + SettingToggle( + title = "Do not verify SSL security", + subtitle = "If active, you may connect to the remote server via insecure HTTPS connection", + value = !verifySsl, + onValueChanged = { value -> + settingsViewModel.verifySsl = !value + } + ) +} + @Composable fun Terminal(settingsViewModel: SettingsViewModel) { var commitsLimit by remember { mutableStateOf(settingsViewModel.terminalPath) } diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/SettingsViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/SettingsViewModel.kt index 307aa28..2aedbb8 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/SettingsViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/SettingsViewModel.kt @@ -29,6 +29,7 @@ class SettingsViewModel @Inject constructor( val commitsLimitEnabledFlow = appSettings.commitsLimitEnabledFlow val swapUncommittedChangesFlow = appSettings.swapUncommittedChangesFlow val cacheCredentialsInMemoryFlow = appSettings.cacheCredentialsInMemoryFlow + val verifySslFlow = appSettings.verifySslFlow val terminalPathFlow = appSettings.terminalPathFlow var scaleUi: Float @@ -61,6 +62,12 @@ class SettingsViewModel @Inject constructor( appSettings.cacheCredentialsInMemory = value } + var verifySsl: Boolean + get() = appSettings.verifySsl + set(value) { + appSettings.verifySsl = value + } + var pullRebase: Boolean get() = appSettings.pullRebase set(value) { diff --git a/src/main/resources/security.svg b/src/main/resources/security.svg new file mode 100644 index 0000000..ecb1f58 --- /dev/null +++ b/src/main/resources/security.svg @@ -0,0 +1 @@ + \ No newline at end of file