Skip to content

Commit

Permalink
GH-290 Create file in directory without read permission
Browse files Browse the repository at this point in the history
Signed-off-by: Uladzislau <[email protected]>
  • Loading branch information
Uladzislau Lailo authored and KUGDev committed Feb 1, 2025
1 parent 3359db6 commit ff81af0
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import org.zowe.explorer.utils.castOrNull
import org.zowe.explorer.utils.service // TODO: remove in v1.*.*-223 and greater
import org.zowe.explorer.vfs.MFVirtualFile
import org.zowe.kotlinsdk.ChangeMode
import org.zowe.kotlinsdk.FileModeValue
import org.zowe.kotlinsdk.FileType

/**
Expand All @@ -58,67 +59,80 @@ abstract class CreateUssEntityAction : AnAction() {
val view = e.getExplorerView<FileExplorerView>() ?: return
val selected = view.mySelectedNodesData[0]
val selectedNode = selected.node
val node = if (selectedNode is UssFileNode) {
selectedNode.parent?.takeIf { it is UssDirNode }

val node: UssDirNode = if (selectedNode is UssFileNode) {
selectedNode.parent?.takeIf { it is UssDirNode } as UssDirNode
} else {
selectedNode.takeIf { it is UssDirNode }
selectedNode.takeIf { it is UssDirNode } as UssDirNode
} ?: return

val connectionConfig = node.unit.connectionConfig ?: return
val dataOpsManager = DataOpsManager.instance

val file = node.virtualFile
// TODO: Why is it highlighted ???
if (node is ExplorerUnitTreeNodeBase<*, *, *>) {
val connectionConfig = node.unit.connectionConfig.castOrNull<ConnectionConfig>() ?: return
val dataOpsManager = node.unit.explorer.componentManager.service<DataOpsManager>()
val filePath = if (file != null) {
dataOpsManager.getAttributesService<RemoteUssAttributes, MFVirtualFile>()
.getAttributes(file)?.path
val attributes = file?.let {
dataOpsManager.getAttributesService<RemoteUssAttributes, MFVirtualFile>()
.getAttributes(it)
}

val filePath = attributes?.path ?: node.value.path

showUntilDone(
initialState = fileType.apply { path = filePath },
{ initState -> CreateFileDialog(e.project, state = initState, filePath = filePath) }
) {
var res = false
val allocationParams = it.toAllocationParams()
val fileType = if (allocationParams.parameters.type == FileType.FILE) {
"File"
} else {
(node as UssDirNode).value.path
"Directory"
}
if (filePath != null) {
showUntilDone(
initialState = fileType.apply { path = filePath },
{ initState -> CreateFileDialog(e.project, state = initState, filePath = filePath) }
) {
var res = false
val allocationParams = it.toAllocationParams()
val fileType = if (allocationParams.parameters.type == FileType.FILE) {
"File"
} else {
"Directory"
runModalTask(
title = "Creating $fileType ${allocationParams.fileName}",
project = e.project,
cancellable = true
) { indicator ->
runCatching {
dataOpsManager.performOperation(
operation = UssAllocationOperation(
request = allocationParams,
connectionConfig = connectionConfig
),
progressIndicator = indicator
)

val fileFetchProvider = dataOpsManager
.getFileFetchProvider<UssQuery, RemoteQuery<ConnectionConfig, UssQuery, Unit>, MFVirtualFile>(
UssQuery::class.java, RemoteQuery::class.java, MFVirtualFile::class.java
)

attributes?.fileMode?.let { fm ->
if (checkReadPermissionsBeforeReload(fm.owner)) {
node.query?.let { query -> fileFetchProvider.reload(query) }
}
}
runModalTask(
title = "Creating $fileType ${allocationParams.fileName}",
project = e.project,
cancellable = true
) { indicator ->
val ussDirNode = node.castOrNull<UssDirNode>()
runCatching {
dataOpsManager.performOperation(
operation = UssAllocationOperation(
request = allocationParams,
connectionConfig = connectionConfig
),
progressIndicator = indicator
)

val fileFetchProvider = dataOpsManager
.getFileFetchProvider<UssQuery, RemoteQuery<ConnectionConfig, UssQuery, Unit>, MFVirtualFile>(
UssQuery::class.java, RemoteQuery::class.java, MFVirtualFile::class.java
)
ussDirNode?.query?.let { query -> fileFetchProvider.reload(query) }

changeFileModeIfNeeded(file, allocationParams, connectionConfig, indicator)

}.onSuccess {
ussDirNode?.cleanCache(false)
res = true
}.onFailure { t ->
view.explorer.reportThrowable(t, e.project)

changeFileModeIfNeeded(file, allocationParams, connectionConfig, indicator)

service<AnalyticsService>().trackAnalyticsEvent(
FileEvent(
allocationParams.parameters.type,
FileAction.CREATE
)
)
}.onSuccess {
attributes?.fileMode?.let { fm ->
if (checkReadPermissionsBeforeReload(fm.owner)) {
node.cleanCache(false)
}
}
res
res = true
}.onFailure { t ->
view.explorer.reportThrowable(t, e.project)
}
}
res
}
}

Expand Down Expand Up @@ -175,4 +189,11 @@ abstract class CreateUssEntityAction : AnAction() {
e.presentation.isEnabled = false
}
}

private fun checkReadPermissionsBeforeReload(permission: Int): Boolean {
return permission == FileModeValue.READ.mode ||
permission == FileModeValue.READ_EXECUTE.mode ||
permission == FileModeValue.READ_WRITE.mode ||
permission == FileModeValue.READ_WRITE_EXECUTE.mode
}
}
32 changes: 21 additions & 11 deletions src/main/kotlin/org/zowe/explorer/explorer/ui/ExplorerTreeView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ val EXPLORER_VIEW = DataKey.create<ExplorerTreeView<*, *, *>>("explorerView")

private val log = log<ExplorerTreeView<*, *, *>>()

fun <ExplorerView: ExplorerTreeView<*, *, *>> AnActionEvent.getExplorerView(clazz: Class<out ExplorerView>): ExplorerView? {
fun <ExplorerView : ExplorerTreeView<*, *, *>> AnActionEvent.getExplorerView(clazz: Class<out ExplorerView>): ExplorerView? {
return getData(EXPLORER_VIEW).castOrNull(clazz)
}

inline fun <reified ExplorerView: ExplorerTreeView<*, *, *>> AnActionEvent.getExplorerView(): ExplorerView? {
inline fun <reified ExplorerView : ExplorerTreeView<*, *, *>> AnActionEvent.getExplorerView(): ExplorerView? {
return getExplorerView(ExplorerView::class.java)
}

Expand All @@ -74,7 +74,7 @@ inline fun <reified ExplorerView: ExplorerTreeView<*, *, *>> AnActionEvent.getEx
* @param rootNodeProvider the root node provider for the root node of the explorer
* @param cutProviderUpdater the cut provider updater to store the information about the cut elements
*/
abstract class ExplorerTreeView<Connection: ConnectionConfigBase, U : WorkingSet<Connection, *>, UnitConfig : EntityWithUuid>
abstract class ExplorerTreeView<Connection : ConnectionConfigBase, U : WorkingSet<Connection, *>, UnitConfig : EntityWithUuid>
(
val explorer: Explorer<Connection, U>,
private val project: Project,
Expand Down Expand Up @@ -201,28 +201,37 @@ abstract class ExplorerTreeView<Connection: ConnectionConfigBase, U : WorkingSet
handler = object : ExplorerListener {


private fun <Connection: ConnectionConfigBase> onAddDelete(explorer: Explorer<Connection, *>) {
private fun <Connection : ConnectionConfigBase> onAddDelete(explorer: Explorer<Connection, *>) {
if (explorer == this@ExplorerTreeView.explorer) {
myFsTreeStructure.findByValue(explorer).forEach {
myStructure.invalidate(it, true)
}
}
}

override fun <Connection: ConnectionConfigBase> onAdded(explorer: Explorer<Connection, *>,unit: ExplorerUnit<Connection>) {
override fun <Connection : ConnectionConfigBase> onAdded(
explorer: Explorer<Connection, *>,
unit: ExplorerUnit<Connection>
) {
onAddDelete(explorer)
}


override fun <Connection: ConnectionConfigBase> onChanged(explorer: Explorer<Connection, *>, unit: ExplorerUnit<Connection>) {
override fun <Connection : ConnectionConfigBase> onChanged(
explorer: Explorer<Connection, *>,
unit: ExplorerUnit<Connection>
) {
if (explorer == this@ExplorerTreeView.explorer) {
myFsTreeStructure.findByValue(unit).forEach {
myStructure.invalidate(it, true)
}
}
}

override fun <Connection: ConnectionConfigBase> onDeleted(explorer: Explorer<Connection, *>, unit: ExplorerUnit<Connection>) {
override fun <Connection : ConnectionConfigBase> onDeleted(
explorer: Explorer<Connection, *>,
unit: ExplorerUnit<Connection>
) {
onAddDelete(explorer)
}
},
Expand Down Expand Up @@ -292,9 +301,9 @@ abstract class ExplorerTreeView<Connection: ConnectionConfigBase, U : WorkingSet
}

it is VFileDeleteEvent &&
this@ExplorerTreeView
.ignoreVFileDeleteEvents
.compareAndSet(true, true) -> {
this@ExplorerTreeView
.ignoreVFileDeleteEvents
.compareAndSet(true, true) -> {
null
}

Expand Down Expand Up @@ -399,7 +408,8 @@ abstract class ExplorerTreeView<Connection: ConnectionConfigBase, U : WorkingSet

tree.selectionModel.selectionMode = TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION
tree.addTreeSelectionListener {
mySelectedNodesData = tree.selectionPaths?.mapNotNull { makeNodeDataFromTreePath<Connection>(explorer, it) } ?: listOf()
mySelectedNodesData =
tree.selectionPaths?.mapNotNull { makeNodeDataFromTreePath<Connection>(explorer, it) } ?: listOf()
}

tree.addTreeWillExpandListener(object : TreeWillExpandListener {
Expand Down

0 comments on commit ff81af0

Please sign in to comment.