[Fleet] Fix issues with read access to settings (#180753)

## Summary

Resolves #180663. Resolves #180662. Resolves #180661.

This PR fixes several UI issues when user only has `Read` privilege to
Fleet settings:

- Disable Fleet Server proxy combobox correctly
- Hide Delete agent binary source button
- Disable setting agent binary source as default 
- Hide agent count and add agent/fleet server CTA links on agent policy
details page
This commit is contained in:
Jen Huang 2024-04-15 10:39:39 -07:00 committed by GitHub
parent 24c4049d4e
commit b41748436a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 62 additions and 45 deletions

View file

@ -69,19 +69,18 @@ export const HeaderRightContent: React.FunctionComponent<HeaderRightContentProps
return null;
}
const addFleetServerLink = (
<EuiLink onClick={addAgent} data-test-subj="addAgentLink">
<FormattedMessage
id="xpack.fleet.policyDetails.addFleetServerButton"
defaultMessage="Add Fleet Server"
/>
</EuiLink>
);
const addAgentLink = (
<EuiLink onClick={addAgent} data-test-subj="addAgentLink">
{isFleetServerPolicy ? (
<FormattedMessage
id="xpack.fleet.policyDetails.addFleetServerButton"
defaultMessage="Add Fleet Server"
/>
) : (
<FormattedMessage
id="xpack.fleet.policyDetails.addAgentButton"
defaultMessage="Add agent"
/>
)}
<FormattedMessage id="xpack.fleet.policyDetails.addAgentButton" defaultMessage="Add agent" />
</EuiLink>
);
@ -111,35 +110,48 @@ export const HeaderRightContent: React.FunctionComponent<HeaderRightContentProps
),
},
{ isDivider: true },
{
label: i18n.translate('xpack.fleet.policyDetails.summary.usedBy', {
defaultMessage: 'Agents',
}),
content:
agentStatus && agentStatus!.total ? (
<LinkedAgentCount
count={agentStatus.total}
agentPolicyId={(agentPolicy && agentPolicy.id) || ''}
showAgentText
/>
) : !authz.fleet.allAgents || agentPolicy?.is_managed ? (
<LinkedAgentCount
count={0}
agentPolicyId={(agentPolicy && agentPolicy.id) || ''}
showAgentText
/>
) : (
<AddAgentHelpPopover
button={addAgentLink}
isOpen={isAddAgentHelpPopoverOpen}
offset={15}
closePopover={() => {
setIsAddAgentHelpPopoverOpen(false);
}}
/>
),
},
{ isDivider: true },
...(authz.fleet.readAgents
? [
{
label: i18n.translate('xpack.fleet.policyDetails.summary.usedBy', {
defaultMessage: 'Agents',
}),
content:
agentStatus && agentStatus!.total ? (
<LinkedAgentCount
count={agentStatus.total}
agentPolicyId={(agentPolicy && agentPolicy.id) || ''}
showAgentText
/>
) : isFleetServerPolicy && authz.fleet.addFleetServers ? (
<AddAgentHelpPopover
button={addFleetServerLink}
isOpen={isAddAgentHelpPopoverOpen}
offset={15}
closePopover={() => {
setIsAddAgentHelpPopoverOpen(false);
}}
/>
) : !isFleetServerPolicy && authz.fleet.addAgents ? (
<AddAgentHelpPopover
button={addAgentLink}
isOpen={isAddAgentHelpPopoverOpen}
offset={15}
closePopover={() => {
setIsAddAgentHelpPopoverOpen(false);
}}
/>
) : (
<LinkedAgentCount
count={0}
agentPolicyId={(agentPolicy && agentPolicy.id) || ''}
showAgentText
/>
),
},
{ isDivider: true },
]
: []),
{
label: i18n.translate('xpack.fleet.policyDetails.summary.lastUpdated', {
defaultMessage: 'Last updated on',

View file

@ -34,7 +34,7 @@ export function useDowloadSourceFlyoutForm(onSuccess: () => void, downloadSource
const defaultDownloadSourceInput = useSwitchInput(
downloadSource?.is_default ?? false,
downloadSource?.is_default
downloadSource?.is_default || isEditDisabled
);
const hostInput = useInput(downloadSource?.host ?? '', validateHost, isEditDisabled);
@ -116,7 +116,7 @@ export function useDowloadSourceFlyoutForm(onSuccess: () => void, downloadSource
inputs,
submit,
isLoading,
isDisabled: isLoading || (downloadSource && !hasChanged),
isDisabled: isLoading || (downloadSource && !hasChanged) || isEditDisabled,
};
}

View file

@ -17,6 +17,7 @@ import type { DownloadSource } from '../../../../types';
export interface DownloadSourceTableProps {
downloadSources: DownloadSource[];
deleteDownloadSource: (ds: DownloadSource) => void;
hasAllSettingsPrivileges: boolean;
}
const NameFlexItemWithMaxWidth = styled(EuiFlexItem)`
@ -31,6 +32,7 @@ const FlexGroupWithMinWidth = styled(EuiFlexGroup)`
export const DownloadSourceTable: React.FunctionComponent<DownloadSourceTableProps> = ({
downloadSources,
deleteDownloadSource,
hasAllSettingsPrivileges,
}) => {
const { getHref } = useLink();
@ -87,7 +89,7 @@ export const DownloadSourceTable: React.FunctionComponent<DownloadSourceTablePro
{
width: '68px',
render: (downloadSource: DownloadSource) => {
const isDeleteVisible = !downloadSource.is_default;
const isDeleteVisible = !downloadSource.is_default && hasAllSettingsPrivileges;
return (
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd">
@ -131,7 +133,7 @@ export const DownloadSourceTable: React.FunctionComponent<DownloadSourceTablePro
}),
},
];
}, [deleteDownloadSource, getHref]);
}, [deleteDownloadSource, getHref, hasAllSettingsPrivileges]);
return (
<EuiBasicTable

View file

@ -218,6 +218,7 @@ export const FleetServerHostsFlyout: React.FunctionComponent<FleetServerHostsFly
}
options={proxiesOptions}
singleSelection={{ asPlainText: true }}
isDisabled={inputs.proxyIdInput.props.disabled}
isClearable={true}
placeholder={i18n.translate(
'xpack.fleet.settings.fleetServerHostsFlyout.proxyIdPlaceholder',

View file

@ -24,6 +24,7 @@ export const AgentBinarySection: React.FunctionComponent<AgentBinarySectionProps
}) => {
const { getHref } = useLink();
const authz = useAuthz();
const hasAllSettingsPrivileges = authz.fleet.allSettings;
return (
<>
@ -46,8 +47,9 @@ export const AgentBinarySection: React.FunctionComponent<AgentBinarySectionProps
<DownloadSourceTable
downloadSources={downloadSources}
deleteDownloadSource={deleteDownloadSource}
hasAllSettingsPrivileges={hasAllSettingsPrivileges}
/>
{authz.fleet.allSettings && (
{hasAllSettingsPrivileges && (
<>
<EuiSpacer size="s" />
<EuiButtonEmpty