mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-10 15:28:42 +00:00
Rename group fns and add upgrade plan modal to project level groups tab
This commit is contained in:
@@ -18,11 +18,11 @@ import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-p
|
|||||||
import { TPermissionServiceFactory } from "../permission/permission-service";
|
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||||
import { TGroupDALFactory } from "./group-dal";
|
import { TGroupDALFactory } from "./group-dal";
|
||||||
import {
|
import {
|
||||||
|
TAddUserToGroupDTO,
|
||||||
TCreateGroupDTO,
|
TCreateGroupDTO,
|
||||||
TCreateGroupUserMembershipDTO,
|
|
||||||
TDeleteGroupDTO,
|
TDeleteGroupDTO,
|
||||||
TDeleteGroupUserMembershipDTO,
|
TListGroupUsersDTO,
|
||||||
TGetGroupUserMembershipsDTO,
|
TRemoveUserFromGroupDTO,
|
||||||
TUpdateGroupDTO
|
TUpdateGroupDTO
|
||||||
} from "./group-types";
|
} from "./group-types";
|
||||||
import { TUserGroupMembershipDALFactory } from "./user-group-membership-dal";
|
import { TUserGroupMembershipDALFactory } from "./user-group-membership-dal";
|
||||||
@@ -185,13 +185,7 @@ export const groupServiceFactory = ({
|
|||||||
return group;
|
return group;
|
||||||
};
|
};
|
||||||
|
|
||||||
const listGroupUsers = async ({
|
const listGroupUsers = async ({ groupSlug, actor, actorId, actorAuthMethod, actorOrgId }: TListGroupUsersDTO) => {
|
||||||
groupSlug,
|
|
||||||
actor,
|
|
||||||
actorId,
|
|
||||||
actorAuthMethod,
|
|
||||||
actorOrgId
|
|
||||||
}: TGetGroupUserMembershipsDTO) => {
|
|
||||||
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
||||||
|
|
||||||
const { permission } = await permissionService.getOrgPermission(
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
@@ -224,7 +218,7 @@ export const groupServiceFactory = ({
|
|||||||
actorId,
|
actorId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
}: TCreateGroupUserMembershipDTO) => {
|
}: TAddUserToGroupDTO) => {
|
||||||
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
||||||
|
|
||||||
const { permission } = await permissionService.getOrgPermission(
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
@@ -368,7 +362,7 @@ export const groupServiceFactory = ({
|
|||||||
actorId,
|
actorId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId
|
actorOrgId
|
||||||
}: TDeleteGroupUserMembershipDTO) => {
|
}: TRemoveUserFromGroupDTO) => {
|
||||||
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
if (!actorOrgId) throw new BadRequestError({ message: "Failed to create group without organization" });
|
||||||
|
|
||||||
const { permission } = await permissionService.getOrgPermission(
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
|||||||
@@ -19,16 +19,16 @@ export type TDeleteGroupDTO = {
|
|||||||
groupSlug: string;
|
groupSlug: string;
|
||||||
} & TGenericPermission;
|
} & TGenericPermission;
|
||||||
|
|
||||||
export type TGetGroupUserMembershipsDTO = {
|
export type TListGroupUsersDTO = {
|
||||||
groupSlug: string;
|
groupSlug: string;
|
||||||
} & TGenericPermission;
|
} & TGenericPermission;
|
||||||
|
|
||||||
export type TCreateGroupUserMembershipDTO = {
|
export type TAddUserToGroupDTO = {
|
||||||
groupSlug: string;
|
groupSlug: string;
|
||||||
username: string;
|
username: string;
|
||||||
} & TGenericPermission;
|
} & TGenericPermission;
|
||||||
|
|
||||||
export type TDeleteGroupUserMembershipDTO = {
|
export type TRemoveUserFromGroupDTO = {
|
||||||
groupSlug: string;
|
groupSlug: string;
|
||||||
username: string;
|
username: string;
|
||||||
} & TGenericPermission;
|
} & TGenericPermission;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
export {
|
export {
|
||||||
|
useAddUserToGroup,
|
||||||
useCreateGroup,
|
useCreateGroup,
|
||||||
useCreateGroupUserMembership,
|
|
||||||
useDeleteGroup,
|
useDeleteGroup,
|
||||||
useDeleteGroupUserMembership,
|
useRemoveUserFromGroup,
|
||||||
useUpdateGroup} from "./mutations";
|
useUpdateGroup} from "./mutations";
|
||||||
export {
|
export {
|
||||||
useGetGroupUserMemberships
|
useListGroupUsers
|
||||||
} from "./queries";
|
} from "./queries";
|
||||||
@@ -85,7 +85,7 @@ export const useDeleteGroup = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useCreateGroupUserMembership = () => {
|
export const useAddUserToGroup = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({
|
||||||
@@ -107,7 +107,7 @@ export const useCreateGroupUserMembership = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useDeleteGroupUserMembership = () => {
|
export const useRemoveUserFromGroup = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({
|
mutationFn: async ({
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type TUser = {
|
|||||||
isPartOfGroup: boolean;
|
isPartOfGroup: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useGetGroupUserMemberships = (groupSlug: string) => {
|
export const useListGroupUsers = (groupSlug: string) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: groupKeys.getGroupUserMembership(groupSlug),
|
queryKey: groupKeys.getGroupUserMembership(groupSlug),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ export {
|
|||||||
useGetUserWorkspaces,
|
useGetUserWorkspaces,
|
||||||
useGetWorkspaceAuthorizations,
|
useGetWorkspaceAuthorizations,
|
||||||
useGetWorkspaceById,
|
useGetWorkspaceById,
|
||||||
useGetWorkspaceGroupMemberships,
|
|
||||||
useGetWorkspaceIdentityMemberships,
|
useGetWorkspaceIdentityMemberships,
|
||||||
useGetWorkspaceIndexStatus,
|
useGetWorkspaceIndexStatus,
|
||||||
useGetWorkspaceIntegrations,
|
useGetWorkspaceIntegrations,
|
||||||
useGetWorkspaceSecrets,
|
useGetWorkspaceSecrets,
|
||||||
useGetWorkspaceUsers,
|
useGetWorkspaceUsers,
|
||||||
|
useListWorkspaceGroups,
|
||||||
useNameWorkspaceSecrets,
|
useNameWorkspaceSecrets,
|
||||||
useRenameWorkspace,
|
useRenameWorkspace,
|
||||||
useToggleAutoCapitalization,
|
useToggleAutoCapitalization,
|
||||||
|
|||||||
@@ -526,7 +526,7 @@ export const useDeleteGroupFromWorkspace = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useGetWorkspaceGroupMemberships = (projectSlug: string) => {
|
export const useListWorkspaceGroups = (projectSlug: string) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: workspaceKeys.getWorkspaceGroupMemberships(projectSlug),
|
queryKey: workspaceKeys.getWorkspaceGroupMemberships(projectSlug),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
|
|||||||
+6
-6
@@ -24,9 +24,9 @@ import {
|
|||||||
OrgPermissionSubjects
|
OrgPermissionSubjects
|
||||||
} from "@app/context";
|
} from "@app/context";
|
||||||
import {
|
import {
|
||||||
useCreateGroupUserMembership,
|
useAddUserToGroup,
|
||||||
useDeleteGroupUserMembership,
|
useListGroupUsers,
|
||||||
useGetGroupUserMemberships} from "@app/hooks/api";
|
useRemoveUserFromGroup} from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -44,9 +44,9 @@ export const OrgGroupMembersModal = ({
|
|||||||
slug: string;
|
slug: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const { data: users, isLoading } = useGetGroupUserMemberships(popUpData?.slug ?? "");
|
const { data: users, isLoading } = useListGroupUsers(popUpData?.slug ?? "");
|
||||||
const { mutateAsync: assignMutateAsync } = useCreateGroupUserMembership();
|
const { mutateAsync: assignMutateAsync } = useAddUserToGroup();
|
||||||
const { mutateAsync: unassignMutateAsync } = useDeleteGroupUserMembership();
|
const { mutateAsync: unassignMutateAsync } = useRemoveUserFromGroup();
|
||||||
|
|
||||||
const handleAssignment = async (username: string, assign: boolean) => {
|
const handleAssignment = async (username: string, assign: boolean) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
+10
-14
@@ -1,8 +1,8 @@
|
|||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import * as yup from "yup";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import {
|
import {
|
||||||
@@ -17,20 +17,16 @@ import {
|
|||||||
useAddGroupToWorkspace,
|
useAddGroupToWorkspace,
|
||||||
useGetOrganizationGroups,
|
useGetOrganizationGroups,
|
||||||
useGetProjectRoles,
|
useGetProjectRoles,
|
||||||
useGetWorkspaceGroupMemberships,
|
useListWorkspaceGroups,
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
// TODO: change this to zod
|
const schema = z.object({
|
||||||
|
slug: z.string(),
|
||||||
|
role: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
const schema = yup
|
export type FormData = z.infer<typeof schema>;
|
||||||
.object({
|
|
||||||
slug: yup.string().required("Group slug is required"),
|
|
||||||
role: yup.string()
|
|
||||||
})
|
|
||||||
.required();
|
|
||||||
|
|
||||||
export type FormData = yup.InferType<typeof schema>;
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
popUp: UsePopUpState<["group"]>;
|
popUp: UsePopUpState<["group"]>;
|
||||||
@@ -48,7 +44,7 @@ export const GroupModal = ({
|
|||||||
const workspaceId = currentWorkspace?.id || "";
|
const workspaceId = currentWorkspace?.id || "";
|
||||||
|
|
||||||
const { data: groups } = useGetOrganizationGroups(orgId);
|
const { data: groups } = useGetOrganizationGroups(orgId);
|
||||||
const { data: groupMemberships } = useGetWorkspaceGroupMemberships(currentWorkspace?.slug || "");
|
const { data: groupMemberships } = useListWorkspaceGroups(currentWorkspace?.slug || "");
|
||||||
|
|
||||||
const { data: roles } = useGetProjectRoles(workspaceId);
|
const { data: roles } = useGetProjectRoles(workspaceId);
|
||||||
|
|
||||||
@@ -70,7 +66,7 @@ export const GroupModal = ({
|
|||||||
reset,
|
reset,
|
||||||
formState: { isSubmitting }
|
formState: { isSubmitting }
|
||||||
} = useForm<FormData>({
|
} = useForm<FormData>({
|
||||||
resolver: yupResolver(schema)
|
resolver: zodResolver(schema)
|
||||||
});
|
});
|
||||||
|
|
||||||
const onFormSubmit = async ({ slug, role }: FormData) => {
|
const onFormSubmit = async ({ slug, role }: FormData) => {
|
||||||
|
|||||||
+20
-3
@@ -5,9 +5,10 @@ import { createNotification } from "@app/components/notifications";
|
|||||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
DeleteActionModal
|
DeleteActionModal,
|
||||||
|
UpgradePlanModal
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub,useWorkspace } from "@app/context";
|
import { ProjectPermissionActions, ProjectPermissionSub, useSubscription,useWorkspace } from "@app/context";
|
||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import { useDeleteGroupFromWorkspace } from "@app/hooks/api";
|
import { useDeleteGroupFromWorkspace } from "@app/hooks/api";
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ import { GroupModal } from "./GroupModal";
|
|||||||
import { GroupTable } from "./GroupsTable";
|
import { GroupTable } from "./GroupsTable";
|
||||||
|
|
||||||
export const GroupsSection = () => {
|
export const GroupsSection = () => {
|
||||||
|
const { subscription } = useSubscription();
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
|
|
||||||
const { mutateAsync: deleteMutateAsync } = useDeleteGroupFromWorkspace();
|
const { mutateAsync: deleteMutateAsync } = useDeleteGroupFromWorkspace();
|
||||||
@@ -25,6 +27,16 @@ export const GroupsSection = () => {
|
|||||||
"upgradePlan"
|
"upgradePlan"
|
||||||
] as const);
|
] as const);
|
||||||
|
|
||||||
|
const handleAddGroupModal = () => {
|
||||||
|
if (!subscription?.groups) {
|
||||||
|
handlePopUpOpen("upgradePlan", {
|
||||||
|
description: "You can manage users more efficiently with groups if you upgrade your Infisical plan."
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
handlePopUpOpen("group");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const onRemoveGroupSubmit = async (groupSlug: string) => {
|
const onRemoveGroupSubmit = async (groupSlug: string) => {
|
||||||
try {
|
try {
|
||||||
await deleteMutateAsync({
|
await deleteMutateAsync({
|
||||||
@@ -60,7 +72,7 @@ export const GroupsSection = () => {
|
|||||||
colorSchema="primary"
|
colorSchema="primary"
|
||||||
type="submit"
|
type="submit"
|
||||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||||
onClick={() => handlePopUpOpen("group")}
|
onClick={() => handleAddGroupModal()}
|
||||||
isDisabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
>
|
>
|
||||||
Add Group
|
Add Group
|
||||||
@@ -83,6 +95,11 @@ export const GroupsSection = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<UpgradePlanModal
|
||||||
|
isOpen={popUp.upgradePlan.isOpen}
|
||||||
|
onOpenChange={(isOpen) => handlePopUpToggle("upgradePlan", isOpen)}
|
||||||
|
text={(popUp.upgradePlan?.data as { description: string })?.description}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
+2
-2
@@ -16,7 +16,7 @@ import {
|
|||||||
Tr
|
Tr
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||||
import { useGetWorkspaceGroupMemberships } from "@app/hooks/api";
|
import { useListWorkspaceGroups } from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
import { GroupRoles } from "./GroupRoles";
|
import { GroupRoles } from "./GroupRoles";
|
||||||
@@ -33,7 +33,7 @@ type Props = {
|
|||||||
|
|
||||||
export const GroupTable = ({ handlePopUpOpen }: Props) => {
|
export const GroupTable = ({ handlePopUpOpen }: Props) => {
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const { data, isLoading } = useGetWorkspaceGroupMemberships(currentWorkspace?.slug || "");
|
const { data, isLoading } = useListWorkspaceGroups(currentWorkspace?.slug || "");
|
||||||
return (
|
return (
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<Table>
|
<Table>
|
||||||
|
|||||||
Reference in New Issue
Block a user