Skip to content

Commit

Permalink
review: generalise instance entitlement check functions
Browse files Browse the repository at this point in the history
Signed-off-by: Mason Hu <[email protected]>
  • Loading branch information
MasWho committed Feb 13, 2025
1 parent d79409f commit 0c86b2d
Show file tree
Hide file tree
Showing 22 changed files with 97 additions and 131 deletions.
4 changes: 2 additions & 2 deletions src/pages/instances/EditInstance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const EditInstance: FC<Props> = ({ instance }) => {
const queryClient = useQueryClient();
const navigate = useNavigate();
const [version, setVersion] = useState(0);
const { canEditInstance } = useInstanceEntitlements(instance);
const { canEditInstance } = useInstanceEntitlements();
const { data: profiles = [] } = useQuery({
queryKey: [queryKeys.profiles],
queryFn: () => fetchProfiles(project || ""),
Expand All @@ -122,7 +122,7 @@ const EditInstance: FC<Props> = ({ instance }) => {
useEffect(updateFormHeight, [section]);
useEventListener("resize", updateFormHeight);

const editRestriction = !canEditInstance()
const editRestriction = !canEditInstance(instance)
? "You do not have permission to edit this instance"
: undefined;

Expand Down
16 changes: 8 additions & 8 deletions src/pages/instances/InstanceConsole.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ const InstanceConsole: FC<Props> = ({ instance }) => {
const isVm = instance.type === "virtual-machine";
const [isGraphic, setGraphic] = useState(isVm);
const { hasCustomVolumeIso } = useSupportedFeatures();
const { canUpdateInstanceState, canAccessConsole } =
useInstanceEntitlements(instance);
const { canUpdateInstanceState, canAccessInstanceConsole } =
useInstanceEntitlements();

const isRunning = instance.status === "Running";

Expand Down Expand Up @@ -61,7 +61,7 @@ const InstanceConsole: FC<Props> = ({ instance }) => {

return (
<div className="instance-console-tab">
{isVm && canAccessConsole() && (
{isVm && canAccessInstanceConsole(instance) && (
<div className="p-panel__controls">
<div className="console-radio-wrapper">
<RadioInput
Expand Down Expand Up @@ -120,9 +120,9 @@ const InstanceConsole: FC<Props> = ({ instance }) => {
appearance="positive"
loading={isLoading}
onClick={handleStart}
disabled={!canUpdateInstanceState()}
disabled={!canUpdateInstanceState(instance)}
title={
canUpdateInstanceState()
canUpdateInstanceState(instance)
? ""
: "You do not have permission to start this instance."
}
Expand All @@ -131,7 +131,7 @@ const InstanceConsole: FC<Props> = ({ instance }) => {
</ActionButton>
</EmptyState>
)}
{isGraphic && isRunning && canAccessConsole() && (
{isGraphic && isRunning && canAccessInstanceConsole(instance) && (
<div className="spice-wrapper">
<InstanceGraphicConsole
instance={instance}
Expand All @@ -140,14 +140,14 @@ const InstanceConsole: FC<Props> = ({ instance }) => {
/>
</div>
)}
{!isGraphic && canAccessConsole() && (
{!isGraphic && canAccessInstanceConsole(instance) && (
<InstanceTextConsole
instance={instance}
onFailure={onFailure}
showNotRunningInfo={showNotRunningInfo}
/>
)}
{!canAccessConsole() && (
{!canAccessInstanceConsole(instance) && (
<Notification severity="caution" title="Restricted permissions">
You do not have permission to access the console for this instance.
</Notification>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/instances/InstanceDetailHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const InstanceDetailHeader: FC<Props> = ({
const eventQueue = useEventQueue();
const navigate = useNavigate();
const toastNotify = useToastNotification();
const { canEditInstance } = useInstanceEntitlements(instance);
const { canEditInstance } = useInstanceEntitlements();
const controllerState = useState<AbortController | null>(null);

const RenameSchema = Yup.object().shape({
Expand Down Expand Up @@ -103,7 +103,7 @@ const InstanceDetailHeader: FC<Props> = ({
});

const getDisabledReason = () => {
if (!canEditInstance()) {
if (!canEditInstance(instance)) {
return "You do not have permission to rename this instance";
}

Expand Down
9 changes: 4 additions & 5 deletions src/pages/instances/InstanceTerminal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ const InstanceTerminal: FC<Props> = ({ instance, refreshInstance }) => {
const xtermRef = useRef<Terminal>(null);
const refreshTimerRef = useRef<NodeJS.Timeout | null>(null);
const [version, setVersion] = useState(0);
const { canUpdateInstanceState, canExecInstance } =
useInstanceEntitlements(instance);
const { canUpdateInstanceState, canExecInstance } = useInstanceEntitlements();

usePrompt({
when: userInteracted,
Expand Down Expand Up @@ -151,7 +150,7 @@ const InstanceTerminal: FC<Props> = ({ instance, refreshInstance }) => {
const isRunning = instance.status === "Running";
const isBooting = isRunning && (instance.state?.processes ?? 0) < 1;
const canConnect = isRunning && !isBooting;
const canExec = canExecInstance();
const canExec = canExecInstance(instance);

useEffect(() => {
if (isBooting && refreshTimerRef.current === null) {
Expand Down Expand Up @@ -260,9 +259,9 @@ const InstanceTerminal: FC<Props> = ({ instance, refreshInstance }) => {
appearance="positive"
loading={isStartLoading || isBooting}
onClick={handleStart}
disabled={!canUpdateInstanceState()}
disabled={!canUpdateInstanceState(instance)}
title={
canUpdateInstanceState()
canUpdateInstanceState(instance)
? ""
: "You do not have permission to start this instance."
}
Expand Down
4 changes: 2 additions & 2 deletions src/pages/instances/actions/AttachIsoBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const AttachIsoBtn: FC<Props> = ({ instance }) => {
const queryClient = useQueryClient();
const { openPortal, closePortal, isOpen, Portal } = usePortal();
const [isLoading, setLoading] = useState(false);
const { canEditInstance } = useInstanceEntitlements(instance);
const { canEditInstance } = useInstanceEntitlements();

const attachedIso = instance.devices["iso-volume"] as
| LxdIsoDevice
Expand Down Expand Up @@ -130,7 +130,7 @@ const AttachIsoBtn: FC<Props> = ({ instance }) => {
});
};

const disabledReason = canEditInstance()
const disabledReason = canEditInstance(instance)
? undefined
: "You do not have permission to edit this instance.";

Expand Down
6 changes: 3 additions & 3 deletions src/pages/instances/actions/DeleteInstanceBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const DeleteInstanceBtn: FC<Props> = ({ instance, classname, onClose }) => {
const instanceLoading = useInstanceLoading();
const [isLoading, setLoading] = useState(false);
const navigate = useNavigate();
const { canDeleteInstance } = useInstanceEntitlements(instance);
const { canDeleteInstance } = useInstanceEntitlements();

const handleDelete = () => {
setLoading(true);
Expand Down Expand Up @@ -75,9 +75,9 @@ const DeleteInstanceBtn: FC<Props> = ({ instance, classname, onClose }) => {
isLoading ||
!isDeletableStatus ||
instanceLoading.getType(instance) === "Migrating" ||
!canDeleteInstance();
!canDeleteInstance(instance);
const getHoverText = () => {
if (!canDeleteInstance()) {
if (!canDeleteInstance(instance)) {
return "You do not have permission to delete this instance";
}
if (!isDeletableStatus) {
Expand Down
6 changes: 3 additions & 3 deletions src/pages/instances/actions/ExportInstanceBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface Props {
const ExportInstanceBtn: FC<Props> = ({ instance, classname, onClose }) => {
const eventQueue = useEventQueue();
const toastNotify = useToastNotification();
const { canManageBackups } = useInstanceEntitlements(instance);
const { canManageInstanceBackups } = useInstanceEntitlements();

const instanceLink = <InstanceLinkChip instance={instance} />;

Expand Down Expand Up @@ -92,11 +92,11 @@ const ExportInstanceBtn: FC<Props> = ({ instance, classname, onClose }) => {
className={classNames("u-no-margin--bottom has-icon", classname)}
onClick={exportInstance}
title={
canManageBackups()
canManageInstanceBackups(instance)
? "Export instance"
: "You do not have permission to export this instance."
}
disabled={!canManageBackups()}
disabled={!canManageInstanceBackups(instance)}
>
<Icon name="export" />
<span>Export</span>
Expand Down
6 changes: 3 additions & 3 deletions src/pages/instances/actions/FreezeInstanceBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const FreezeInstanceBtn: FC<Props> = ({ instance }) => {
const instanceLoading = useInstanceLoading();
const toastNotify = useToastNotification();
const queryClient = useQueryClient();
const { canUpdateInstanceState } = useInstanceEntitlements(instance);
const { canUpdateInstanceState } = useInstanceEntitlements();

const clearCache = () => {
void queryClient.invalidateQueries({
Expand Down Expand Up @@ -83,12 +83,12 @@ const FreezeInstanceBtn: FC<Props> = ({ instance }) => {
</p>
),
onConfirm: handleFreeze,
confirmButtonLabel: canUpdateInstanceState()
confirmButtonLabel: canUpdateInstanceState(instance)
? "Freeze"
: "You do not have permission to freeze this instance",
}}
className="has-icon is-dense"
disabled={isDisabled || !canUpdateInstanceState()}
disabled={isDisabled || !canUpdateInstanceState(instance)}
shiftClickEnabled
showShiftClickHint
>
Expand Down
16 changes: 8 additions & 8 deletions src/pages/instances/actions/InstanceBulkAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface Props {
isLoading: boolean;
isDisabled: boolean;
onClick: () => void;
nonRestrictedInstances: Set<string>;
restrictedInstances: string[];
}

const InstanceBulkAction: FC<Props> = ({
Expand All @@ -34,7 +34,7 @@ const InstanceBulkAction: FC<Props> = ({
isLoading,
isDisabled,
onClick,
nonRestrictedInstances,
restrictedInstances,
}) => {
const selectedStates = new Set(instances.map((item) => item.status));
const hasDifferentStates = selectedStates.size > 1;
Expand All @@ -58,7 +58,7 @@ const InstanceBulkAction: FC<Props> = ({
const count = instances.filter(
(instance) =>
instance.status === currentState &&
nonRestrictedInstances.has(instance.name),
!restrictedInstances.includes(instance.name),
).length;

if (count === 0) {
Expand Down Expand Up @@ -108,15 +108,15 @@ const InstanceBulkAction: FC<Props> = ({
}
};

const getNonRestrictedInstances = () => {
const count = instances.length - nonRestrictedInstances.size;
if (count === 0) {
const getRestrictedInstances = () => {
if (restrictedInstances.length === 0) {
return null;
}

return (
<Fragment key="restricted">
- No action for <b>{count}</b> restricted instances.
- No action for <b>{restrictedInstances.length}</b> restricted
instances.
<br />
</Fragment>
);
Expand All @@ -134,7 +134,7 @@ const InstanceBulkAction: FC<Props> = ({
<p>
{selectedSummary}
{getLineOrder().map((state) => statusLine(state, action))}
{getNonRestrictedInstances()}
{getRestrictedInstances()}
</p>
),
confirmExtra: confirmExtra,
Expand Down
23 changes: 12 additions & 11 deletions src/pages/instances/actions/InstanceBulkActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import InstanceBulkAction from "pages/instances/actions/InstanceBulkAction";
import { getPromiseSettledCounts } from "util/helpers";
import { useEventQueue } from "context/eventQueue";
import { useToastNotification } from "context/toastNotificationProvider";
import { useInstanceEntitlementSet } from "util/entitlements/instances";
import { useInstanceEntitlements } from "util/entitlements/instances";

interface Props {
instances: LxdInstance[];
Expand All @@ -29,7 +29,7 @@ const InstanceBulkActions: FC<Props> = ({ instances, onStart, onFinish }) => {
null,
);
const [isForce, setForce] = useState(false);
const { canUpdateInstanceStateSet } = useInstanceEntitlementSet(instances);
const { canUpdateInstanceState } = useInstanceEntitlements();

const clearCache = () => {
void queryClient.invalidateQueries({
Expand All @@ -47,11 +47,8 @@ const InstanceBulkActions: FC<Props> = ({ instances, onStart, onFinish }) => {
const handleAction = (desiredAction: LxdInstanceAction) => {
setActiveAction(desiredAction);
onStart();
const actions = instanceActions(
instances,
desiredAction,
canUpdateInstanceStateSet,
);
const validInstances = instances.filter(canUpdateInstanceState);
const actions = instanceActions(validInstances, desiredAction);

void updateInstanceBulkAction(actions, isForce, eventQueue).then(
(results) => {
Expand Down Expand Up @@ -97,6 +94,10 @@ const InstanceBulkActions: FC<Props> = ({ instances, onStart, onFinish }) => {
);
};

const restrictedInstances = instances
.filter((instance) => !canUpdateInstanceState(instance))
.map((instance) => instance.name);

return (
<div className="p-segmented-control bulk-actions">
<div className="p-segmented-control__list bulk-action-frame">
Expand All @@ -109,7 +110,7 @@ const InstanceBulkActions: FC<Props> = ({ instances, onStart, onFinish }) => {
action="start"
instances={instances}
confirmLabel="Start"
nonRestrictedInstances={canUpdateInstanceStateSet}
restrictedInstances={restrictedInstances}
/>
<InstanceBulkAction
icon="restart"
Expand All @@ -125,7 +126,7 @@ const InstanceBulkActions: FC<Props> = ({ instances, onStart, onFinish }) => {
force={[isForce, setForce]}
/>
}
nonRestrictedInstances={canUpdateInstanceStateSet}
restrictedInstances={restrictedInstances}
/>
<InstanceBulkAction
icon="pause"
Expand All @@ -135,7 +136,7 @@ const InstanceBulkActions: FC<Props> = ({ instances, onStart, onFinish }) => {
action="freeze"
instances={instances}
confirmLabel="Freeze"
nonRestrictedInstances={canUpdateInstanceStateSet}
restrictedInstances={restrictedInstances}
/>
<InstanceBulkAction
icon="stop"
Expand All @@ -148,7 +149,7 @@ const InstanceBulkActions: FC<Props> = ({ instances, onStart, onFinish }) => {
confirmExtra={
<ConfirmationForce label="Force stop" force={[isForce, setForce]} />
}
nonRestrictedInstances={canUpdateInstanceStateSet}
restrictedInstances={restrictedInstances}
/>
</div>
</div>
Expand Down
12 changes: 7 additions & 5 deletions src/pages/instances/actions/InstanceBulkDelete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getPromiseSettledCounts } from "util/helpers";
import { ConfirmationButton, Icon } from "@canonical/react-components";
import { useEventQueue } from "context/eventQueue";
import { useToastNotification } from "context/toastNotificationProvider";
import { useInstanceEntitlementSet } from "util/entitlements/instances";
import { useInstanceEntitlements } from "util/entitlements/instances";

interface Props {
instances: LxdInstance[];
Expand All @@ -22,16 +22,18 @@ const InstanceBulkDelete: FC<Props> = ({ instances, onStart, onFinish }) => {
const toastNotify = useToastNotification();
const queryClient = useQueryClient();
const [isLoading, setLoading] = useState(false);
const { canDeleteInstanceStateSet } = useInstanceEntitlementSet(instances);

const { canDeleteInstance } = useInstanceEntitlements();
const restrictedInstances = instances.filter(
(instance) => !canDeleteInstance(instance),
);
const deletableInstances = instances.filter(
(instance) =>
deletableStatuses.includes(instance.status) &&
canDeleteInstanceStateSet.has(instance.name),
canDeleteInstance(instance),
);
const totalCount = instances.length;
const deleteCount = deletableInstances.length;
const restrictedCount = totalCount - canDeleteInstanceStateSet.size;
const restrictedCount = restrictedInstances.length;
const ignoredCount = totalCount - deleteCount - restrictedCount;

const handleDelete = () => {
Expand Down
4 changes: 2 additions & 2 deletions src/pages/instances/actions/MigrateInstanceBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface Props {

const MigrateInstanceBtn: FC<Props> = ({ instance, classname }) => {
const { openPortal, closePortal, isOpen, Portal } = usePortal();
const { canEditInstance } = useInstanceEntitlements(instance);
const { canEditInstance } = useInstanceEntitlements();
const instanceLoading = useInstanceLoading();
const isLoading =
instanceLoading.getType(instance) === "Migrating" ||
Expand All @@ -36,7 +36,7 @@ const MigrateInstanceBtn: FC<Props> = ({ instance, classname }) => {
type="button"
className={classNames("u-no-margin--bottom has-icon", classname)}
loading={isLoading}
disabled={isDisabled || !canEditInstance()}
disabled={isDisabled || !canEditInstance(instance)}
title={
canEditInstance()
? "Migrate instance"
Expand Down
Loading

0 comments on commit 0c86b2d

Please sign in to comment.