mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Opt for bulk save role permissions instead of save on each form change
This commit is contained in:
@@ -66,7 +66,6 @@ export const OrgRoleTable = () => {
|
||||
colorSchema="primary"
|
||||
type="submit"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
// onClick={() => onSelectRole()}
|
||||
onClick={() => {
|
||||
handlePopUpOpen("role");
|
||||
}}
|
||||
|
||||
@@ -64,11 +64,8 @@ type Props = {
|
||||
formName: keyof Omit<Exclude<TFormSchema["permissions"], undefined>, "workspace">;
|
||||
setValue: UseFormSetValue<TFormSchema>;
|
||||
control: Control<TFormSchema>;
|
||||
handleSubmit: () => void;
|
||||
};
|
||||
|
||||
// permission categories
|
||||
|
||||
enum Permission {
|
||||
NoAccess = "no-access",
|
||||
ReadOnly = "read-only",
|
||||
@@ -76,16 +73,7 @@ enum Permission {
|
||||
Custom = "custom"
|
||||
}
|
||||
|
||||
// TODO: support for default roles
|
||||
|
||||
export const RolePermissionRow = ({
|
||||
isEditable,
|
||||
title,
|
||||
formName,
|
||||
handleSubmit,
|
||||
control,
|
||||
setValue
|
||||
}: Props) => {
|
||||
export const RolePermissionRow = ({ isEditable, title, formName, control, setValue }: Props) => {
|
||||
const [isRowExpanded, setIsRowExpanded] = useToggle();
|
||||
const [isCustom, setIsCustom] = useToggle();
|
||||
|
||||
@@ -157,8 +145,6 @@ export const RolePermissionRow = ({
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
handleSubmit();
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -211,7 +197,6 @@ export const RolePermissionRow = ({
|
||||
return;
|
||||
}
|
||||
field.onChange(e);
|
||||
handleSubmit();
|
||||
}}
|
||||
id={`permissions.${formName}.${action}`}
|
||||
>
|
||||
|
||||
@@ -1,18 +1,162 @@
|
||||
import { RolePermissionsTable } from "./RolePermissionsTable";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button , Table, TableContainer, TBody, Th, THead, Tr } from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import { useGetOrgRole, useUpdateOrgRole } from "@app/hooks/api";
|
||||
import {
|
||||
formRolePermission2API,
|
||||
formSchema,
|
||||
rolePermission2Form,
|
||||
TFormSchema
|
||||
} from "@app/views/Org/MembersPage/components/OrgRoleTabSection/OrgRoleModifySection/OrgRoleModifySection.utils";
|
||||
|
||||
import { RolePermissionRow } from "./RolePermissionRow";
|
||||
|
||||
const SIMPLE_PERMISSION_OPTIONS = [
|
||||
{
|
||||
title: "User management",
|
||||
formName: "member"
|
||||
},
|
||||
{
|
||||
title: "Group management",
|
||||
formName: "groups"
|
||||
},
|
||||
{
|
||||
title: "Machine identity management",
|
||||
formName: "identity"
|
||||
},
|
||||
{
|
||||
title: "Billing & usage",
|
||||
formName: "billing"
|
||||
},
|
||||
{
|
||||
title: "Role management",
|
||||
formName: "role"
|
||||
},
|
||||
{
|
||||
title: "Incident Contacts",
|
||||
formName: "incident-contact"
|
||||
},
|
||||
{
|
||||
title: "Organization profile",
|
||||
formName: "settings"
|
||||
},
|
||||
{
|
||||
title: "Secret Scanning",
|
||||
formName: "secret-scanning"
|
||||
},
|
||||
{
|
||||
title: "SSO",
|
||||
formName: "sso"
|
||||
},
|
||||
{
|
||||
title: "LDAP",
|
||||
formName: "ldap"
|
||||
},
|
||||
{
|
||||
title: "SCIM",
|
||||
formName: "scim"
|
||||
}
|
||||
] as const;
|
||||
|
||||
type Props = {
|
||||
roleId: string;
|
||||
};
|
||||
|
||||
export const RolePermissionsSection = ({ roleId }: Props) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const orgId = currentOrg?.id || "";
|
||||
|
||||
const { data: role } = useGetOrgRole(orgId, roleId);
|
||||
|
||||
const {
|
||||
setValue,
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { isDirty, isSubmitting },
|
||||
reset
|
||||
} = useForm<TFormSchema>({
|
||||
defaultValues: role ? { ...role, permissions: rolePermission2Form(role.permissions) } : {},
|
||||
resolver: zodResolver(formSchema)
|
||||
});
|
||||
|
||||
const { mutateAsync: updateRole } = useUpdateOrgRole();
|
||||
|
||||
const onSubmit = async (el: TFormSchema) => {
|
||||
try {
|
||||
await updateRole({
|
||||
orgId,
|
||||
id: roleId,
|
||||
...el,
|
||||
permissions: formRolePermission2API(el.permissions)
|
||||
});
|
||||
createNotification({ type: "success", text: "Successfully updated role" });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
createNotification({ type: "error", text: "Failed to update role" });
|
||||
}
|
||||
};
|
||||
|
||||
const isCustomRole = !["admin", "member", "no-access"].includes(role?.slug ?? "");
|
||||
|
||||
return (
|
||||
<div className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<form
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"
|
||||
>
|
||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
||||
<h3 className="text-lg font-semibold text-mineshaft-100">Permissions</h3>
|
||||
{isCustomRole && (
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
colorSchema="primary"
|
||||
type="submit"
|
||||
isDisabled={isSubmitting || !isDirty}
|
||||
isLoading={isSubmitting}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
className="ml-4 text-mineshaft-300"
|
||||
variant="link"
|
||||
isDisabled={isSubmitting || !isDirty}
|
||||
isLoading={isSubmitting}
|
||||
onClick={() => reset()}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="py-4">
|
||||
<RolePermissionsTable roleId={roleId} />
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
<Th className="w-5" />
|
||||
<Th>Resource</Th>
|
||||
<Th>Permission</Th>
|
||||
</Tr>
|
||||
</THead>
|
||||
<TBody>
|
||||
{SIMPLE_PERMISSION_OPTIONS.map((permission) => {
|
||||
return (
|
||||
<RolePermissionRow
|
||||
title={permission.title}
|
||||
formName={permission.formName}
|
||||
control={control}
|
||||
setValue={setValue}
|
||||
key={`org-role-${roleId}-permission-${permission.formName}`}
|
||||
isEditable={isCustomRole}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</TBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Table, TableContainer, TBody, Th, THead, Tr } from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import { useGetOrgRole, useUpdateOrgRole } from "@app/hooks/api";
|
||||
import {
|
||||
formRolePermission2API,
|
||||
formSchema,
|
||||
rolePermission2Form,
|
||||
TFormSchema
|
||||
} from "@app/views/Org/MembersPage/components/OrgRoleTabSection/OrgRoleModifySection/OrgRoleModifySection.utils";
|
||||
|
||||
import { RolePermissionRow } from "./RolePermissionRow";
|
||||
|
||||
const SIMPLE_PERMISSION_OPTIONS = [
|
||||
{
|
||||
title: "User management",
|
||||
formName: "member"
|
||||
},
|
||||
{
|
||||
title: "Group management",
|
||||
formName: "groups"
|
||||
},
|
||||
{
|
||||
title: "Machine identity management",
|
||||
formName: "identity"
|
||||
},
|
||||
{
|
||||
title: "Billing & usage",
|
||||
formName: "billing"
|
||||
},
|
||||
{
|
||||
title: "Role management",
|
||||
formName: "role"
|
||||
},
|
||||
{
|
||||
title: "Incident Contacts",
|
||||
formName: "incident-contact"
|
||||
},
|
||||
{
|
||||
title: "Organization profile",
|
||||
formName: "settings"
|
||||
},
|
||||
{
|
||||
title: "Secret Scanning",
|
||||
formName: "secret-scanning"
|
||||
},
|
||||
{
|
||||
title: "SSO",
|
||||
formName: "sso"
|
||||
},
|
||||
{
|
||||
title: "LDAP",
|
||||
formName: "ldap"
|
||||
},
|
||||
{
|
||||
title: "SCIM",
|
||||
formName: "scim"
|
||||
}
|
||||
] as const;
|
||||
|
||||
type Props = {
|
||||
roleId: string;
|
||||
};
|
||||
|
||||
export const RolePermissionsTable = ({ roleId }: Props) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const orgId = currentOrg?.id || "";
|
||||
|
||||
const { data: role } = useGetOrgRole(orgId, roleId);
|
||||
|
||||
const { setValue, control, handleSubmit } = useForm<TFormSchema>({
|
||||
defaultValues: role ? { ...role, permissions: rolePermission2Form(role.permissions) } : {},
|
||||
resolver: zodResolver(formSchema)
|
||||
});
|
||||
|
||||
const { mutateAsync: updateRole } = useUpdateOrgRole();
|
||||
|
||||
const onSubmit = async (el: TFormSchema) => {
|
||||
try {
|
||||
await updateRole({
|
||||
orgId,
|
||||
id: roleId,
|
||||
...el,
|
||||
permissions: formRolePermission2API(el.permissions)
|
||||
});
|
||||
createNotification({ type: "success", text: "Successfully updated role" });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
createNotification({ type: "error", text: "Failed to update role" });
|
||||
}
|
||||
};
|
||||
|
||||
const isCustomRole = !["admin", "member", "no-access"].includes(role?.slug ?? "");
|
||||
|
||||
return (
|
||||
<TableContainer>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
<Th className="w-5" />
|
||||
<Th>Resource</Th>
|
||||
<Th>Permission</Th>
|
||||
</Tr>
|
||||
</THead>
|
||||
<TBody>
|
||||
{SIMPLE_PERMISSION_OPTIONS.map((permission) => {
|
||||
return (
|
||||
<RolePermissionRow
|
||||
title={permission.title}
|
||||
formName={permission.formName}
|
||||
control={control}
|
||||
setValue={setValue}
|
||||
handleSubmit={handleSubmit(onSubmit)}
|
||||
key={`org-role-${roleId}-permission-${permission.formName}`}
|
||||
isEditable={isCustomRole}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</TBody>
|
||||
</Table>
|
||||
</form>
|
||||
</TableContainer>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user