Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/candidate-9.4.x' into candidate-…
Browse files Browse the repository at this point in the history
…9.6.x

Signed-off-by: Gordon Smith <[email protected]>

# Conflicts:
#	helm/hpcc/Chart.yaml
#	helm/hpcc/templates/_helpers.tpl
#	helm/hpcc/templates/dafilesrv.yaml
#	helm/hpcc/templates/dali.yaml
#	helm/hpcc/templates/dfuserver.yaml
#	helm/hpcc/templates/eclagent.yaml
#	helm/hpcc/templates/eclccserver.yaml
#	helm/hpcc/templates/eclscheduler.yaml
#	helm/hpcc/templates/esp.yaml
#	helm/hpcc/templates/localroxie.yaml
#	helm/hpcc/templates/roxie.yaml
#	helm/hpcc/templates/sasha.yaml
#	helm/hpcc/templates/thor.yaml
#	version.cmake
  • Loading branch information
GordonSmith committed Jul 5, 2024
2 parents 328b5de + d28c896 commit 8cb73d9
Show file tree
Hide file tree
Showing 17 changed files with 420 additions and 35 deletions.
8 changes: 5 additions & 3 deletions esp/services/ws_workunits/ws_workunitsHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,15 @@ struct WUComponentLogOptions
}
else if (!isEmptyString(end))
{
if (isEmptyString(end))
if (isEmptyString(start))
throw makeStringException(ECLWATCH_INVALID_INPUT, "ZapLogFilter: Empty 'Absolute TimeRange Start' detected!");
}
else
{
if (relativeTimeBufferSecs > 0 )
wuLogSearchTimeBuffSecs = relativeTimeBufferSecs;
else
throw makeStringException(ECLWATCH_INVALID_INPUT, "ZapLogFilter: Invalid 'TimeRange' detected!");
}
}

Expand All @@ -208,9 +210,9 @@ struct WUComponentLogOptions
logDataFormat = logAccessFormatFromName(requestedLogDataFormat.str());

StringBuffer start; // Absolute query time range start in YYYY-DD-MMTHH:MM:SS
zapHttpRequest->getParameter("LogFilter_AbsoluteTimeRange_Start", start);
zapHttpRequest->getParameter("LogFilter_AbsoluteTimeRange_StartDate", start);
StringBuffer end; // Absolute query time range end in YYYY-DD-MMTHH:MM:SS
zapHttpRequest->getParameter("LogFilter_AbsoluteTimeRange_End", end);
zapHttpRequest->getParameter("LogFilter_AbsoluteTimeRange_EndDate", end);
// Query time range based on WU Time +- Buffer in seconds
unsigned bufferSecs = (unsigned)zapHttpRequest->getParameterInt("LogFilter_RelativeTimeRangeBuffer", 0);

Expand Down
1 change: 1 addition & 0 deletions esp/src/eclwatch/ShowIndividualPermissionsWidget.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ define([
evt.preventDefault();
context.calcPermissionState(evt.cell.column.field, evt.value, evt.cell.row.data);
evt.grid.store.put(evt.cell.row.data);
const t = window.setTimeout(() => { context.grid.refresh(); window.clearTimeout(t); }, 100);
});
return retVal;
},
Expand Down
31 changes: 22 additions & 9 deletions esp/src/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion esp/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"@hpcc-js/chart": "2.83.3",
"@hpcc-js/codemirror": "2.62.0",
"@hpcc-js/common": "2.71.17",
"@hpcc-js/comms": "2.92.2",
"@hpcc-js/comms": "2.92.3",
"@hpcc-js/dataflow": "8.1.6",
"@hpcc-js/eclwatch": "2.74.5",
"@hpcc-js/graph": "2.85.15",
Expand Down
4 changes: 2 additions & 2 deletions esp/src/src-react/components/FileDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ export const FileDetails: React.FunctionComponent<FileDetailsProps> = ({
}) => {
const [file] = useFile(cluster, logicalFile);
React.useEffect(() => {
if (file?.NodeGroup && cluster === undefined) {
if (file?.NodeGroup && cluster === undefined && !file?.isSuperfile) {
replaceUrl(`/files/${file.NodeGroup}/${logicalFile}`);
}
}, [cluster, file?.NodeGroup, logicalFile]);
}, [cluster, file?.NodeGroup, file?.isSuperfile, logicalFile]);
const [defFile] = useDefFile(cluster, logicalFile, WsDfu.DFUDefFileFormat.def);
const [xmlFile] = useDefFile(cluster, logicalFile, WsDfu.DFUDefFileFormat.xml);

Expand Down
2 changes: 1 addition & 1 deletion esp/src/src-react/components/LogicalFileSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export const LogicalFileSummary: React.FunctionComponent<LogicalFileSummaryProps
<TableGroup fields={{
"Wuid": { label: nlsHPCC.Workunit, type: "link", value: file?.Wuid, href: `#/${isDFUWorkunit ? "dfu" : ""}workunits/${file?.Wuid}`, readonly: true, },
"Owner": { label: nlsHPCC.Owner, type: "string", value: file?.Owner, readonly: true },
"SuperOwner": { label: nlsHPCC.SuperFile, type: "links", links: file?.Superfiles?.DFULogicalFile?.map(row => ({ label: "", type: "link", value: row.Name, href: `#/files/${row.Name}` })) },
"SuperOwner": { label: nlsHPCC.SuperFile, type: "links", links: file?.Superfiles?.DFULogicalFile?.map(row => ({ label: "", type: "link", value: row.Name, href: `#/files/${row.NodeGroup !== null ? row.NodeGroup : undefined}/${row.Name}` })) },
"NodeGroup": { label: nlsHPCC.ClusterName, type: "string", value: file?.NodeGroup, readonly: true },
"Description": { label: nlsHPCC.Description, type: "string", value: description },
"JobName": { label: nlsHPCC.JobName, type: "string", value: file?.JobName, readonly: true },
Expand Down
1 change: 1 addition & 0 deletions esp/src/src-react/components/Metrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ export const Metrics: React.FunctionComponent<MetricsProps> = ({
const propsTable2 = useConst(() => new Table()
.columns([nlsHPCC.Property, nlsHPCC.Value])
.columnWidth("auto")
.sortable(true)
);

const updatePropsTable2 = React.useCallback((selection: IScope[]) => {
Expand Down
1 change: 1 addition & 0 deletions esp/src/src-react/components/MetricsPropertiesTables.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const MetricsPropertiesTables: React.FunctionComponent<MetricsPropertiesT
const propsTable = useConst(() => new Table()
.columns([nlsHPCC.Property, nlsHPCC.Value, "Avg", "Min", "Max", "Delta", "StdDev", "SkewMin", "SkewMax", "NodeMin", "NodeMax"])
.columnWidth("auto")
.sortable(true)
);

React.useEffect(() => {
Expand Down
205 changes: 205 additions & 0 deletions esp/src/src-react/components/PermissionsEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import * as React from "react";
import { Checkbox, CommandBar, ContextualMenuItemType, ICommandBarItemProps, Label, Stack } from "@fluentui/react";
import { WsAccess, AccessService } from "@hpcc-js/comms";
import { scopedLogger } from "@hpcc-js/util";
import nlsHPCC from "src/nlsHPCC";
import { useConfirm } from "../hooks/confirm";
import { HolyGrail } from "../layouts/HolyGrail";
import { ShortVerticalDivider } from "./Common";
import { AddGroupResourceForm } from "./forms/AddGroupResource";

const logger = scopedLogger("src-react/components/PermissionsEditor.tsx");

const service = new AccessService({ baseUrl: "" });

// from ShowIndividualPermissionsWidget.js
const calcPermissionState = (field, value, row) => {
switch (field) {
case "allow_access":
row.allow_full = value && row.allow_read && row.allow_write;
if (value)
calcPermissionState("deny_access", false, row);
break;
case "allow_read":
row.allow_full = row.allow_access && value && row.allow_write;
if (value)
calcPermissionState("deny_read", false, row);
break;
case "allow_write":
row.allow_full = row.allow_access && row.allow_read && value;
if (value)
calcPermissionState("deny_write", false, row);
break;
case "allow_full":
row.allow_access = value;
row.allow_read = value;
row.allow_write = value;
if (value)
calcPermissionState("deny_full", false, row);
break;
case "deny_access":
row.deny_full = value && row.deny_read && row.deny_write;
if (value)
calcPermissionState("allow_access", false, row);
break;
case "deny_read":
row.deny_full = row.deny_access && value && row.deny_write;
if (value)
calcPermissionState("allow_read", false, row);
break;
case "deny_write":
row.deny_full = row.deny_access && row.deny_read && value;
if (value)
calcPermissionState("allow_write", false, row);
break;
case "deny_full":
row.deny_access = value;
row.deny_read = value;
row.deny_write = value;
if (value)
calcPermissionState("allow_full", false, row);
break;
}
row[field] = value;
};

interface PermissionsEditorProps {
BaseDn?: string;
Name?: string;
}

export const PermissionsEditor: React.FunctionComponent<PermissionsEditorProps> = ({
BaseDn,
Name
}) => {

const [data, setData] = React.useState<any[]>([]);
const [selectedIndex, setSelectedIndex] = React.useState(-1);
const [showAddGroup, setShowAddGroup] = React.useState(false);

const refreshData = React.useCallback(() => {
service.ResourcePermissions({ BasednName: BaseDn, name: Name })
.then(({ Permissions }: WsAccess.ResourcePermissionsResponse) => {
setData(Permissions?.Permission.map(Permission => {
return {
account_name: Permission.account_name,
allow_access: Permission.allow_access ?? false,
allow_read: Permission.allow_read ?? false,
allow_write: Permission.allow_write ?? false,
allow_full: Permission.allow_full ?? false,
deny_access: Permission.deny_access ?? false,
deny_read: Permission.deny_read ?? false,
deny_write: Permission.deny_write ?? false,
deny_full: Permission.deny_full ?? false,
};
}));
setSelectedIndex(-1);
})
.catch(err => logger.error(err))
;
}, [BaseDn, Name]);

const [DeleteConfirm, setShowDeleteConfirm] = useConfirm({
title: nlsHPCC.Delete,
message: nlsHPCC.DeleteSelectedGroups + "\n\n" + data[selectedIndex]?.account_name,
onSubmit: React.useCallback(() => {
service.PermissionAction({
action: "delete",
BasednName: BaseDn,
rname: Name,
account_name: data[selectedIndex]?.account_name
})
.then(() => refreshData())
.catch(err => logger.error(err))
;
}, [BaseDn, data, Name, refreshData, selectedIndex])
});

// Command Bar ---
const buttons = React.useMemo((): ICommandBarItemProps[] => [
{
key: "refresh", text: nlsHPCC.Refresh, iconProps: { iconName: "Refresh" },
onClick: () => refreshData()
},
{ key: "divider_1", itemType: ContextualMenuItemType.Divider, onRender: () => <ShortVerticalDivider /> },
{
key: "add", text: nlsHPCC.Add,
onClick: () => setShowAddGroup(true)
},
{ key: "divider_2", itemType: ContextualMenuItemType.Divider, onRender: () => <ShortVerticalDivider /> },
{
key: "delete", text: nlsHPCC.Delete, disabled: selectedIndex < 0,
onClick: () => setShowDeleteConfirm(true)
},
], [refreshData, selectedIndex, setShowDeleteConfirm]);

React.useEffect(() => {
refreshData();
}, [refreshData]);

const onRowSelect = React.useCallback((evt, index) => {
if (evt.target.checked) {
setSelectedIndex(index);
} else {
setSelectedIndex(-1);
}
}, [setSelectedIndex]);

const onPermissionCheckboxClick = React.useCallback((evt, permission, prop) => {
calcPermissionState(prop, evt.target.checked, permission);
service.PermissionAction({
action: "update",
BasednName: BaseDn,
rname: Name,
account_type: 1,
...permission
}).then(({ retcode, retmsg }) => {
if (retcode === 0) {
setData(prevState => {
const newState = Array.from(prevState);
return newState;
});
} else if (retcode === -1) {
logger.error(retmsg);
refreshData();
}
}).catch(err => logger.error(err));
}, [BaseDn, Name, refreshData]);

return <>
<HolyGrail
header={<CommandBar items={buttons} />}
main={
<div style={{ margin: "0 10px" }}>
<Stack horizontal>
<Stack.Item grow={1}><Label>{nlsHPCC.Account}</Label></Stack.Item>
<Stack.Item style={{ width: "min-content", margin: "0 10px" }}><Label>{nlsHPCC.AllowAccess}</Label></Stack.Item>
<Stack.Item style={{ width: "min-content", margin: "0 10px" }}><Label>{nlsHPCC.AllowRead}</Label></Stack.Item>
<Stack.Item style={{ width: "min-content", margin: "0 10px" }}><Label>{nlsHPCC.AllowWrite}</Label></Stack.Item>
<Stack.Item style={{ width: "min-content", margin: "0 16px 0 10px" }}><Label>{nlsHPCC.AllowFull}</Label></Stack.Item>
<Stack.Item style={{ width: "min-content", margin: "0 10px 0 16px" }}><Label>{nlsHPCC.DenyAccess}</Label></Stack.Item>
<Stack.Item style={{ width: "min-content", margin: "0 10px" }}><Label>{nlsHPCC.DenyRead}</Label></Stack.Item>
<Stack.Item style={{ width: "min-content", margin: "0 10px" }}><Label>{nlsHPCC.DenyWrite}</Label></Stack.Item>
<Stack.Item style={{ width: "min-content", margin: "0 10px" }}><Label>{nlsHPCC.DenyFull}</Label></Stack.Item>
</Stack>
{data?.map((permission, index) => (
<Stack horizontal style={{ marginBottom: 5 }}>
<Stack.Item><Checkbox checked={index === selectedIndex ? true : false} onChange={(ev) => onRowSelect(ev, index)} /></Stack.Item>
<Stack.Item grow={1}>{permission.account_name}</Stack.Item>
<Stack.Item style={{ width: 36, margin: "0 10px" }}><Checkbox checked={permission.allow_access} onChange={(ev) => onPermissionCheckboxClick(ev, permission, "allow_access")} /></Stack.Item>
<Stack.Item style={{ width: 36, margin: "0 10px" }}><Checkbox checked={permission.allow_read} onChange={(ev) => onPermissionCheckboxClick(ev, permission, "allow_read")} /></Stack.Item>
<Stack.Item style={{ width: 36, margin: "0 10px" }}><Checkbox checked={permission.allow_write} onChange={(ev) => onPermissionCheckboxClick(ev, permission, "allow_write")} /></Stack.Item>
<Stack.Item style={{ width: 36, margin: "0 20px 0 10px" }}><Checkbox checked={permission.allow_full} onChange={(ev) => onPermissionCheckboxClick(ev, permission, "allow_full")} /></Stack.Item>
<Stack.Item style={{ width: 36, margin: "0 10px" }}><Checkbox checked={permission.deny_access} onChange={(ev) => onPermissionCheckboxClick(ev, permission, "deny_access")} /></Stack.Item>
<Stack.Item style={{ width: 36, margin: "0 10px" }}><Checkbox checked={permission.deny_read} onChange={(ev) => onPermissionCheckboxClick(ev, permission, "deny_read")} /></Stack.Item>
<Stack.Item style={{ width: 36, margin: "0 10px" }}><Checkbox checked={permission.deny_write} onChange={(ev) => onPermissionCheckboxClick(ev, permission, "deny_write")} /></Stack.Item>
<Stack.Item style={{ width: 36, margin: "0 10px" }}><Checkbox checked={permission.deny_full} onChange={(ev) => onPermissionCheckboxClick(ev, permission, "deny_full")} /></Stack.Item>
</Stack>
))}
</div>
}
/>
<AddGroupResourceForm rname={Name} BasednName={BaseDn} refreshGrid={refreshData} showForm={showAddGroup} setShowForm={setShowAddGroup} />
<DeleteConfirm />
</>;
};
4 changes: 2 additions & 2 deletions esp/src/src-react/components/Security.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { SizeMe } from "react-sizeme";
import { pushUrl } from "../util/history";
import { Groups } from "./Groups";
import { Permissions } from "./Permissions";
import { PermissionsEditor } from "./PermissionsEditor";
import { Users } from "./Users";
import { useBuildInfo } from "../hooks/platform";
import { pivotItemStyle } from "../layouts/pivot";
import { DojoAdapter } from "../layouts/DojoAdapter";
import nlsHPCC from "src/nlsHPCC";

interface SecurityProps {
Expand Down Expand Up @@ -59,7 +59,7 @@ export const Security: React.FunctionComponent<SecurityProps> = ({
<Permissions />
}
{name && baseDn &&
<DojoAdapter widgetClassID="ShowIndividualPermissionsWidget" params={{ Basedn: baseDn, Name: name }} />
<PermissionsEditor BaseDn={baseDn} Name={name} />
}
</PivotItem>
</Pivot>
Expand Down
Loading

0 comments on commit 8cb73d9

Please sign in to comment.