LCOV - code coverage report
Current view: top level - pkg/lib - cockpit-components-privileged.tsx Coverage Total Hit
Test: cockpit Lines: 100.0 % 47 47
Test Date: 2026-06-16 14:09:37

            Line data    Source code
       1              : /*
       2              :  * Copyright (C) 2019 Red Hat, Inc.
       3              :  * SPDX-License-Identifier: LGPL-2.1-or-later
       4              :  */
       5           38 : import React from 'react';
       6              : 
       7              : import { Button, type ButtonProps } from "@patternfly/react-core/dist/esm/components/Button/index.js";
       8              : import { Tooltip, TooltipPosition } from "@patternfly/react-core/dist/esm/components/Tooltip/index.js";
       9              : 
      10           38 : import cockpit from "cockpit";
      11              : import { superuser } from 'superuser';
      12              : import { useEvent, useLoggedInUser } from "hooks";
      13              : 
      14              : /**
      15              :  * UI element wrapper for something that requires privilege. When access is not
      16              :  * allowed, then wrap the element into a Tooltip.
      17              :  *
      18              :  * Note that the wrapped element itself needs to be disabled explicitly, this
      19              :  * wrapper cannot do this (unfortunately wrapping it into a disabled span does
      20              :  * not inherit).
      21              :  */
      22           36 : export function Privileged({
      23           36 :     excuse,
      24           36 :     allowed,
      25           36 :     placement,
      26           36 :     tooltipId,
      27           36 :     children
      28           36 : }: {
      29              :     excuse: React.ReactNode;
      30              :     allowed: boolean | null;
      31              :     placement?: TooltipPosition | `${TooltipPosition}` | undefined;
      32              :     tooltipId?: string | undefined;
      33              :     children: React.ReactNode;
      34           36 : }) {
      35              :     // wrap into extra <span> so that a disabled child keeps the tooltip working
      36           28 :     let contents = <span id={allowed ? undefined : tooltipId}>{ children }</span>;
      37           35 :     if (!allowed) {
      38           35 :         contents = (
      39           35 :             <Tooltip position={ placement || TooltipPosition.top} id={ tooltipId + "_tooltip" }
      40           35 :                      content={ excuse }>
      41           35 :                 { contents }
      42           35 :             </Tooltip>);
      43           35 :     }
      44           36 :     return contents;
      45           36 : }
      46              : 
      47              : /**
      48              :  * Convenience element for a Privilege wrapped Button
      49              :  */
      50           25 : export const PrivilegedButton = ({
      51           25 :     tooltipId,
      52           25 :     placement,
      53           25 :     excuse,
      54           25 :     buttonId,
      55           25 :     onClick,
      56           25 :     ariaLabel,
      57           25 :     variant,
      58           25 :     isDanger,
      59           25 :     children
      60           25 : }: {
      61              :     excuse: string; // must contain a $0, replaced with user name
      62              :     onClick?: React.MouseEventHandler<HTMLButtonElement>;
      63              :     variant?: ButtonProps["variant"];
      64              :     isDanger?: boolean;
      65              :     placement?: TooltipPosition | `${TooltipPosition}` | undefined;
      66              :     buttonId?: string;
      67              :     tooltipId?: string;
      68              :     ariaLabel?: string;
      69              :     children: React.ReactNode;
      70           25 : }) => {
      71           25 :     const user = useLoggedInUser();
      72           25 :     useEvent(superuser, "changed");
      73              : 
      74           25 :     return (
      75           25 :         <Privileged allowed={ superuser.allowed } tooltipId={ tooltipId } placement={ placement }
      76            4 :                     excuse={ cockpit.format(excuse, user?.name ?? '') }>
      77           25 :             <Button isInline isDisabled={ !superuser.allowed }
      78           25 :                 {...(buttonId !== undefined && { id: buttonId })}
      79           25 :                 {...(variant !== undefined && { variant })}
      80            4 :                 {...(isDanger !== undefined && { isDanger })}
      81           25 :                 {...(onClick !== undefined && { onClick })}
      82            4 :                 {...(ariaLabel !== undefined && { "aria-label": ariaLabel })}
      83              :             >
      84           25 :                 { children }
      85           25 :             </Button>
      86           25 :         </Privileged>
      87              :     );
      88           25 : };
        

Generated by: LCOV version 2.0-1