Skip to content

Commit

Permalink
Merge pull request #189 from zowe/feature/IJMP-1814
Browse files Browse the repository at this point in the history
IJMP-1814 Added parsing all zosmf profiles
  • Loading branch information
ktsytsen authored Aug 21, 2024
2 parents 4a91572 + 7f36d12 commit 4e51e18
Show file tree
Hide file tree
Showing 14 changed files with 880 additions and 174 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ val junitVersion = "5.10.2"
val mockkVersion = "1.13.10"
val ibmMqVersion = "9.3.5.0"
val jGraphTVersion = "1.5.2"
val zoweKotlinSdkVersion = "0.5.0-rc.8"
val zoweKotlinSdkVersion = "0.5.0-rc.11"
val javaKeytarVersion = "1.0.0"

repositories {
Expand Down
1 change: 1 addition & 0 deletions gradle/sonar.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ subprojects {
properties {
property "sonar.sources", "src/main/kotlin"
property "sonar.tests", "src/test/kotlin"
property 'sonar.exclusions', "**/src/IC-231/**, **/src/IC-223/**"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,30 @@ private fun createCredentialAttributes(key: String): CredentialAttributes {
*/
class CredentialServiceImpl : CredentialService {

/**
* Get PasswordSafe service
* Required for test purposes
*/
private fun getPasswordSafeService(): PasswordSafe {
return service<PasswordSafe>()
}

/**
* Get user credentials by connection config UUID.
* @param connectionConfigUuid connection configuration universally unique identifier.
* @return user credentials [Credentials] if they are.
*/
private fun getCredentials(connectionConfigUuid: String): Credentials? {
return service<PasswordSafe>().get(createCredentialAttributes(connectionConfigUuid))
val credentialAttributes = createCredentialAttributes(connectionConfigUuid)
var ret = service<PasswordSafe>().get(credentialAttributes)
//Another attempt to read the password was added, since the saving of credentials occurs in a separate thread
//and depends on the operating system. If we saved the credentials and try to read them in another thread,
//but they have not yet actually been saved in storage.
if (ret==null){
Thread.sleep(10)
ret = getPasswordSafeService().get(credentialAttributes)
}
return ret
}

/**
Expand Down Expand Up @@ -67,7 +84,7 @@ class CredentialServiceImpl : CredentialService {
val credentialAttributes = createCredentialAttributes(connectionConfigUuid)
val credentials = Credentials(username, password)
runBackgroundableTask("Setting user credentials") {
service<PasswordSafe>().set(credentialAttributes, credentials)
getPasswordSafeService().set(credentialAttributes, credentials)
sendTopic(CREDENTIALS_CHANGED).onChanged(connectionConfigUuid)
}
}
Expand All @@ -78,7 +95,7 @@ class CredentialServiceImpl : CredentialService {
*/
override fun clearCredentials(connectionConfigUuid: String) {
val credentialAttributes = createCredentialAttributes(connectionConfigUuid)
service<PasswordSafe>().set(credentialAttributes, null)
getPasswordSafeService().set(credentialAttributes, null)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ class ConnectionDialog(
)
.bindText(state::username)
.validationOnApply {
it.text = it.text.trim()
if (it !is JPasswordField)
it.text = it.text.trim()
validateForBlank(it)
}.onApply {
state.username = state.username.uppercase()
Expand All @@ -299,7 +300,8 @@ class ConnectionDialog(
.widthGroup(sameWidthLabelsGroup)
passField = cell(JPasswordField())
.bindText(state::password)
.validationOnApply { validateForBlank(it) }
.validationOnApply {
validateForBlank(it) }
.align(AlignX.FILL)
}
indent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import org.zowe.explorer.utils.crudable.getAll
import org.zowe.explorer.utils.isThe
import org.zowe.explorer.utils.runWriteActionInEdtAndWait
import org.zowe.explorer.utils.toMutableList
import org.zowe.explorer.zowe.service.ZoweConfigServiceImpl
import org.zowe.kotlinsdk.zowe.config.ZoweConfig
import org.zowe.kotlinsdk.zowe.config.parseConfigJson
import java.awt.event.MouseAdapter
Expand Down Expand Up @@ -63,14 +64,23 @@ class ZOSMFConnectionConfigurable : BoundSearchableConfigurable("z/OSMF Connecti
showAndTestConnection()?.let { connectionsTableModel?.addRow(it) }
}

/**Unable to save invalid URL
* Updates the selected profilef or current connection.
* If update is not possible(brocken URL), throws IllegalStateException exception
*/
@Throws(IllegalStateException::class)
private fun ZoweConfig.updateFromState(state: ConnectionDialogState) {
val uri = URI(state.connectionUrl)
if (uri.host.isNullOrEmpty())
throw IllegalStateException("Unable to save invalid URL: ${state.connectionUrl}")
setProfile(ZoweConfigServiceImpl.getProfileNameFromConnName(state.connectionName))
host = uri.host
port = uri.port.toLong()
port = if (uri.port==-1) 10443 else uri.port.toLong()
protocol = state.connectionUrl.split("://")[0]
user = state.username
password = state.password
rejectUnauthorized = !state.isAllowSsl
restoreProfile()
}

/**
Expand All @@ -81,7 +91,9 @@ class ZOSMFConnectionConfigurable : BoundSearchableConfigurable("z/OSMF Connecti
private fun updateZoweConfigIfNeeded(state: ConnectionDialogState?) {
val res = showOkCancelDialog(
title = "Zowe Config Update",
message = "Do you want to update zowe config file?\n${state?.zoweConfigPath}",
message = "Do you want to update zowe config file and credentials in secret store?"
+ "\n${state?.connectionName}"
+ "\n${state?.zoweConfigPath}",
okText = "Yes",
cancelText = "No"
)
Expand All @@ -95,11 +107,21 @@ class ZOSMFConnectionConfigurable : BoundSearchableConfigurable("z/OSMF Connecti

val zoweConfig = parseConfigJson(configFile.inputStream)
zoweConfig.extractSecureProperties(configFile.path.split("/").toTypedArray())
zoweConfig.updateFromState(state)
runWriteActionInEdtAndWait {
zoweConfig.saveSecureProperties(configFile.path.split("/").toTypedArray())
configFile.setBinaryContent(zoweConfig.toJson().toByteArray(configFile.charset))
kotlin.runCatching {
zoweConfig.updateFromState(state)
}
.onSuccess {
runWriteActionInEdtAndWait {
zoweConfig.setProfile(ZoweConfigServiceImpl.getProfileNameFromConnName(state.connectionName))
zoweConfig.saveSecureProperties(configFile.path.split("/").toTypedArray())
zoweConfig.restoreProfile()
configFile.setBinaryContent(zoweConfig.toJson().toByteArray(configFile.charset))
}
}
.onFailure {
Messages.showErrorDialog("Unable to save invalid URL: ${state.connectionUrl}", "Invalid URL")
return
}
}
}

Expand All @@ -112,8 +134,9 @@ class ZOSMFConnectionConfigurable : BoundSearchableConfigurable("z/OSMF Connecti
val state = showAndTestConnection(connectionsTableModel!![idx].apply {
mode = DialogMode.UPDATE
})
state?.zoweConfigPath?.let {
zoweConfigStates[it] = state
state?.let {
if (it.zoweConfigPath != null)
zoweConfigStates[it.connectionName] = state
}
if (state != null) {
connectionsTableModel?.set(idx, state)
Expand Down Expand Up @@ -319,7 +342,7 @@ class ZOSMFConnectionConfigurable : BoundSearchableConfigurable("z/OSMF Connecti
/** Check are the Credentials and Connections sandboxes modified */
override fun isModified(): Boolean {
return isSandboxModified<Credentials>()
|| isSandboxModified<ConnectionConfig>()
|| isSandboxModified<ConnectionConfig>()
}

override fun cancel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import org.zowe.explorer.explorer.ui.UssDirNode
import org.zowe.explorer.explorer.ui.UssFileNode
import org.zowe.explorer.utils.crudable.Crudable
import org.zowe.explorer.utils.crudable.find
import org.zowe.kotlinsdk.DatasetOrganization
import javax.swing.JComponent
import javax.swing.JPasswordField
import javax.swing.JTextField

private val urlRegex = Regex("^(https?|http)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]")
private val urlRegex =
Regex("^(https?|http)://[-a-zA-Z0-9+&@#/%?=~_|!,.;]*(:((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{1,5})|([0-9]{1,4})))?")
private val maskRegex = Regex("^[A-Za-z\\$\\*%@#][A-Za-z0-9\\-\\$\\*%@#]{0,7}")
private val ussPathRegex = Regex("^/$|^(/[^/]+)+$")
private val forbiddenSymbol = "/"
Expand Down Expand Up @@ -81,7 +81,10 @@ fun validateForPassword(password: String, component: JPasswordField): Validation
* @param component the component to check the text in
*/
fun validateForBlank(component: JTextField): ValidationInfo? {
return validateForBlank(component.text, component)
return if(component is JPasswordField){
validateForBlank(String(component.password).trim(), component)
}
else validateForBlank(component.text, component)
}

/**
Expand Down
16 changes: 10 additions & 6 deletions src/main/kotlin/org/zowe/explorer/zowe/ZoweStartupActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ import org.zowe.explorer.config.connect.ConnectionConfig
import org.zowe.explorer.explorer.EXPLORER_NOTIFICATION_GROUP_ID
import org.zowe.explorer.utils.subscribe
import org.zowe.explorer.zowe.service.*
import org.zowe.explorer.zowe.service.ZoweConfigService.Companion.lock
import org.zowe.kotlinsdk.zowe.config.ZoweConfig
import java.util.regex.Pattern
import kotlin.concurrent.write

const val ZOWE_CONFIG_NAME = "zowe.config.json"

Expand Down Expand Up @@ -71,15 +73,15 @@ fun showNotificationForAddUpdateZoweConfigIfNeeded(project: Project, type: ZoweC
fun showDialogForDeleteZoweConfigIfNeeded(project: Project, type: ZoweConfigType) {
val zoweConfigService = project.service<ZoweConfigService>()
val zoweConfigState = zoweConfigService.getZoweConfigState(type = type)
if (zoweConfigState != ZoweConfigState.NEED_TO_ADD || zoweConfigState != ZoweConfigState.NOT_EXISTS) {
if (zoweConfigState != ZoweConfigState.NEED_TO_ADD && zoweConfigState != ZoweConfigState.NOT_EXISTS) {
val choice = Messages.showDialog(
project,
"$type Zowe config file has been deleted.\n" +
"Would you like to delete the corresponding connection?\n" +
"If you decide to leave the connection, it will be converted to a regular connection (username will be visible).",
"Deleting Zowe Config connection",
arrayOf(
"Delete Connection", "Keep Connection"
"Delete Connection(s)", "Keep Connection(s)"
),
0,
AllIcons.General.QuestionDialog
Expand All @@ -88,10 +90,12 @@ fun showDialogForDeleteZoweConfigIfNeeded(project: Project, type: ZoweConfigType
zoweConfigService.deleteZoweConfig(type)
}
}
if (type == ZoweConfigType.LOCAL)
zoweConfigService.localZoweConfig = null
else
zoweConfigService.globalZoweConfig = null
lock.write {
if (type == ZoweConfigType.LOCAL)
zoweConfigService.localZoweConfig = null
else
zoweConfigService.globalZoweConfig = null
}
zoweConfigService.checkAndRemoveOldZoweConnection(type)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import com.intellij.openapi.actionSystem.CommonDataKeys
import com.intellij.openapi.components.service
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.project.DumbAwareAction
import org.zowe.explorer.utils.write
import org.zowe.explorer.zowe.service.ZoweConfigService
import org.zowe.explorer.zowe.service.ZoweConfigService.Companion.lock
import org.zowe.explorer.zowe.service.ZoweConfigServiceImpl
import org.zowe.explorer.zowe.service.ZoweConfigState
import org.zowe.explorer.zowe.service.ZoweConfigType
Expand All @@ -29,8 +31,7 @@ import org.zowe.kotlinsdk.zowe.config.parseConfigJson
* @since 2021-02-12
*/
class UpdateZoweConfigAction : DumbAwareAction() {

override fun getActionUpdateThread() = ActionUpdateThread.EDT
override fun getActionUpdateThread() = ActionUpdateThread.BGT

override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: let {
Expand Down Expand Up @@ -75,27 +76,26 @@ class UpdateZoweConfigAction : DumbAwareAction() {
type = ZoweConfigType.LOCAL

val zoweConfigService = project.service<ZoweConfigService>()

val prevZoweConfig = if (type == ZoweConfigType.LOCAL)
zoweConfigService.localZoweConfig
else
zoweConfigService.globalZoweConfig
runCatching {
lock.write {
val prevZoweConfig = if (type == ZoweConfigType.LOCAL)
zoweConfigService.localZoweConfig
else
zoweConfigService.globalZoweConfig
if (type == ZoweConfigType.LOCAL) {
zoweConfigService.localZoweConfig = parseConfigJson(editor.document.text)
zoweConfigService.localZoweConfig?.extractSecureProperties(vFile.path.split("/").toTypedArray())
} else {
zoweConfigService.globalZoweConfig = parseConfigJson(editor.document.text)
zoweConfigService.globalZoweConfig?.extractSecureProperties(vFile.path.split("/").toTypedArray())
}
}
val zoweState = zoweConfigService.getZoweConfigState(false, type = type)
e.presentation.isEnabledAndVisible =
zoweState == ZoweConfigState.NEED_TO_UPDATE || zoweState == ZoweConfigState.NEED_TO_ADD
if (type == ZoweConfigType.LOCAL) {
zoweConfigService.localZoweConfig = prevZoweConfig
} else {
zoweConfigService.globalZoweConfig = prevZoweConfig
val zoweState = zoweConfigService.getZoweConfigState(false, type = type)
e.presentation.isEnabledAndVisible =
zoweState == ZoweConfigState.NEED_TO_UPDATE || zoweState == ZoweConfigState.NEED_TO_ADD
if (type == ZoweConfigType.LOCAL) {
zoweConfigService.localZoweConfig = prevZoweConfig
} else {
zoweConfigService.globalZoweConfig = prevZoweConfig
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import com.intellij.util.messages.Topic
import org.zowe.explorer.config.connect.ConnectionConfig
import org.zowe.explorer.config.connect.ui.zosmf.ConnectionDialogState
import org.zowe.kotlinsdk.zowe.config.ZoweConfig
import java.util.concurrent.locks.ReentrantReadWriteLock


/**
Expand Down Expand Up @@ -78,7 +79,7 @@ interface ZoweConfigService {
* @param checkConnection - Verify zowe connection by sending info request if true.
* @return - ConnectionConfig that was added or updated.
*/
fun addOrUpdateZoweConfig(scanProject: Boolean = true, checkConnection: Boolean = true, type: ZoweConfigType): ConnectionConfig?
fun addOrUpdateZoweConfig(scanProject: Boolean = true, checkConnection: Boolean = true, type: ZoweConfigType)

/**
* Deletes connection config related to zoweConnection
Expand All @@ -102,6 +103,7 @@ interface ZoweConfigService {

companion object {
fun getInstance(project: Project): ZoweConfigService = project.getService(ZoweConfigService::class.java)
val lock = ReentrantReadWriteLock()
}
}

Expand Down
Loading

0 comments on commit 4e51e18

Please sign in to comment.