From b04030a060614ae179d27987fb5b1ba1cb4d260e Mon Sep 17 00:00:00 2001 From: Akhil Mohan Date: Thu, 18 Jan 2024 21:10:37 +0530 Subject: [PATCH] feat(infisical-pg): resolved missing integration auth api --- backend-pg/.eslintignore | 1 - .../routes/v1/integration-auth-router.ts | 40 ++++++++- .../src/server/routes/v3/secret-router.ts | 2 +- .../integration-auth-service.ts | 28 +++++- .../integration-auth-types.ts | 7 +- .../src/hooks/api/integrationAuth/queries.tsx | 87 ++++++++++--------- 6 files changed, 119 insertions(+), 46 deletions(-) diff --git a/backend-pg/.eslintignore b/backend-pg/.eslintignore index 339bd4399..c767a4a9e 100644 --- a/backend-pg/.eslintignore +++ b/backend-pg/.eslintignore @@ -1,3 +1,2 @@ -.eslintrc.js vitest-environment-infisical.ts vitest.config.ts diff --git a/backend-pg/src/server/routes/v1/integration-auth-router.ts b/backend-pg/src/server/routes/v1/integration-auth-router.ts index 92edc8c6a..1d92813f2 100644 --- a/backend-pg/src/server/routes/v1/integration-auth-router.ts +++ b/backend-pg/src/server/routes/v1/integration-auth-router.ts @@ -59,6 +59,44 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) } }); + server.route({ + url: "/", + method: "DELETE", + onRequest: verifyAuth([AuthMode.JWT]), + schema: { + querystring: z.object({ + integration: z.string().trim(), + projectId: z.string().trim() + }), + response: { + 200: z.object({ + integrationAuth: integrationAuthPubSchema.array() + }) + } + }, + handler: async (req) => { + const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuths({ + actorId: req.permission.id, + actor: req.permission.type, + integration: req.query.integration, + projectId: req.query.projectId + }); + + await server.services.auditLog.createAuditLog({ + ...req.auditLogInfo, + projectId: req.query.projectId, + event: { + type: EventType.UNAUTHORIZE_INTEGRATION, + metadata: { + integration: req.query.integration + } + } + }); + + return { integrationAuth }; + } + }); + server.route({ url: "/:integrationAuthId", method: "DELETE", @@ -74,7 +112,7 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider) } }, handler: async (req) => { - const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuth({ + const integrationAuth = await server.services.integrationAuth.deleteIntegrationAuthById({ actorId: req.permission.id, actor: req.permission.type, id: req.params.integrationAuthId diff --git a/backend-pg/src/server/routes/v3/secret-router.ts b/backend-pg/src/server/routes/v3/secret-router.ts index 064e858c6..b7d3d9584 100644 --- a/backend-pg/src/server/routes/v3/secret-router.ts +++ b/backend-pg/src/server/routes/v3/secret-router.ts @@ -155,7 +155,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => { event: { type: EventType.GET_SECRET, metadata: { - environment: req.query.environment, + environment, secretPath: req.query.secretPath, secretId: secret.id, secretKey: req.params.secretName, diff --git a/backend-pg/src/services/integration-auth/integration-auth-service.ts b/backend-pg/src/services/integration-auth/integration-auth-service.ts index 7c1c0cad7..f651fe88c 100644 --- a/backend-pg/src/services/integration-auth/integration-auth-service.ts +++ b/backend-pg/src/services/integration-auth/integration-auth-service.ts @@ -27,7 +27,8 @@ import { TIntegrationAuthDalFactory } from "./integration-auth-dal"; import { TBitbucketWorkspace, TChecklyGroups, - TDeleteIntegrationAuthDTO, + TDeleteIntegrationAuthByIdDTO, + TDeleteIntegrationAuthsDTO, TGetIntegrationAuthDTO, TGetIntegrationAuthTeamCityBuildConfigDTO, TIntegrationAuthAppsDTO, @@ -966,7 +967,27 @@ export const integrationAuthServiceFactory = ({ return []; }; - const deleteIntegrationAuth = async ({ id, actorId, actor }: TDeleteIntegrationAuthDTO) => { + const deleteIntegrationAuths = async ({ + projectId, + integration, + actor, + actorId + }: TDeleteIntegrationAuthsDTO) => { + const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId); + ForbiddenError.from(permission).throwUnlessCan( + ProjectPermissionActions.Delete, + ProjectPermissionSub.Integrations + ); + + const integrations = await integrationAuthDal.delete({ integration, projectId }); + return integrations; + }; + + const deleteIntegrationAuthById = async ({ + id, + actorId, + actor + }: TDeleteIntegrationAuthByIdDTO) => { const integrationAuth = await integrationAuthDal.findById(id); if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" }); @@ -996,7 +1017,8 @@ export const integrationAuthServiceFactory = ({ getIntegrationAuth, oauthExchange, saveIntegrationToken, - deleteIntegrationAuth, + deleteIntegrationAuthById, + deleteIntegrationAuths, getIntegrationAuthTeams, getIntegrationApps, getVercelBranches, diff --git a/backend-pg/src/services/integration-auth/integration-auth-types.ts b/backend-pg/src/services/integration-auth/integration-auth-types.ts index bd365dc03..34c5d995a 100644 --- a/backend-pg/src/services/integration-auth/integration-auth-types.ts +++ b/backend-pg/src/services/integration-auth/integration-auth-types.ts @@ -19,6 +19,11 @@ export type TSaveIntegrationAccessTokenDTO = { refreshToken?: string; } & TProjectPermission; +export type TDeleteIntegrationAuthsDTO = TProjectPermission & { + integration: string; + projectId: string; +}; + export type TIntegrationAuthAppsDTO = { id: string; teamId?: string; @@ -76,7 +81,7 @@ export type TIntegrationAuthNorthflankSecretGroupDTO = { appId: string; } & Omit; -export type TDeleteIntegrationAuthDTO = { +export type TDeleteIntegrationAuthByIdDTO = { id: string; } & Omit; diff --git a/frontend/src/hooks/api/integrationAuth/queries.tsx b/frontend/src/hooks/api/integrationAuth/queries.tsx index 21257f5ac..83dfb5d1a 100644 --- a/frontend/src/hooks/api/integrationAuth/queries.tsx +++ b/frontend/src/hooks/api/integrationAuth/queries.tsx @@ -3,16 +3,16 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { apiRequest } from "@app/config/request"; import { workspaceKeys } from "../workspace/queries"; -import { - App, - BitBucketWorkspace, - ChecklyGroup, - Environment, - IntegrationAuth, +import { + App, + BitBucketWorkspace, + ChecklyGroup, + Environment, + IntegrationAuth, NorthflankSecretGroup, Org, Project, - Service, + Service, Team, TeamCityBuildConfig } from "./types"; @@ -37,10 +37,9 @@ const integrationAuthKeys = { }: { integrationAuthId: string; accountId: string; - }) => - [{ integrationAuthId, accountId }, "integrationAuthChecklyGroups"] as const, - getIntegrationAuthQoveryOrgs: (integrationAuthId: string) => - [{ integrationAuthId }, "integrationAuthQoveryOrgs"] as const, + }) => [{ integrationAuthId, accountId }, "integrationAuthChecklyGroups"] as const, + getIntegrationAuthQoveryOrgs: (integrationAuthId: string) => + [{ integrationAuthId }, "integrationAuthQoveryOrgs"] as const, getIntegrationAuthQoveryProjects: ({ integrationAuthId, orgId @@ -93,7 +92,7 @@ const integrationAuthKeys = { }: { integrationAuthId: string; appId: string; - }) => [{ integrationAuthId, appId }, "integrationAuthTeamCityBranchConfigs"] as const, + }) => [{ integrationAuthId, appId }, "integrationAuthTeamCityBranchConfigs"] as const }; const fetchIntegrationAuthById = async (integrationAuthId: string) => { @@ -112,12 +111,12 @@ const fetchIntegrationAuthApps = async ({ teamId?: string; workspaceSlug?: string; }) => { - const params: Record = {} + const params: Record = {}; if (teamId) { - params.teamId = teamId + params.teamId = teamId; } if (workspaceSlug) { - params.workspaceSlug = workspaceSlug + params.workspaceSlug = workspaceSlug; } const searchParams = new URLSearchParams(params); @@ -193,7 +192,7 @@ const fetchIntegrationAuthQoveryProjects = async ({ orgId: string; }) => { if (orgId === "none") return []; - + const { data: { projects } } = await apiRequest.get<{ projects: Project[] }>( @@ -241,7 +240,7 @@ const fetchIntegrationAuthQoveryScopes = async ({ scope: "job" | "application" | "container"; }) => { if (environmentId === "none") return []; - + if (scope === "application") { const { data: { apps } @@ -255,8 +254,8 @@ const fetchIntegrationAuthQoveryScopes = async ({ ); return apps; - } - + } + if (scope === "container") { const { data: { containers } @@ -335,7 +334,9 @@ const fetchIntegrationAuthRailwayServices = async ({ }; const fetchIntegrationAuthBitBucketWorkspaces = async (integrationAuthId: string) => { - const { data: { workspaces } } = await apiRequest.get<{ workspaces: BitBucketWorkspace[] }>( + const { + data: { workspaces } + } = await apiRequest.get<{ workspaces: BitBucketWorkspace[] }>( `/api/v1/integration-auth/${integrationAuthId}/bitbucket/workspaces` ); return workspaces; @@ -396,7 +397,7 @@ export const useGetIntegrationAuthById = (integrationAuthId: string) => { export const useGetIntegrationAuthApps = ({ integrationAuthId, teamId, - workspaceSlug, + workspaceSlug }: { integrationAuthId: string; teamId?: string; @@ -455,10 +456,11 @@ export const useGetIntegrationAuthChecklyGroups = ({ integrationAuthId, accountId }), - queryFn: () => fetchIntegrationAuthChecklyGroups({ - integrationAuthId, - accountId - }), + queryFn: () => + fetchIntegrationAuthChecklyGroups({ + integrationAuthId, + accountId + }), enabled: true }); }; @@ -466,8 +468,7 @@ export const useGetIntegrationAuthChecklyGroups = ({ export const useGetIntegrationAuthQoveryOrgs = (integrationAuthId: string) => { return useQuery({ queryKey: integrationAuthKeys.getIntegrationAuthQoveryOrgs(integrationAuthId), - queryFn: () => - fetchIntegrationAuthQoveryOrgs(integrationAuthId), + queryFn: () => fetchIntegrationAuthQoveryOrgs(integrationAuthId), enabled: true }); }; @@ -622,10 +623,11 @@ export const useGetIntegrationAuthTeamCityBuildConfigs = ({ integrationAuthId, appId }), - queryFn: () => fetchIntegrationAuthTeamCityBuildConfigs({ - integrationAuthId, - appId - }), + queryFn: () => + fetchIntegrationAuthTeamCityBuildConfigs({ + integrationAuthId, + appId + }), enabled: true }); }; @@ -645,7 +647,9 @@ export const useAuthorizeIntegration = () => { integration: string; url?: string; }) => { - const { data: { integrationAuth } } = await apiRequest.post("/api/v1/integration-auth/oauth-token", { + const { + data: { integrationAuth } + } = await apiRequest.post("/api/v1/integration-auth/oauth-token", { workspaceId, code, integration, @@ -681,7 +685,9 @@ export const useSaveIntegrationAccessToken = () => { url?: string; namespace?: string; }) => { - const { data: { integrationAuth } } = await apiRequest.post("/api/v1/integration-auth/access-token", { + const { + data: { integrationAuth } + } = await apiRequest.post("/api/v1/integration-auth/access-token", { workspaceId, integration, refreshToken, @@ -703,10 +709,13 @@ export const useDeleteIntegrationAuths = () => { const queryClient = useQueryClient(); return useMutation<{}, {}, { integration: string; workspaceId: string }>({ - mutationFn: ({ integration, workspaceId }) => apiRequest.delete(`/api/v1/integration-auth?${new URLSearchParams({ - integration, - workspaceId - })}`), + mutationFn: ({ integration, workspaceId }) => + apiRequest.delete( + `/api/v1/integration-auth?${new URLSearchParams({ + integration, + projectId: workspaceId + })}` + ), onSuccess: (_, { workspaceId }) => { queryClient.invalidateQueries(workspaceKeys.getWorkspaceAuthorization(workspaceId)); queryClient.invalidateQueries(workspaceKeys.getWorkspaceIntegrations(workspaceId)); @@ -714,7 +723,8 @@ export const useDeleteIntegrationAuths = () => { }); }; -export const useDeleteIntegrationAuth = () => { // not used +export const useDeleteIntegrationAuth = () => { + // not used const queryClient = useQueryClient(); return useMutation<{}, {}, { id: string; workspaceId: string }>({ @@ -725,4 +735,3 @@ export const useDeleteIntegrationAuth = () => { // not used } }); }; -