diff --git a/frontend/src/hooks/api/users/index.tsx b/frontend/src/hooks/api/users/index.tsx index fb4c2d1ce..ab14892a3 100644 --- a/frontend/src/hooks/api/users/index.tsx +++ b/frontend/src/hooks/api/users/index.tsx @@ -29,3 +29,4 @@ export { useUpdateOrgMembership, useUpdateUserAuthMethods } from "./queries"; +export { userKeys } from "./query-keys"; diff --git a/frontend/src/hooks/api/users/mutation.tsx b/frontend/src/hooks/api/users/mutation.tsx index 9ee16415d..d4092baf4 100644 --- a/frontend/src/hooks/api/users/mutation.tsx +++ b/frontend/src/hooks/api/users/mutation.tsx @@ -6,8 +6,8 @@ import { } from "@app/components/utilities/cryptography/crypto"; import { apiRequest } from "@app/config/request"; -import { workspaceKeys } from "../workspace/queries"; -import { userKeys } from "./queries"; +import { workspaceKeys } from "../workspace"; +import { userKeys } from "./query-keys"; import { AddUserToWsDTOE2EE, AddUserToWsDTONonE2EE } from "./types"; export const useAddUserToWsE2EE = () => { diff --git a/frontend/src/hooks/api/users/queries.tsx b/frontend/src/hooks/api/users/queries.tsx index 27878f624..fc5243510 100644 --- a/frontend/src/hooks/api/users/queries.tsx +++ b/frontend/src/hooks/api/users/queries.tsx @@ -6,6 +6,8 @@ import { setAuthToken } from "@app/reactQuery"; import { APIKeyDataV2 } from "../apiKeys/types"; import { TGroupWithProjectMemberships } from "../groups/types"; +import { workspaceKeys } from "../workspace"; +import { userKeys } from "./query-keys"; import { AddUserToOrgDTO, APIKeyData, @@ -21,29 +23,6 @@ import { UserEnc } from "./types"; -export const userKeys = { - getUser: ["user"] as const, - getPrivateKey: ["user"] as const, - userAction: ["user-action"] as const, - userProjectFavorites: (orgId: string) => [{ orgId }, "user-project-favorites"] as const, - getOrgMembership: (orgId: string, orgMembershipId: string) => - [{ orgId, orgMembershipId }, "org-membership"] as const, - allOrgMembershipProjectMemberships: (orgId: string) => [orgId, "all-user-memberships"] as const, - forOrgMembershipProjectMemberships: (orgId: string, orgMembershipId: string) => - [...userKeys.allOrgMembershipProjectMemberships(orgId), { orgMembershipId }] as const, - getOrgMembershipProjectMemberships: (orgId: string, username: string) => - [{ orgId, username }, "org-membership-project-memberships"] as const, - getOrgUsers: (orgId: string) => [{ orgId }, "user"], - myIp: ["ip"] as const, - myAPIKeys: ["api-keys"] as const, - myAPIKeysV2: ["api-keys-v2"] as const, - mySessions: ["sessions"] as const, - listUsers: ["user-list"] as const, - listUserGroupMemberships: (username: string) => ["user-group-memberships", username] as const, - - myOrganizationProjects: (orgId: string) => [{ orgId }, "organization-projects"] as const -}; - export const fetchUserDetails = async () => { const { data } = await apiRequest.get<{ user: User & UserEnc }>("/api/v1/user"); @@ -175,8 +154,15 @@ export const useAddUsersToOrg = () => { mutationFn: (dto) => { return apiRequest.post("/api/v1/invite-org/signup", dto); }, - onSuccess: (_, { organizationId }) => { + onSuccess: (_, { organizationId, projects }) => { queryClient.invalidateQueries(userKeys.getOrgUsers(organizationId)); + + projects?.forEach((project) => { + if (project.slug) { + queryClient.invalidateQueries(workspaceKeys.getWorkspaceGroupMemberships(project.slug)); + } + queryClient.invalidateQueries(workspaceKeys.getWorkspaceUsers(project.id)); + }); } }); }; diff --git a/frontend/src/hooks/api/users/query-keys.tsx b/frontend/src/hooks/api/users/query-keys.tsx new file mode 100644 index 000000000..8603364b2 --- /dev/null +++ b/frontend/src/hooks/api/users/query-keys.tsx @@ -0,0 +1,21 @@ +export const userKeys = { + getUser: ["user"] as const, + getPrivateKey: ["user"] as const, + userAction: ["user-action"] as const, + userProjectFavorites: (orgId: string) => [{ orgId }, "user-project-favorites"] as const, + getOrgMembership: (orgId: string, orgMembershipId: string) => + [{ orgId, orgMembershipId }, "org-membership"] as const, + allOrgMembershipProjectMemberships: (orgId: string) => [orgId, "all-user-memberships"] as const, + forOrgMembershipProjectMemberships: (orgId: string, orgMembershipId: string) => + [...userKeys.allOrgMembershipProjectMemberships(orgId), { orgMembershipId }] as const, + getOrgMembershipProjectMemberships: (orgId: string, username: string) => + [{ orgId, username }, "org-membership-project-memberships"] as const, + getOrgUsers: (orgId: string) => [{ orgId }, "user"], + myIp: ["ip"] as const, + myAPIKeys: ["api-keys"] as const, + myAPIKeysV2: ["api-keys-v2"] as const, + mySessions: ["sessions"] as const, + listUsers: ["user-list"] as const, + listUserGroupMemberships: (username: string) => [{ username }, "user-group-memberships"] as const, + myOrganizationProjects: (orgId: string) => [{ orgId }, "organization-projects"] as const +}; diff --git a/frontend/src/hooks/api/users/types.ts b/frontend/src/hooks/api/users/types.ts index 048dd3d63..c96e3d735 100644 --- a/frontend/src/hooks/api/users/types.ts +++ b/frontend/src/hooks/api/users/types.ts @@ -151,9 +151,11 @@ export type DeletOrgMembershipDTO = { export type AddUserToOrgDTO = { inviteeEmails: string[]; - projects?: { id: string; projectRoleSlug: string[] }[]; organizationRoleSlug: string; organizationId: string; + + // We need the slug in order to invalidate the groups query. `slug` is only used for invalidation purposes. + projects?: { id: string; slug?: string; projectRoleSlug: string[] }[]; }; export type CreateAPIKeyRes = { diff --git a/frontend/src/hooks/api/workspace/index.tsx b/frontend/src/hooks/api/workspace/index.tsx index e3c886258..454560e88 100644 --- a/frontend/src/hooks/api/workspace/index.tsx +++ b/frontend/src/hooks/api/workspace/index.tsx @@ -38,3 +38,4 @@ export { useUpdateWsEnvironment, useUpgradeProject } from "./queries"; +export { workspaceKeys } from "./query-keys"; diff --git a/frontend/src/hooks/api/workspace/mutations.tsx b/frontend/src/hooks/api/workspace/mutations.tsx index 5ac54a089..a09d47e15 100644 --- a/frontend/src/hooks/api/workspace/mutations.tsx +++ b/frontend/src/hooks/api/workspace/mutations.tsx @@ -2,8 +2,8 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { apiRequest } from "@app/config/request"; -import { userKeys } from "../users/queries"; -import { workspaceKeys } from "./queries"; +import { userKeys } from "../users/query-keys"; +import { workspaceKeys } from "./query-keys"; import { TUpdateWorkspaceGroupRoleDTO } from "./types"; export const useAddGroupToWorkspace = () => { diff --git a/frontend/src/hooks/api/workspace/queries.tsx b/frontend/src/hooks/api/workspace/queries.tsx index 0557e5f6f..bdfc5fba9 100644 --- a/frontend/src/hooks/api/workspace/queries.tsx +++ b/frontend/src/hooks/api/workspace/queries.tsx @@ -14,9 +14,10 @@ import { TIntegration } from "../integrations/types"; import { TPkiAlert } from "../pkiAlerts/types"; import { TPkiCollection } from "../pkiCollections/types"; import { EncryptedSecret } from "../secrets/types"; -import { userKeys } from "../users/queries"; +import { userKeys } from "../users/query-keys"; import { TWorkspaceUser } from "../users/types"; import { ProjectSlackConfig } from "../workflowIntegrations/types"; +import { workspaceKeys } from "./query-keys"; import { CreateEnvironmentDTO, CreateWorkspaceDTO, @@ -34,49 +35,6 @@ import { Workspace } from "./types"; -export const workspaceKeys = { - getWorkspaceById: (workspaceId: string) => [{ workspaceId }, "workspace"] as const, - getWorkspaceSecrets: (workspaceId: string) => [{ workspaceId }, "workspace-secrets"] as const, - getWorkspaceIndexStatus: (workspaceId: string) => - [{ workspaceId }, "workspace-index-status"] as const, - getProjectUpgradeStatus: (workspaceId: string) => [{ workspaceId }, "workspace-upgrade-status"], - getWorkspaceMemberships: (orgId: string) => [{ orgId }, "workspace-memberships"], - getWorkspaceAuthorization: (workspaceId: string) => [{ workspaceId }, "workspace-authorizations"], - getWorkspaceIntegrations: (workspaceId: string) => [{ workspaceId }, "workspace-integrations"], - getAllUserWorkspace: ["workspaces"] as const, - getWorkspaceAuditLogs: (workspaceId: string) => - [{ workspaceId }, "workspace-audit-logs"] as const, - getWorkspaceUsers: (workspaceId: string) => [{ workspaceId }, "workspace-users"] as const, - getWorkspaceIdentityMemberships: (workspaceId: string) => - [{ workspaceId }, "workspace-identity-memberships"] as const, - getWorkspaceGroupMemberships: (workspaceId: string) => - [{ workspaceId }, "workspace-groups"] as const, - getWorkspaceCas: ({ projectSlug }: { projectSlug: string }) => - [{ projectSlug }, "workspace-cas"] as const, - specificWorkspaceCas: ({ projectSlug, status }: { projectSlug: string; status?: CaStatus }) => - [...workspaceKeys.getWorkspaceCas({ projectSlug }), { status }] as const, - allWorkspaceCertificates: () => ["workspace-certificates"] as const, - forWorkspaceCertificates: (slug: string) => - [...workspaceKeys.allWorkspaceCertificates(), slug] as const, - specificWorkspaceCertificates: ({ - slug, - offset, - limit - }: { - slug: string; - offset: number; - limit: number; - }) => [...workspaceKeys.forWorkspaceCertificates(slug), { offset, limit }] as const, - getWorkspacePkiAlerts: (workspaceId: string) => - [{ workspaceId }, "workspace-pki-alerts"] as const, - getWorkspacePkiCollections: (workspaceId: string) => - [{ workspaceId }, "workspace-pki-collections"] as const, - getWorkspaceCertificateTemplates: (workspaceId: string) => - [{ workspaceId }, "workspace-certificate-templates"] as const, - getWorkspaceSlackConfig: (workspaceId: string) => - [{ workspaceId }, "workspace-slack-config"] as const -}; - const fetchWorkspaceById = async (workspaceId: string) => { const { data } = await apiRequest.get<{ workspace: Workspace }>( `/api/v1/workspace/${workspaceId}` diff --git a/frontend/src/hooks/api/workspace/query-keys.tsx b/frontend/src/hooks/api/workspace/query-keys.tsx new file mode 100644 index 000000000..f9ec3803e --- /dev/null +++ b/frontend/src/hooks/api/workspace/query-keys.tsx @@ -0,0 +1,44 @@ +import type { CaStatus } from "../ca"; + +export const workspaceKeys = { + getWorkspaceById: (workspaceId: string) => [{ workspaceId }, "workspace"] as const, + getWorkspaceSecrets: (workspaceId: string) => [{ workspaceId }, "workspace-secrets"] as const, + getWorkspaceIndexStatus: (workspaceId: string) => + [{ workspaceId }, "workspace-index-status"] as const, + getProjectUpgradeStatus: (workspaceId: string) => [{ workspaceId }, "workspace-upgrade-status"], + getWorkspaceMemberships: (orgId: string) => [{ orgId }, "workspace-memberships"], + getWorkspaceAuthorization: (workspaceId: string) => [{ workspaceId }, "workspace-authorizations"], + getWorkspaceIntegrations: (workspaceId: string) => [{ workspaceId }, "workspace-integrations"], + getAllUserWorkspace: ["workspaces"] as const, + getWorkspaceAuditLogs: (workspaceId: string) => + [{ workspaceId }, "workspace-audit-logs"] as const, + getWorkspaceUsers: (workspaceId: string) => [{ workspaceId }, "workspace-users"] as const, + getWorkspaceIdentityMemberships: (workspaceId: string) => + [{ workspaceId }, "workspace-identity-memberships"] as const, + getWorkspaceGroupMemberships: (workspaceId: string) => + [{ workspaceId }, "workspace-groups"] as const, + getWorkspaceCas: ({ projectSlug }: { projectSlug: string }) => + [{ projectSlug }, "workspace-cas"] as const, + specificWorkspaceCas: ({ projectSlug, status }: { projectSlug: string; status?: CaStatus }) => + [...workspaceKeys.getWorkspaceCas({ projectSlug }), { status }] as const, + allWorkspaceCertificates: () => ["workspace-certificates"] as const, + forWorkspaceCertificates: (slug: string) => + [...workspaceKeys.allWorkspaceCertificates(), slug] as const, + specificWorkspaceCertificates: ({ + slug, + offset, + limit + }: { + slug: string; + offset: number; + limit: number; + }) => [...workspaceKeys.forWorkspaceCertificates(slug), { offset, limit }] as const, + getWorkspacePkiAlerts: (workspaceId: string) => + [{ workspaceId }, "workspace-pki-alerts"] as const, + getWorkspacePkiCollections: (workspaceId: string) => + [{ workspaceId }, "workspace-pki-collections"] as const, + getWorkspaceCertificateTemplates: (workspaceId: string) => + [{ workspaceId }, "workspace-certificate-templates"] as const, + getWorkspaceSlackConfig: (workspaceId: string) => + [{ workspaceId }, "workspace-slack-config"] as const +};