From cb0100c6e773cece5a81dffb298a024d9a028df6 Mon Sep 17 00:00:00 2001 From: Kunal Aswani Date: Wed, 7 Feb 2024 12:08:12 -0500 Subject: [PATCH] HPCC-31202 File permission dialog fails to open When checking file permissions for file scopes, dialog was not opening. Dialog now opening for users to check permissions. Signed-off-by: Kunal Aswani --- esp/src/src-react/components/Permissions.tsx | 5 +- .../components/forms/CheckPermissions.tsx | 145 ++++++++++++++++++ esp/src/src/nls/hpcc.ts | 2 +- 3 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 esp/src/src-react/components/forms/CheckPermissions.tsx diff --git a/esp/src/src-react/components/Permissions.tsx b/esp/src/src-react/components/Permissions.tsx index 98c2f9039e6..33345e78233 100644 --- a/esp/src/src-react/components/Permissions.tsx +++ b/esp/src/src-react/components/Permissions.tsx @@ -9,6 +9,7 @@ import { useConfirm } from "../hooks/confirm"; import { useBuildInfo } from "../hooks/platform"; import { DojoGrid, selector, tree } from "./DojoGrid"; import { AddPermissionForm } from "./forms/AddPermission"; +import { CheckPermissionsForm } from "./forms/CheckPermissions"; import { HolyGrail } from "../layouts/HolyGrail"; import { pushUrl } from "../util/history"; @@ -35,6 +36,7 @@ export const Permissions: React.FunctionComponent = ({ const [selection, setSelection] = React.useState([]); const [showAddPermission, setShowAddPermission] = React.useState(false); + const [showCheckFilePermissions, setShowCheckFilePermissions] = React.useState(false); const [scopeScansEnabled, setScopeScansEnabled] = React.useState(false); const [modulesDn, setModulesDn] = React.useState(""); const [uiState, setUIState] = React.useState({ ...defaultUIState }); @@ -203,7 +205,7 @@ export const Permissions: React.FunctionComponent = ({ { key: "fileScopeDefaults", text: nlsHPCC.FileScopeDefaultPermissions, onClick: (evt, item) => pushUrl(`/${opsCategory}/security/permissions/_/File%20Scopes`), disabled: !uiState.fileScope }, { key: "workunitScopeDefaults", text: nlsHPCC.WorkUnitScopeDefaultPermissions, onClick: (evt, item) => pushUrl(`/${opsCategory}/security/permissions/_/Workunit%20Scopes`), disabled: !uiState.workunitScope }, { key: "physicalFiles", text: nlsHPCC.PhysicalFiles, onClick: (evt, item) => pushUrl(`/${opsCategory}/security/permissions/file/File%20Scopes`), disabled: !uiState.fileScope }, - { key: "checkFilePermissions", text: nlsHPCC.CheckFilePermissions, disabled: !uiState.fileScope }, + { key: "checkFilePermissions", text: nlsHPCC.CheckFilePermissions, onClick: () => setShowCheckFilePermissions(true), disabled: !uiState.fileScope }, { key: "codeGenerator", text: nlsHPCC.CodeGenerator, onClick: (evt, item) => pushUrl(`/${opsCategory}/security/permissions/_/${modulesDn}`), disabled: !uiState.repositoryModule }, ], }, @@ -223,6 +225,7 @@ export const Permissions: React.FunctionComponent = ({ + refreshTable()} /> ; diff --git a/esp/src/src-react/components/forms/CheckPermissions.tsx b/esp/src/src-react/components/forms/CheckPermissions.tsx new file mode 100644 index 00000000000..97da1bc6829 --- /dev/null +++ b/esp/src/src-react/components/forms/CheckPermissions.tsx @@ -0,0 +1,145 @@ +import * as React from "react"; +import { DefaultButton, Dropdown, IDropdownOption, MessageBar, MessageBarType, PrimaryButton, TextField } from "@fluentui/react"; +import { scopedLogger } from "@hpcc-js/util"; +import { useForm, Controller } from "react-hook-form"; +import nlsHPCC from "src/nlsHPCC"; +import { MessageBox } from "../../layouts/MessageBox"; +import { FilePermission } from "src/ws_access"; + +const logger = scopedLogger("src-react/components/forms/CheckPermissions.tsx"); + +interface CheckPermissionsFormValues { + FileName: string; + SelectedValue: string; +} + +const defaultValues: CheckPermissionsFormValues = { + FileName: "", + SelectedValue: "", +}; + +interface CheckPermissionsFormProps { + refreshGrid?: () => void; + showForm: boolean; + setShowForm: (_: boolean) => void; +} + +export const CheckPermissionsForm: React.FunctionComponent = ({ + refreshGrid, + showForm, + setShowForm +}) => { + + const { handleSubmit, control, reset, setValue, watch } = useForm({ defaultValues }); + + const [showError, setShowError] = React.useState(false); + const [errorMessage, setErrorMessage] = React.useState(""); + const [userOptions, setUserOptions] = React.useState([]); + const [groupOptions, setGroupOptions] = React.useState([]); + const [filePermissionResponse, setFilePermissionResponse] = React.useState(""); + + React.useEffect(() => { + const fetchData = async () => { + try { + const { FilePermissionResponse } = await FilePermission({}); + const { Users, Groups } = FilePermissionResponse; + const sortedUsers = Users?.User?.sort((a, b) => a.username.localeCompare(b.username)); + const sortedGroups = Groups?.Group?.sort((a, b) => a.name.localeCompare(b.name)); + + setUserOptions(sortedUsers?.map((user: { username: any; }) => { + return { key: user.username, text: user.username }; + }) ?? []); + + setGroupOptions(sortedGroups?.map(group => { + return { key: group.name, text: group.name }; + }) ?? []); + } catch (error) { + logger.error(error); + } + }; + + fetchData(); + }, []); + + const closeForm = React.useCallback(() => { + reset(defaultValues); + setShowForm(false); + setFilePermissionResponse(""); + }, [reset, setShowForm]); + + const onSubmit = async (data: CheckPermissionsFormValues) => { + try { + const { FileName, SelectedValue } = data; + logger.info(`Checking permissions for file ${FileName} for selected value: ${SelectedValue}`); + const response = await FilePermission({ + request: { + FileName, + UserName: SelectedValue, + GroupName: SelectedValue + } + }); + setFilePermissionResponse(response.FilePermissionResponse.UserPermission); + } catch (error) { + logger.error(error); + setErrorMessage("Error occurred while fetching file permissions."); + setShowError(true); + } + }; + + return ( + + + + }> + } + rules={{ + required: nlsHPCC.ValidationErrorRequired + }} + /> + { + setValue("SelectedValue", option?.key.toString() || ""); + }} + /> + { + setValue("SelectedValue", option?.key.toString() || ""); + }} + /> + {filePermissionResponse && ( + + )} + {showError && +
+ setShowError(false)} dismissButtonAriaLabel="Close"> + {errorMessage} + +
+ } +
+ ); +}; \ No newline at end of file diff --git a/esp/src/src/nls/hpcc.ts b/esp/src/src/nls/hpcc.ts index 13bcce618df..85c162096f8 100644 --- a/esp/src/src/nls/hpcc.ts +++ b/esp/src/src/nls/hpcc.ts @@ -338,7 +338,7 @@ export = { FileScopeDefaultPermissions: "File Scope Default Permissions", FileSize: "File Size", FilesNoPackage: "Files without matching package definitions", - FilePermission: "File Permission", + FilePermission: "File Permission", FilesWarning: "The number of files returned is too large. Only the first 100,000 files sorted by date/time modified were returned. If you wish to limit results, set a filter.", FilesWithUnknownSize: "Files With Unknown Size", FileType: "File Type",