Skip to content

Commit

Permalink
Merge pull request #1398 from Salman2301/feat-github-integration
Browse files Browse the repository at this point in the history
Github Integrations
  • Loading branch information
dangtony98 authored Mar 16, 2024
2 parents 2d3fddd + 7edebba commit 56fc5a2
Show file tree
Hide file tree
Showing 15 changed files with 923 additions and 360 deletions.
60 changes: 60 additions & 0 deletions backend/src/server/routes/v1/integration-auth-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,66 @@ export const registerIntegrationAuthRouter = async (server: FastifyZodProvider)
}
});

server.route({
url: "/:integrationAuthId/github/orgs",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
response: {
200: z.object({
orgs: z.object({ name: z.string(), orgId: z.string() }).array()
})
}
},
handler: async (req) => {
const orgs = await server.services.integrationAuth.getGithubOrgs({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId
});
if (!orgs) throw new Error("No organization found.");

return { orgs };
}
});

server.route({
url: "/:integrationAuthId/github/envs",
method: "GET",
onRequest: verifyAuth([AuthMode.JWT]),
schema: {
params: z.object({
integrationAuthId: z.string().trim()
}),
querystring: z.object({
repoOwner: z.string().trim(),
repoName: z.string().trim()
}),
response: {
200: z.object({
envs: z.object({ name: z.string(), envId: z.string() }).array()
})
}
},
handler: async (req) => {
const envs = await server.services.integrationAuth.getGithubEnvs({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
id: req.params.integrationAuthId,
repoName: req.query.repoName,
repoOwner: req.query.repoOwner
});
if (!envs) throw new Error("No organization found.");

return { envs };
}
});

server.route({
url: "/:integrationAuthId/qovery/orgs",
method: "GET",
Expand Down
75 changes: 72 additions & 3 deletions backend/src/services/integration-auth/integration-auth-service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ForbiddenError } from "@casl/ability";
import { Octokit } from "@octokit/rest";

import { SecretEncryptionAlgo, SecretKeyEncoding, TIntegrationAuths, TIntegrationAuthsInsert } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
Expand All @@ -24,6 +25,8 @@ import {
TIntegrationAuthAppsDTO,
TIntegrationAuthBitbucketWorkspaceDTO,
TIntegrationAuthChecklyGroupsDTO,
TIntegrationAuthGithubEnvsDTO,
TIntegrationAuthGithubOrgsDTO,
TIntegrationAuthHerokuPipelinesDTO,
TIntegrationAuthNorthflankSecretGroupDTO,
TIntegrationAuthQoveryEnvironmentsDTO,
Expand Down Expand Up @@ -383,6 +386,72 @@ export const integrationAuthServiceFactory = ({
return [];
};

const getGithubOrgs = async ({ actorId, actor, actorOrgId, id }: TIntegrationAuthGithubOrgsDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });

const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);

const octokit = new Octokit({
auth: accessToken
});

const { data } = await octokit.request("GET /user/orgs", {
headers: {
"X-GitHub-Api-Version": "2022-11-28"
}
});
if (!data) return [];

return data.map(({ login: name, id: orgId }) => ({ name, orgId: String(orgId) }));
};

const getGithubEnvs = async ({
actorId,
actor,
actorOrgId,
id,
repoOwner,
repoName
}: TIntegrationAuthGithubEnvsDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });

const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
integrationAuth.projectId,
actorOrgId
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Integrations);
const botKey = await projectBotService.getBotKey(integrationAuth.projectId);
const { accessToken } = await getIntegrationAccessToken(integrationAuth, botKey);

const octokit = new Octokit({
auth: accessToken
});

const {
data: { environments }
} = await octokit.request("GET /repos/{owner}/{repo}/environments", {
headers: {
"X-GitHub-Api-Version": "2022-11-28"
},
owner: repoOwner,
repo: repoName
});
if (!environments) return [];
return environments.map(({ id: envId, name }) => ({ name, envId: String(envId) }));
};

const getQoveryOrgs = async ({ actorId, actor, actorOrgId, id }: TIntegrationAuthQoveryOrgsDTO) => {
const integrationAuth = await integrationAuthDAL.findById(id);
if (!integrationAuth) throw new BadRequestError({ message: "Failed to find integration" });
Expand Down Expand Up @@ -756,9 +825,7 @@ export const integrationAuthServiceFactory = ({

while (hasNextPage) {
// eslint-disable-next-line
const { data }: { data: { values: TBitbucketWorkspace[]; next: string } } = await request.get(
workspaceUrl,
{
const { data }: { data: { values: TBitbucketWorkspace[]; next: string } } = await request.get(workspaceUrl, {
headers: {
Authorization: `Bearer ${accessToken}`,
"Accept-Encoding": "application/json"
Expand Down Expand Up @@ -934,6 +1001,8 @@ export const integrationAuthServiceFactory = ({
getIntegrationApps,
getVercelBranches,
getApps,
getGithubOrgs,
getGithubEnvs,
getChecklyGroups,
getQoveryApps,
getQoveryEnvs,
Expand Down
10 changes: 10 additions & 0 deletions backend/src/services/integration-auth/integration-auth-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ export type TIntegrationAuthChecklyGroupsDTO = {
accountId: string;
} & Omit<TProjectPermission, "projectId">;

export type TIntegrationAuthGithubOrgsDTO = {
id: string;
} & Omit<TProjectPermission, "projectId">;

export type TIntegrationAuthGithubEnvsDTO = {
id: string;
repoName: string;
repoOwner: string;
} & Omit<TProjectPermission, "projectId">;

export type TIntegrationAuthQoveryOrgsDTO = {
id: string;
} & Omit<TProjectPermission, "projectId">;
Expand Down
Loading

0 comments on commit 56fc5a2

Please sign in to comment.