diff --git a/frontend/src/hooks/api/types.ts b/frontend/src/hooks/api/types.ts index 04d215898..6748db6ac 100644 --- a/frontend/src/hooks/api/types.ts +++ b/frontend/src/hooks/api/types.ts @@ -22,7 +22,7 @@ export * from "./secrets/types"; export type { CreateServiceTokenDTO, ServiceToken } from "./serviceTokens/types"; export type { SubscriptionPlan } from "./subscriptions/types"; export type { WsTag } from "./tags/types"; -export type { AddUserToWsDTO, OrgUser, TWorkspaceUser, User, UserEnc } from "./users/types"; +export type { AddUserToWsDTOE2EE, OrgUser, TWorkspaceUser, User, UserEnc } from "./users/types"; export type { TWebhook } from "./webhooks/types"; export type { CreateEnvironmentDTO, diff --git a/frontend/src/hooks/api/users/index.tsx b/frontend/src/hooks/api/users/index.tsx index 75dd36cc5..9c51948f2 100644 --- a/frontend/src/hooks/api/users/index.tsx +++ b/frontend/src/hooks/api/users/index.tsx @@ -1,4 +1,4 @@ -export { useAddUserToWs } from "./mutation"; +export { useAddUserToWsE2EE, useAddUserToWsNonE2EE } from "./mutation"; export { fetchOrgUsers, useAddUserToOrg, diff --git a/frontend/src/hooks/api/users/mutation.tsx b/frontend/src/hooks/api/users/mutation.tsx index 03276c2ef..f7c0e1558 100644 --- a/frontend/src/hooks/api/users/mutation.tsx +++ b/frontend/src/hooks/api/users/mutation.tsx @@ -7,12 +7,12 @@ import { import { apiRequest } from "@app/config/request"; import { workspaceKeys } from "../workspace/queries"; -import { AddUserToWsDTO } from "./types"; +import { AddUserToWsDTOE2EE, AddUserToWsDTONonE2EE } from "./types"; -export const useAddUserToWs = () => { +export const useAddUserToWsE2EE = () => { const queryClient = useQueryClient(); - return useMutation<{}, {}, AddUserToWsDTO>({ + return useMutation<{}, {}, AddUserToWsDTOE2EE>({ mutationFn: async ({ workspaceId, members, decryptKey, userPrivateKey }) => { // assymmetrically decrypt symmetric key with local private key const key = decryptAssymmetric({ @@ -45,3 +45,19 @@ export const useAddUserToWs = () => { } }); }; + +export const useAddUserToWsNonE2EE = () => { + const queryClient = useQueryClient(); + + return useMutation<{}, {}, AddUserToWsDTONonE2EE>({ + mutationFn: async ({ projectId, emails }) => { + const { data } = await apiRequest.post(`/api/v3/projects/${projectId}/memberships`, { + emails + }); + return data; + }, + onSuccess: (_, { projectId }) => { + queryClient.invalidateQueries(workspaceKeys.getWorkspaceUsers(projectId)); + } + }); +}; diff --git a/frontend/src/hooks/api/users/types.ts b/frontend/src/hooks/api/users/types.ts index ebddefb14..366ee93bf 100644 --- a/frontend/src/hooks/api/users/types.ts +++ b/frontend/src/hooks/api/users/types.ts @@ -63,7 +63,7 @@ export type TProjectMembership = { export type TWorkspaceUser = OrgUser; -export type AddUserToWsDTO = { +export type AddUserToWsDTOE2EE = { workspaceId: string; decryptKey: UserWsKeyPair; userPrivateKey: string; @@ -73,6 +73,11 @@ export type AddUserToWsDTO = { }[]; }; +export type AddUserToWsDTONonE2EE = { + projectId: string; + emails: string[]; +}; + export type UpdateOrgUserRoleDTO = { organizationId: string; membershipId: string; diff --git a/frontend/src/hooks/api/workspace/queries.tsx b/frontend/src/hooks/api/workspace/queries.tsx index 89a436df2..38879de9d 100644 --- a/frontend/src/hooks/api/workspace/queries.tsx +++ b/frontend/src/hooks/api/workspace/queries.tsx @@ -158,21 +158,19 @@ export const useGetWorkspaceIntegrations = (workspaceId: string) => export const createWorkspace = ({ organizationId, - projectName, - inviteAllOrgMembers -}: CreateWorkspaceDTO): Promise<{ data: { workspace: Workspace } }> => { - return apiRequest.post("/api/v3/projects", { projectName, inviteAllOrgMembers, organizationId }); + projectName +}: CreateWorkspaceDTO): Promise<{ data: { project: Workspace } }> => { + return apiRequest.post("/api/v3/projects", { projectName, organizationId }); }; export const useCreateWorkspace = () => { const queryClient = useQueryClient(); - return useMutation<{ data: { workspace: Workspace } }, {}, CreateWorkspaceDTO>({ - mutationFn: async ({ organizationId, projectName, inviteAllOrgMembers }) => + return useMutation<{ data: { project: Workspace } }, {}, CreateWorkspaceDTO>({ + mutationFn: async ({ organizationId, projectName }) => createWorkspace({ organizationId, - projectName, - inviteAllOrgMembers + projectName }), onSuccess: () => { queryClient.invalidateQueries(workspaceKeys.getAllUserWorkspace); @@ -287,11 +285,13 @@ export const useAddUserToWorkspace = () => { return useMutation({ mutationFn: async ({ email, workspaceId }: { email: string; workspaceId: string }) => { const { - data: { invitee, latestKey } - } = await apiRequest.post(`/api/v1/workspace/${workspaceId}/invite-signup`, { email }); + data: { invitees, latestKey } + } = await apiRequest.post(`/api/v1/workspace/${workspaceId}/invite-signup`, { + emails: [email] + }); return { - invitee, + invitees, latestKey }; }, diff --git a/frontend/src/hooks/api/workspace/types.ts b/frontend/src/hooks/api/workspace/types.ts index 3538e761b..8b825d062 100644 --- a/frontend/src/hooks/api/workspace/types.ts +++ b/frontend/src/hooks/api/workspace/types.ts @@ -3,6 +3,7 @@ export type Workspace = { id: string; name: string; orgId: string; + e2ee: boolean; autoCapitalization: boolean; environments: WorkspaceEnv[]; }; @@ -26,7 +27,6 @@ export type NameWorkspaceSecretsDTO = { // mutation dto export type CreateWorkspaceDTO = { projectName: string; - inviteAllOrgMembers: boolean; organizationId: string; }; diff --git a/frontend/src/layouts/AppLayout/AppLayout.tsx b/frontend/src/layouts/AppLayout/AppLayout.tsx index d175afe48..6f9d80e6b 100644 --- a/frontend/src/layouts/AppLayout/AppLayout.tsx +++ b/frontend/src/layouts/AppLayout/AppLayout.tsx @@ -62,7 +62,7 @@ import { import { usePopUp } from "@app/hooks"; import { fetchOrgUsers, - useAddUserToWs, + useAddUserToWsE2EE, useCreateWorkspace, useGetOrgTrialUrl, useGetSecretApprovalRequestCount, @@ -130,7 +130,7 @@ export const AppLayout = ({ children }: LayoutProps) => { const createWs = useCreateWorkspace(); const uploadWsKey = useUploadWsKey(); - const addWsUser = useAddUserToWs(); + const addWsUser = useAddUserToWsE2EE(); const infisicalPlatformVersion = process.env.NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION; const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ @@ -224,11 +224,11 @@ export const AppLayout = ({ children }: LayoutProps) => { try { const { data: { - workspace: { id: newWorkspaceId } + project: { id: newWorkspaceId } } } = await createWs.mutateAsync({ organizationId: currentOrg?.id, - workspaceName: name + projectName: name }); const randomBytes = crypto.randomBytes(16).toString("hex"); diff --git a/frontend/src/pages/org/[id]/overview/index.tsx b/frontend/src/pages/org/[id]/overview/index.tsx index ae1bf4b3d..56cf50af6 100644 --- a/frontend/src/pages/org/[id]/overview/index.tsx +++ b/frontend/src/pages/org/[id]/overview/index.tsx @@ -53,7 +53,7 @@ import { // fetchOrgUsers, // useAddUserToWs, useCreateWorkspace, - useRegisterUserAction, + useRegisterUserAction } from "@app/hooks/api"; // import { fetchUserWsKey } from "@app/hooks/api/keys/queries"; import { useFetchServerStatus } from "@app/hooks/api/serverDetails"; @@ -471,7 +471,7 @@ const OrganizationPage = withPermission( const currentOrg = String(router.query.id); const orgWorkspaces = workspaces?.filter((workspace) => workspace.orgId === currentOrg) || []; const { createNotification } = useNotificationContext(); - // const addWsUser = useAddUserToWs(); + // const addWsUser = useAddUserToWs(); const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ "addNewWs", @@ -501,35 +501,32 @@ const OrganizationPage = withPermission( try { const { data: { - workspace: { id: newWorkspaceId } + project: { id: newWorkspaceId } } } = await createWs.mutateAsync({ organizationId: currentOrg, - inviteAllOrgMembers: addMembers, projectName: name }); - /* if (addMembers) { // not using hooks because need at this point only - const orgUsers = await fetchOrgUsers(currentOrg); - const decryptKey = await fetchUserWsKey(newWorkspaceId); - - await addWsUser.mutateAsync({ - workspaceId: newWorkspaceId, - decryptKey, - userPrivateKey: PRIVATE_KEY, - members: orgUsers - .filter( - ({ status, user: orgUser }) => status === "accepted" && user.email !== orgUser.email - ) - .map(({ user: orgUser, id: orgMembershipId }) => ({ - userPublicKey: orgUser.publicKey, - orgMembershipId - })) - }); + // const orgUsers = await fetchOrgUsers(currentOrg); + // const decryptKey = await fetchUserWsKey(newWorkspaceId); + // await addWsUser.mutateAsync({ + // workspaceId: newWorkspaceId, + // decryptKey, + // userPrivateKey: PRIVATE_KEY, + // members: orgUsers + // .filter( + // ({ status, user: orgUser }) => status === "accepted" && user.email !== orgUser.email + // ) + // .map(({ user: orgUser, id: orgMembershipId }) => ({ + // userPublicKey: orgUser.publicKey, + // orgMembershipId + // })) + // }); } - */ + createNotification({ text: "Workspace created", type: "success" }); handlePopUpClose("addNewWs"); router.push(`/project/${newWorkspaceId}/secrets/overview`); diff --git a/frontend/src/views/Project/MembersPage/components/MemberListTab/MemberListTab.tsx b/frontend/src/views/Project/MembersPage/components/MemberListTab/MemberListTab.tsx index 76f97741d..838ccce19 100644 --- a/frontend/src/views/Project/MembersPage/components/MemberListTab/MemberListTab.tsx +++ b/frontend/src/views/Project/MembersPage/components/MemberListTab/MemberListTab.tsx @@ -44,7 +44,8 @@ import { } from "@app/context"; import { usePopUp } from "@app/hooks"; import { - useAddUserToWs, + useAddUserToWsE2EE, + useAddUserToWsNonE2EE, useDeleteUserFromWorkspace, useGetOrgUsers, useGetProjectRoles, @@ -95,12 +96,14 @@ export const MemberListTab = () => { formState: { isSubmitting } } = useForm({ resolver: zodResolver(addMemberFormSchema) }); - const { mutateAsync: addUserToWorkspace } = useAddUserToWs(); + const { mutateAsync: addUserToWorkspace } = useAddUserToWsE2EE(); + const { mutateAsync: addUserToWorkspaceNonE2EE } = useAddUserToWsNonE2EE(); const { mutateAsync: uploadWsKey } = useUploadWsKey(); const { mutateAsync: removeUserFromWorkspace } = useDeleteUserFromWorkspace(); const { mutateAsync: updateUserWorkspaceRole } = useUpdateUserWorkspaceRole(); const onAddMember = async ({ orgMembershipId }: TAddMemberForm) => { + if (!currentWorkspace) return; if (!currentOrg?.id) return; // TODO(akhilmhdh): Move to memory storage const userPrivateKey = localStorage.getItem("PRIVATE_KEY"); @@ -114,12 +117,19 @@ export const MemberListTab = () => { if (!orgUser) return; try { - await addUserToWorkspace({ - workspaceId, - userPrivateKey, - decryptKey: wsKey, - members: [{ orgMembershipId, userPublicKey: orgUser.user.publicKey }] - }); + if (currentWorkspace.e2ee) { + await addUserToWorkspace({ + workspaceId, + userPrivateKey, + decryptKey: wsKey, + members: [{ orgMembershipId, userPublicKey: orgUser.user.publicKey }] + }); + } else { + await addUserToWorkspaceNonE2EE({ + projectId: workspaceId, + emails: [orgUser.user.email] + }); + } createNotification({ text: "Successfully added user to the project", type: "success"