diff --git a/CHANGELOG.md b/CHANGELOG.md index a7f30105..0a9ed6d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Option to view an individual file's history in the source control menu (#960) - Change context menu now lists IPM packages from all Git-enabled namespaces, prefixed with the namespace name (#952) - Pull event handler option in settings page now displays user-friendly names for options (#908) +- Validation that SSH key file path is not a directory when configuring Embedded Git (#943) ### Fixed - Changes to % routines mapped to the current namespace may now be added to source control and committed (#944) diff --git a/cls/SourceControl/Git/Settings.cls b/cls/SourceControl/Git/Settings.cls index 7f871933..f6a65b10 100644 --- a/cls/SourceControl/Git/Settings.cls +++ b/cls/SourceControl/Git/Settings.cls @@ -427,6 +427,11 @@ ClassMethod HasNamespaceWebApp(Output webAppDirectory) As %Boolean [ Internal ] Method OnAfterConfigure() As %Boolean [ Internal ] { set defaultPromptFlag = $$$DisableBackupCharMask + $$$TrapCtrlCMask + $$$EnableQuitCharMask + $$$DisableHelpCharMask + $$$DisableHelpContextCharMask + $$$TrapErrorMask + set sc = ..ValidatePrivateKeyFilePath(..privateKeyFile) + if $$$ISERR(sc) { + write !, $System.Status.GetErrorText(sc), ! + quit + } if (..privateKeyFile '= "") && '##class(%File).Exists(..privateKeyFile) { set value = 1 set response = ##class(%Library.Prompt).GetYesNo("Do you wish to create a new SSH key pair?",.value,,defaultPromptFlag) @@ -508,6 +513,14 @@ Method OnAfterConfigure() As %Boolean [ Internal ] } } +ClassMethod ValidatePrivateKeyFilePath(path As %String) As %Status +{ + if (path '= "") && ##class(%File).DirectoryExists(path) { + quit $$$ERROR($$$GeneralError, "SSH key file path is a directory. Please specify the full path to the key file.") + } + quit $$$OK +} + Method ConfigureBinPath(ByRef path As %String) As %Boolean [ Internal ] { if (path = "") { return 1 } diff --git a/csp/gitprojectsettings.csp b/csp/gitprojectsettings.csp index c70f2e1c..1f51ab2a 100644 --- a/csp/gitprojectsettings.csp +++ b/csp/gitprojectsettings.csp @@ -352,7 +352,12 @@ body {
Set fileExists = ##class(%File).Exists(settings.privateKeyFile) - if (settings.privateKeyFile = "") { + set validateSC = ##class(SourceControl.Git.Settings).ValidatePrivateKeyFilePath(settings.privateKeyFile) + if $$$ISERR(validateSC) { + set class = "form-control is-invalid" + set divClass = "invalid-feedback" + set feedbackText = $System.Status.GetErrorText(validateSC) + } elseif (settings.privateKeyFile = "") { set class = "form-control" set divClass = "neutral-feedback" set feedbackText = "You must configure an SSH private key to be able to work with remotes. This should be set up as a deploy key / equivalent, authenticating the server, not a specific user." @@ -379,7 +384,7 @@ body {
- if (settings.privateKeyFile '= "") && fileExists { + if (settings.privateKeyFile '= "") && fileExists && $$$ISOK(validateSC) { set pubKeyName = settings.privateKeyFile_".pub" if ##class(%File).Exists(pubKeyName) { set pubStream = ##class(%Stream.FileCharacter).%OpenId(pubKeyName) diff --git a/test/UnitTest/SourceControl/Git/Settings.cls b/test/UnitTest/SourceControl/Git/Settings.cls index 038e2dd6..60470972 100644 --- a/test/UnitTest/SourceControl/Git/Settings.cls +++ b/test/UnitTest/SourceControl/Git/Settings.cls @@ -160,4 +160,19 @@ Method %OnClose() As %Status quit $$$OK } +Method TestValidatePrivateKeyFilePath() +{ + // empty path is OK + do $$$AssertStatusOK(##class(SourceControl.Git.Settings).ValidatePrivateKeyFilePath("")) + + // nonexistent file path is OK (will trigger key-generation prompt separately) + do $$$AssertStatusOK(##class(SourceControl.Git.Settings).ValidatePrivateKeyFilePath("/nonexistent/path/id_rsa")) + + // a directory path is an error + set mgrDir = ##class(%File).NormalizeDirectory($System.Util.ManagerDirectory()) + set sc = ##class(SourceControl.Git.Settings).ValidatePrivateKeyFilePath(mgrDir) + do $$$AssertStatusNotOK(sc) + do $$$AssertTrue($System.Status.GetErrorText(sc) [ "SSH key file path is a directory") +} + }