Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(RBAC): add permission's info #6617

Merged
merged 1 commit into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions ui/actions/manage-groups/manage-groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ export const updateProviderGroup = async (
});

if (!response.ok) {
const errorResponse = await response.json();
throw new Error(
`Failed to update provider group: ${response.status} ${response.statusText}`,
);
Expand All @@ -202,7 +201,6 @@ export const updateProviderGroup = async (
revalidatePath("/manage-groups");
return parseStringify(data);
} catch (error) {
console.error("Unexpected error:", error);
return {
error: getErrorMessage(error),
};
Expand Down
65 changes: 36 additions & 29 deletions ui/components/roles/workflow/forms/add-role-form.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { Checkbox, Divider } from "@nextui-org/react";
import { SaveIcon } from "lucide-react";
import { Checkbox, Divider, Tooltip } from "@nextui-org/react";
import clsx from "clsx";
import { InfoIcon, SaveIcon } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
Expand All @@ -16,6 +17,7 @@ import {
CustomInput,
} from "@/components/ui/custom";
import { Form } from "@/components/ui/form";
import { permissionFormFields } from "@/lib";
import { addRoleFormSchema, ApiError } from "@/types";

type FormValues = z.infer<typeof addRoleFormSchema>;
Expand Down Expand Up @@ -138,19 +140,6 @@ export const AddRoleForm = ({
}
};

const permissions = [
{ field: "manage_users", label: "Invite and Manage Users" },
...(process.env.NEXT_PUBLIC_IS_CLOUD_ENV === "true"
? [{ field: "manage_billing", label: "Manage Billing" }]
: []),
{ field: "manage_providers", label: "Manage Cloud Providers" },
{ field: "manage_account", label: "Manage Account" },
// TODO: Add back when we have integrations ready
// { field: "manage_integrations", label: "Manage Integrations" },
{ field: "manage_scans", label: "Manage Scans" },
{ field: "unlimited_visibility", label: "Unlimited Visibility" },
];

return (
<Form {...form}>
<form
Expand All @@ -174,7 +163,7 @@ export const AddRoleForm = ({

{/* Select All Checkbox */}
<Checkbox
isSelected={permissions.every((perm) =>
isSelected={permissionFormFields.every((perm) =>
form.watch(perm.field as keyof FormValues),
)}
onChange={(e) => onSelectAllChange(e.target.checked)}
Expand All @@ -188,19 +177,37 @@ export const AddRoleForm = ({

{/* Permissions Grid */}
<div className="grid grid-cols-2 gap-4">
{permissions.map(({ field, label }) => (
<Checkbox
key={field}
{...form.register(field as keyof FormValues)}
isSelected={!!form.watch(field as keyof FormValues)}
classNames={{
label: "text-small",
wrapper: "checkbox-update",
}}
>
{label}
</Checkbox>
))}
{permissionFormFields
.filter(
(permission) =>
permission.field !== "manage_billing" ||
process.env.NEXT_PUBLIC_IS_CLOUD_ENV === "true",
)
.map(({ field, label, description }) => (
<div key={field} className="flex items-center gap-2">
<Checkbox
{...form.register(field as keyof FormValues)}
isSelected={!!form.watch(field as keyof FormValues)}
classNames={{
label: "text-small",
wrapper: "checkbox-update",
}}
>
{label}
</Checkbox>
<Tooltip content={description} placement="right">
<div className="flex w-fit items-center justify-center">
<InfoIcon
className={clsx(
"cursor-pointer text-default-400 group-data-[selected=true]:text-foreground",
)}
aria-hidden={"true"}
width={16}
/>
</div>
</Tooltip>
</div>
))}
</div>
</div>
<Divider className="my-4" />
Expand Down
65 changes: 36 additions & 29 deletions ui/components/roles/workflow/forms/edit-role-form.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { Checkbox, Divider } from "@nextui-org/react";
import { SaveIcon } from "lucide-react";
import { Checkbox, Divider, Tooltip } from "@nextui-org/react";
import { clsx } from "clsx";
import { InfoIcon, SaveIcon } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect } from "react";
import { Controller, useForm } from "react-hook-form";
Expand All @@ -16,6 +17,7 @@ import {
CustomInput,
} from "@/components/ui/custom";
import { Form } from "@/components/ui/form";
import { permissionFormFields } from "@/lib";
import { ApiError, editRoleFormSchema } from "@/types";

type FormValues = z.infer<typeof editRoleFormSchema>;
Expand Down Expand Up @@ -162,19 +164,6 @@ export const EditRoleForm = ({
}
};

const permissions = [
{ field: "manage_users", label: "Invite and Manage Users" },
...(process.env.NEXT_PUBLIC_IS_CLOUD_ENV === "true"
? [{ field: "manage_billing", label: "Manage Billing" }]
: []),
{ field: "manage_account", label: "Manage Account" },
{ field: "manage_providers", label: "Manage Cloud Providers" },
// TODO: Add back when we have integrations ready
// { field: "manage_integrations", label: "Manage Integrations" },
{ field: "manage_scans", label: "Manage Scans" },
{ field: "unlimited_visibility", label: "Unlimited Visibility" },
];

return (
<Form {...form}>
<form
Expand All @@ -198,7 +187,7 @@ export const EditRoleForm = ({

{/* Select All Checkbox */}
<Checkbox
isSelected={permissions.every((perm) =>
isSelected={permissionFormFields.every((perm) =>
form.watch(perm.field as keyof FormValues),
)}
onChange={(e) => onSelectAllChange(e.target.checked)}
Expand All @@ -212,19 +201,37 @@ export const EditRoleForm = ({

{/* Permissions Grid */}
<div className="grid grid-cols-2 gap-4">
{permissions.map(({ field, label }) => (
<Checkbox
key={field}
{...form.register(field as keyof FormValues)}
isSelected={!!form.watch(field as keyof FormValues)}
classNames={{
label: "text-small",
wrapper: "checkbox-update",
}}
>
{label}
</Checkbox>
))}
{permissionFormFields
.filter(
(permission) =>
permission.field !== "manage_billing" ||
process.env.NEXT_PUBLIC_IS_CLOUD_ENV === "true",
)
.map(({ field, label, description }) => (
<div key={field} className="flex items-center gap-2">
<Checkbox
{...form.register(field as keyof FormValues)}
isSelected={!!form.watch(field as keyof FormValues)}
classNames={{
label: "text-small",
wrapper: "checkbox-update",
}}
>
{label}
</Checkbox>
<Tooltip content={description} placement="right">
<div className="flex w-fit items-center justify-center">
<InfoIcon
className={clsx(
"cursor-pointer text-default-400 group-data-[selected=true]:text-foreground",
)}
aria-hidden={"true"}
width={16}
/>
</div>
</Tooltip>
</div>
))}
</div>
</div>
<Divider className="my-4" />
Expand Down
44 changes: 43 additions & 1 deletion ui/lib/helper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getTask } from "@/actions/task";
import { MetaDataProps } from "@/types";
import { MetaDataProps, PermissionInfo } from "@/types";

export async function checkTaskStatus(
taskId: string,
Expand Down Expand Up @@ -183,3 +183,45 @@ export const regions = [
{ key: "us-west2", label: "GCP - US West (Los Angeles)" },
{ key: "us-east4", label: "GCP - US East (Northern Virginia)" },
];

export const permissionFormFields: PermissionInfo[] = [
{
field: "manage_users",
label: "Invite and Manage Users",
description: "Allows inviting new users and managing existing user details",
},
{
field: "manage_account",
label: "Manage Account",
description: "Provides access to account settings and RBAC configuration",
},
{
field: "unlimited_visibility",
label: "Unlimited Visibility",
description:
"Provides complete visibility across all the providers and its related resources",
},
{
field: "manage_providers",
label: "Manage Cloud Providers",
description:
"Allows configuration and management of cloud provider connections",
},
// {
// field: "manage_integrations",
// label: "Manage Integrations",
// description:
// "Controls the setup and management of third-party integrations",
// },
{
field: "manage_scans",
label: "Manage Scans",
description: "Allows launching and configuring scans security scans",
},

{
field: "manage_billing",
label: "Manage Billing",
description: "Provides access to billing settings and invoices",
},
];
1 change: 1 addition & 0 deletions ui/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ module.exports = {
"0px -6px 24px #FFFFFF, 0px 7px 16px rgba(104, 132, 157, 0.5)",
up: "0.3rem 0.3rem 0.6rem #c8d0e7, -0.2rem -0.2rem 0.5rem #fff",
down: "inset 0.2rem 0.2rem 0.5rem #c8d0e7, inset -0.2rem -0.2rem 0.5rem #fff",
box: "rgba(0, 0, 0, 0.05) 0px 0px 0px 1px",
},
animation: {
"fade-in": "fade-in 200ms ease-out 0s 1 normal forwards running",
Expand Down
5 changes: 5 additions & 0 deletions ui/types/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export type NextUIColors =
| "danger"
| "default";

export interface PermissionInfo {
field: string;
label: string;
description: string;
}
export interface FindingsByStatusData {
data: {
type: "findings-overview";
Expand Down
Loading