mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 01:52:22 +00:00
feat(rbac): added glob support in permission and revealed settings
This commit is contained in:
@@ -1,78 +1,92 @@
|
||||
|
||||
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { Checkbox, PopoverContent } from "@app/components/v2";
|
||||
import { Button, Checkbox, PopoverContent } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
|
||||
|
||||
import { WsTag } from "../../hooks/api/tags/types";
|
||||
import { ProjectPermissionCan } from "../permissions";
|
||||
|
||||
interface Props {
|
||||
wsTags: WsTag[] | undefined;
|
||||
secKey: string;
|
||||
selectedTagIds: Record<string, boolean>;
|
||||
handleSelectTag: (wsTag: WsTag) => void;
|
||||
handleTagOnMouseEnter: (wsTag: WsTag) => void;
|
||||
handleTagOnMouseLeave: () => void;
|
||||
checkIfTagIsVisible: (wsTag: WsTag) => boolean;
|
||||
handleOnCreateTagOpen: () => void
|
||||
wsTags: WsTag[] | undefined;
|
||||
secKey: string;
|
||||
selectedTagIds: Record<string, boolean>;
|
||||
handleSelectTag: (wsTag: WsTag) => void;
|
||||
handleTagOnMouseEnter: (wsTag: WsTag) => void;
|
||||
handleTagOnMouseLeave: () => void;
|
||||
checkIfTagIsVisible: (wsTag: WsTag) => boolean;
|
||||
handleOnCreateTagOpen: () => void;
|
||||
}
|
||||
|
||||
const AddTagPopoverContent = ({
|
||||
wsTags,
|
||||
secKey,
|
||||
selectedTagIds,
|
||||
handleSelectTag,
|
||||
handleTagOnMouseEnter,
|
||||
handleTagOnMouseLeave,
|
||||
checkIfTagIsVisible,
|
||||
handleOnCreateTagOpen
|
||||
wsTags,
|
||||
secKey,
|
||||
selectedTagIds,
|
||||
handleSelectTag,
|
||||
handleTagOnMouseEnter,
|
||||
handleTagOnMouseLeave,
|
||||
checkIfTagIsVisible,
|
||||
handleOnCreateTagOpen
|
||||
}: Props) => {
|
||||
return (
|
||||
<PopoverContent
|
||||
side="left"
|
||||
className="relative max-h-96 w-auto min-w-[200px] p-2 overflow-y-auto overflow-x-hidden border border-mineshaft-600 bg-mineshaft-800 text-bunker-200"
|
||||
hideCloseBtn
|
||||
>
|
||||
<div className=" text-center text-sm font-medium text-bunker-200">
|
||||
Add tags to {secKey || "this secret"}
|
||||
return (
|
||||
<PopoverContent
|
||||
side="left"
|
||||
className="relative max-h-96 w-auto min-w-[200px] p-2 overflow-y-auto overflow-x-hidden border border-mineshaft-600 bg-mineshaft-800 text-bunker-200"
|
||||
hideCloseBtn
|
||||
>
|
||||
<div className=" text-center text-sm font-medium text-bunker-200">
|
||||
Add tags to {secKey || "this secret"}
|
||||
</div>
|
||||
<div className="absolute left-0 w-full border-mineshaft-600 border-t mt-2" />
|
||||
<div className="flex flex-col space-y-1.5">
|
||||
{wsTags?.map((wsTag: WsTag) => (
|
||||
<div
|
||||
key={`tag-${wsTag._id}`}
|
||||
className="mt-4 h-[32px] relative flex items-center justify-start hover:border-mineshaft-600 hover:border hover:bg-mineshaft-700 p-2 rounded-md hover:text-bunker-200 bg-none"
|
||||
onClick={() => handleSelectTag(wsTag)}
|
||||
onMouseEnter={() => handleTagOnMouseEnter(wsTag)}
|
||||
onMouseLeave={() => handleTagOnMouseLeave()}
|
||||
tabIndex={0}
|
||||
role="button"
|
||||
onKeyDown={() => {}}
|
||||
>
|
||||
{(checkIfTagIsVisible(wsTag) || selectedTagIds?.[wsTag.slug]) && (
|
||||
<Checkbox
|
||||
id="autoCapitalization"
|
||||
isChecked={selectedTagIds?.[wsTag.slug]}
|
||||
className="absolute top-[50%] translate-y-[-50%] left-[10px] "
|
||||
checkIndicatorBg={`${
|
||||
!selectedTagIds?.[wsTag.slug] ? "text-transparent" : "text-mineshaft-800"
|
||||
}`}
|
||||
/>
|
||||
)}
|
||||
<div className="ml-7 flex items-center gap-3">
|
||||
<div
|
||||
className="w-[10px] h-[10px] rounded-full"
|
||||
style={{ background: wsTag?.tagColor ? wsTag.tagColor : "#bec2c8" }}
|
||||
>
|
||||
{" "}
|
||||
</div>
|
||||
<span>{wsTag.slug}</span>
|
||||
</div>
|
||||
<div className="absolute left-0 w-full border-mineshaft-600 border-t mt-2" />
|
||||
<div className="flex flex-col space-y-1.5">
|
||||
{wsTags?.map((wsTag: WsTag) => (
|
||||
<div key={`tag-${wsTag._id}`} className="mt-4 h-[32px] relative flex items-center justify-start hover:border-mineshaft-600 hover:border hover:bg-mineshaft-700 p-2 rounded-md hover:text-bunker-200 bg-none"
|
||||
onClick={() => handleSelectTag(wsTag)}
|
||||
onMouseEnter={() => handleTagOnMouseEnter(wsTag)}
|
||||
onMouseLeave={() => handleTagOnMouseLeave()}
|
||||
tabIndex={0} role="button"
|
||||
onKeyDown={() => { }}>
|
||||
{
|
||||
</div>
|
||||
))}
|
||||
<ProjectPermissionCan I={ProjectPermissionActions.Create} a={ProjectPermissionSub.Tags}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
onClick={() => handleOnCreateTagOpen()}
|
||||
isDisabled={!isAllowed}
|
||||
size="xs"
|
||||
className="mt-2"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} className="ml-1 mr-2" />}
|
||||
>
|
||||
Add new tag
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
);
|
||||
};
|
||||
|
||||
(checkIfTagIsVisible(wsTag) || selectedTagIds?.[wsTag.slug]) && <Checkbox
|
||||
id="autoCapitalization"
|
||||
isChecked={selectedTagIds?.[wsTag.slug]}
|
||||
className="absolute top-[50%] translate-y-[-50%] left-[10px] "
|
||||
checkIndicatorBg={`${!selectedTagIds?.[wsTag.slug] ? "text-transparent" : "text-mineshaft-800"}`}
|
||||
/>
|
||||
}
|
||||
<div className="ml-7 flex items-center gap-3">
|
||||
<div className="w-[10px] h-[10px] rounded-full" style={{ background: wsTag?.tagColor ? wsTag.tagColor : "#bec2c8" }}> </div>
|
||||
<span >
|
||||
{wsTag.slug}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<div
|
||||
className="h-[32px] relative flex items-center cursor-pointer justify-start border-mineshaft-600 border bg-mineshaft-700 p-2 rounded-md hover:text-bunker-200 bg-none"
|
||||
onClick={() => handleOnCreateTagOpen()}
|
||||
tabIndex={0} role="button"
|
||||
onKeyDown={() => { }}>
|
||||
<FontAwesomeIcon icon={faPlus} className="ml-1 mr-2" />
|
||||
<span> Add new tag</span>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddTagPopoverContent
|
||||
export default AddTagPopoverContent;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { ReactNode } from "react";
|
||||
import { faLock } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
type Props = {
|
||||
containerClassName?: string;
|
||||
className?: string;
|
||||
children?: ReactNode;
|
||||
};
|
||||
|
||||
export const PermissionDeniedBanner = ({ containerClassName, className, children }: Props) => {
|
||||
return (
|
||||
<div
|
||||
className={twMerge(
|
||||
"container h-full mx-auto flex justify-center items-center",
|
||||
containerClassName
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={twMerge(
|
||||
"rounded-md bg-mineshaft-800 text-bunker-300 p-16 flex space-x-12 items-end",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div>
|
||||
<FontAwesomeIcon icon={faLock} size="6x" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-4xl font-medium mb-2">Permission Denied</div>
|
||||
{children || (
|
||||
<div className="text-sm">
|
||||
You do not have permission. <br /> Kindly contact your organization administrator
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -11,7 +11,11 @@ type Props = {
|
||||
// so when permission is allowed same tooltip will be reused to show helpertext
|
||||
renderTooltip?: boolean;
|
||||
allowedLabel?: string;
|
||||
} & BoundCanProps<TProjectPermission>;
|
||||
// BUG(akhilmhdh): As a workaround for now i put any but this should be TProjectPermission
|
||||
// For some reason when i put TProjectPermission in a wrapper component it just wont work causes a weird ts error
|
||||
// tried a lot combinations
|
||||
// REF: https://github.com/stalniy/casl/blob/ac081a34f56366a7eaaed05d21689d27041ef005/packages/casl-react/src/factory.ts#L15
|
||||
} & BoundCanProps<any>;
|
||||
|
||||
export const ProjectPermissionCan: FunctionComponent<Props> = ({
|
||||
label = "Permission Denied. Kindly contact your project admin",
|
||||
@@ -22,7 +26,6 @@ export const ProjectPermissionCan: FunctionComponent<Props> = ({
|
||||
...props
|
||||
}) => {
|
||||
const permission = useProjectPermission();
|
||||
|
||||
return (
|
||||
<Can {...props} passThrough={passThrough} ability={props?.ability || permission}>
|
||||
{(isAllowed, ability) => {
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export { OrgPermissionCan } from "./OrgPermissionCan";
|
||||
export { PermissionDeniedBanner } from "./PermissionDeniedBanner";
|
||||
export { ProjectPermissionCan } from "./ProjectPermissionCan";
|
||||
|
||||
Reference in New Issue
Block a user