Skip to content

Commit

Permalink
Merge branch 'public-release/v2.0.0-231' into zowe-release/v2.0.0-231
Browse files Browse the repository at this point in the history
Signed-off-by: Uladzislau <[email protected]>
  • Loading branch information
KUGDev committed Apr 17, 2024
2 parents ac313b0 + 698653c commit 08f24b2
Show file tree
Hide file tree
Showing 130 changed files with 8,924 additions and 3,689 deletions.
34 changes: 23 additions & 11 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ version = properties("pluginVersion").get()
val remoteRobotVersion = "0.11.22"
val okHttp3Version = "4.12.0"
val kotestVersion = "5.8.1"
val retrofit2Vertion = "2.11.0"
val junitVersion = "5.10.2"
val mockkVersion = "1.13.10"
val ibmMqVersion = "9.3.5.0"
val jGraphTVersion = "1.5.2"
val zoweKotlinSdkVersion = "0.4.0"
val javaKeytarVersion = "1.0.0"

repositories {
mavenCentral()
Expand All @@ -66,28 +73,33 @@ java {
}

dependencies {
implementation(group = "com.squareup.retrofit2", name = "retrofit", version = "2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.retrofit2:converter-scalars:2.9.0")
implementation(group = "com.squareup.retrofit2", name = "retrofit", version = retrofit2Vertion)
implementation("com.squareup.retrofit2:converter-gson:$retrofit2Vertion")
implementation("com.squareup.retrofit2:converter-scalars:$retrofit2Vertion")
implementation("com.squareup.okhttp3:okhttp:$okHttp3Version")
implementation("org.jgrapht:jgrapht-core:1.5.2")
implementation("com.starxg:java-keytar:1.0.0")
implementation("org.zowe.sdk:zowe-kotlin-sdk:0.4.0")
implementation("com.ibm.mq:com.ibm.mq.allclient:9.3.4.1")
testImplementation("io.mockk:mockk:1.13.9")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.10.1")
implementation("org.jgrapht:jgrapht-core:$jGraphTVersion")
implementation("com.starxg:java-keytar:$javaKeytarVersion")
implementation("org.zowe.sdk:zowe-kotlin-sdk:$zoweKotlinSdkVersion")
implementation("com.ibm.mq:com.ibm.mq.allclient:$ibmMqVersion")
implementation("org.junit.jupiter:junit-jupiter-params:$junitVersion")
testImplementation("org.junit.jupiter:junit-jupiter-api:$junitVersion")
testImplementation("io.mockk:mockk:$mockkVersion")
testImplementation("io.kotest:kotest-assertions-core:$kotestVersion")
testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion")
testImplementation("com.intellij.remoterobot:remote-robot:$remoteRobotVersion")
testImplementation("com.intellij.remoterobot:remote-fixtures:$remoteRobotVersion")
testImplementation("com.squareup.okhttp3:mockwebserver:$okHttp3Version")
testImplementation("com.squareup.okhttp3:okhttp-tls:$okHttp3Version")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.10.1")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.10.1")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:$junitVersion")
}

intellij {
version.set(properties("platformVersion").get())
// !Development only!
// downloadSources.set(true)
// In Settings | Advanced Settings enable option Download sources in section Build Tools. Gradle.
// Then invoke Reload All Gradle Projects action from the Gradle tool window.
}

// Configure Gradle Changelog Plugin - read more: https://github.com/JetBrains/gradle-changelog-plugin
Expand Down
7 changes: 2 additions & 5 deletions src/main/kotlin/org/zowe/explorer/common/ui/Table.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ import com.intellij.openapi.actionSystem.ActionToolbarPosition
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.ui.AnActionButton
import com.intellij.ui.ToolbarDecorator
import com.intellij.ui.dsl.builder.Row
import com.intellij.ui.dsl.gridLayout.HorizontalAlign
import com.intellij.ui.dsl.gridLayout.VerticalAlign
import com.intellij.ui.dsl.builder.*
import com.intellij.ui.table.TableView
import javax.swing.JPanel
import javax.swing.JTable
Expand Down Expand Up @@ -152,8 +150,7 @@ fun <Item> Row.tableWithToolbar(
.apply { toolbarTableBuilder() }
.createPanel()
return cell(tableComponent)
.horizontalAlign(HorizontalAlign.FILL)
.verticalAlign(VerticalAlign.FILL)
.align(AlignX.FILL.plus(AlignY.FILL))
}

val TableModelEvent.rows: IntRange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ class ValidatingTableView<Item>(
model: ValidatingListTableModel<Item>,
val disposable: Disposable
) : TableView<Item>(model) {
init {
for (column in columnModel.columns) {
column.minWidth = 150
}
}

@Suppress("UNCHECKED_CAST")
override fun getListTableModel(): ValidatingListTableModel<Item> {
Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/org/zowe/explorer/config/connect/Credentials.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Credentials {
if (other == null || javaClass != other.javaClass) return false
val that = other as Credentials
if (configUuid != that.configUuid) return false
return if (username != that.username) false else password == that.password
return username == that.username && password == that.password
}

override fun hashCode(): Int {
Expand All @@ -51,9 +51,9 @@ class Credentials {

override fun toString(): String {
return "Credentials{" +
"connectionConfigUuid='" + configUuid + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}'
"connectionConfigUuid='" + configUuid + '\'' +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ package org.zowe.explorer.config.connect.ui
import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project
import com.intellij.ui.dsl.builder.*
import com.intellij.ui.dsl.gridLayout.HorizontalAlign
import org.zowe.explorer.common.ui.StatefulDialog
import org.zowe.explorer.utils.validateForBlank
import org.zowe.explorer.utils.validateForPassword
Expand Down Expand Up @@ -46,7 +45,7 @@ class ChangePasswordDialog(
it.text = it.text.trim()
validateForBlank(it)
}
.horizontalAlign(HorizontalAlign.FILL)
.align(AlignX.FILL)
}
row {
label("Old password: ")
Expand All @@ -58,7 +57,7 @@ class ChangePasswordDialog(
addShowHidePasswordIcon(this)
}
.validationOnApply { validateForBlank(it) }
.horizontalAlign(HorizontalAlign.FILL)
.align(AlignX.FILL)
}
row {
label("New password: ")
Expand All @@ -75,7 +74,7 @@ class ChangePasswordDialog(
})
}
.validationOnApply { validateForBlank(it) }
.horizontalAlign(HorizontalAlign.FILL)
.align(AlignX.FILL)
}
row {
label("Confirm password: ")
Expand All @@ -87,7 +86,7 @@ class ChangePasswordDialog(
addShowHidePasswordIcon(this)
}
.validationOnApply { validateForBlank(it) ?: validateForPassword(state.newPassword, it) }
.horizontalAlign(HorizontalAlign.FILL)
.align(AlignX.FILL)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@ package org.zowe.explorer.config.connect.ui.zosmf

import com.intellij.icons.AllIcons
import com.intellij.openapi.components.service
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.runBackgroundableTask
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.MessageDialogBuilder
import com.intellij.openapi.ui.MessageType
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.popup.Balloon
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.ui.awt.RelativePoint
import com.intellij.ui.components.JBCheckBox
import com.intellij.ui.components.JBTextField
import com.intellij.ui.dsl.builder.*
import com.intellij.ui.dsl.gridLayout.HorizontalAlign
import org.zowe.explorer.common.message
import org.zowe.explorer.common.ui.DialogMode
import org.zowe.explorer.common.ui.StatefulDialog
import org.zowe.explorer.common.ui.showUntilDone
Expand All @@ -39,10 +43,7 @@ import org.zowe.kotlinsdk.annotations.ZVersion
import java.awt.Component
import java.awt.Point
import java.util.*
import javax.swing.JCheckBox
import javax.swing.JComponent
import javax.swing.JPasswordField
import javax.swing.JTextField
import javax.swing.*

/** Dialog to add a new connection */
class ConnectionDialog(
Expand All @@ -62,6 +63,31 @@ class ConnectionDialog(
.toDialogState(crudable) else ConnectionDialogState()
companion object {

/**
* Check if only the connection name has changed in the connection dialog
*/
private fun isOnlyConnectionNameChanged(initialState: ConnectionDialogState, state: ConnectionDialogState): Boolean {
return initialState.connectionName != state.connectionName &&
initialState.connectionUrl == state.connectionUrl &&
initialState.username == state.username &&
initialState.password == state.password &&
initialState.isAllowSsl == state.isAllowSsl
}

/**
* Companion function which takes the instance of ConnectionDialog and checks its current state after OK button is pressed.
* @param dialog
* @return returns true if there are violations found, if no violations were found then returns false as a result of validation
*/
private fun validateSecureConnectionUsage(dialog : ConnectionDialog) : Boolean {
val urlToCheck = dialog.urlTextField.text.trim().startsWith("http://", true)
val sslEnabledCheck = dialog.sslCheckbox.isSelected
if (urlToCheck || sslEnabledCheck) {
return dialog.showSelfSignedUsageWarningDialog(dialog.urlTextField, dialog.sslCheckbox)
}
return false
}

/** Show Test connection dialog and test the connection regarding the dialog state.
* First the method checks whether connection succeeds for specified user/password.
* If connection succeeds then the method automatically fill in z/OS version for this connection.
Expand All @@ -74,12 +100,25 @@ class ConnectionDialog(
project: Project? = null,
initialState: ConnectionDialogState
): ConnectionDialogState? {
var connectionDialog = ConnectionDialog(crudable, initialState, project)
val initState = initialState.clone()
return showUntilDone(
initialState = initialState,
factory = { ConnectionDialog(crudable, initialState, project) },
factory = { connectionDialog },
test = { state ->

if (validateSecureConnectionUsage(connectionDialog)) {
state.connectionUrl = connectionDialog.urlTextField.text
state.isAllowSsl = connectionDialog.sslCheckbox.isSelected
connectionDialog = ConnectionDialog(crudable, state, project)
return@showUntilDone false
}

val newTestedConnConfig : ConnectionConfig
if (initialState.mode == DialogMode.UPDATE) {
if (isOnlyConnectionNameChanged(initState, state)) {
return@showUntilDone true
}
val newState = state.clone()
newState.initEmptyUuids(crudable)
newTestedConnConfig = ConnectionConfig(newState.connectionUuid, newState.connectionName, newState.connectionUrl, newState.isAllowSsl, newState.zVersion)
Expand All @@ -101,6 +140,7 @@ class ConnectionDialog(
runCatching {
service<DataOpsManager>().performOperation(InfoOperation(newTestedConnConfig), it)
}.onSuccess {
state.owner = whoAmI(newTestedConnConfig) ?: ""
val systemInfo = service<DataOpsManager>().performOperation(ZOSInfoOperation(newTestedConnConfig))
state.zVersion = when (systemInfo.zosVersion) {
"04.25.00" -> ZVersion.ZOS_2_2
Expand All @@ -120,12 +160,16 @@ class ConnectionDialog(
if (throwable != null) {
state.mode = DialogMode.UPDATE
val confirmMessage = "Do you want to add it anyway?"
val tMessage = throwable.message?.let {
if (it.contains("Exception")) {
it.substring(it.lastIndexOf(":") + 2)
.replaceFirstChar { c -> if (c.isLowerCase()) c.titlecase(Locale.getDefault()) else c.toString() }
} else {
it
val tMessage = if (throwable is ProcessCanceledException) {
message("explorer.cancel.by.user.error")
} else {
throwable.message?.let {
if (it.contains("Exception")) {
it.substring(it.lastIndexOf(":") + 2)
.replaceFirstChar { c -> if (c.isLowerCase()) c.titlecase(Locale.getDefault()) else c.toString() }
} else {
it
}
}
}
val message = if (tMessage != null) {
Expand All @@ -145,11 +189,9 @@ class ConnectionDialog(
ask(project)
}
}
connectionDialog = ConnectionDialog(crudable, state, project)
addAnyway
} else {
runTask(title = "Retrieving user information", project = project) {
state.owner = whoAmI(newTestedConnConfig) ?: ""
}
true
}
}
Expand Down Expand Up @@ -188,12 +230,12 @@ class ConnectionDialog(
)
}
.focused()
.horizontalAlign(HorizontalAlign.FILL)
.align(AlignX.FILL)
} else {
textField()
.bindText(state::connectionName)
.applyToComponent { isEditable = false }
.horizontalAlign(HorizontalAlign.FILL)
.align(AlignX.FILL)
}
}
row {
Expand All @@ -206,7 +248,7 @@ class ConnectionDialog(
validateForBlank(it) ?: validateZosmfUrl(it)
}
.also { urlTextField = it.component }
.horizontalAlign(HorizontalAlign.FILL)
.align(AlignX.FILL)
}
row {
label("Username")
Expand All @@ -224,21 +266,30 @@ class ConnectionDialog(
.onApply {
state.username = state.username.trim().uppercase()
}
.horizontalAlign(HorizontalAlign.FILL)
.align(AlignX.FILL)
}
row {
label("Password: ")
.widthGroup(sameWidthLabelsGroup)
passField = cell(JPasswordField())
.bindText(state::password)
.validationOnApply { validateForBlank(it) }
.horizontalAlign(HorizontalAlign.FILL)
.align(AlignX.FILL)
}
indent {
row {
checkBox("Accept self-signed SSL certificates")
.bindSelected(state::isAllowSsl)
.also { sslCheckbox = it.component }
.also {
it.component.apply {
addActionListener {
if (this.isSelected) {
showSelfSignedUsageWarningDialog(this)
}
}
sslCheckbox = this
}
}
}
}
if (state.mode == DialogMode.UPDATE) {
Expand Down Expand Up @@ -376,4 +427,40 @@ class ConnectionDialog(
}
}

/**
* Function shows the warning dialog if any violations found and resolves them in case "Back to safety" was clicked
* @param components - dialog components which have to be resolved to valid values
* @return result of the pressed button
*/
private fun showSelfSignedUsageWarningDialog(vararg components : Component) : Boolean {
// default return backToSafety
val backToSafety = true
val choice = Messages.showDialog(
project,
"Creating an unsecure connection (HTTP instead of HTTP(s) and/or using self-signed certificates) is not recommended.\n" +
"You do this at your own peril and risk, and we do not bear any responsibility for the possible consequences of using this type of connection.\n" +
"Please contact your system administrator to configure your system to be able to create a secure connection.\n\n" +
"Do you want to proceed anyway?",
"Attempt to create an unsecured connection",
arrayOf(
"Back to safety",
"Proceed"
),
0,
AllIcons.General.WarningDialog,
null
)
return when (choice) {
0 -> {
components.forEach {
if (it is JBCheckBox) it.isSelected = false
if (it is JBTextField) it.text = it.text.replace("http", "https", true)
}
backToSafety
}
1 -> !backToSafety
else -> backToSafety
}
}

}
Loading

0 comments on commit 08f24b2

Please sign in to comment.