Skip to content

Commit

Permalink
Merge pull request #310 from Infisical/refactor-integration-pages
Browse files Browse the repository at this point in the history
Refactor integration pages into separate steps for authorization and integration creation.
  • Loading branch information
dangtony98 authored Feb 7, 2023
2 parents 1383886 + db05412 commit 747cc11
Show file tree
Hide file tree
Showing 41 changed files with 1,835 additions and 718 deletions.
100 changes: 18 additions & 82 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 36 additions & 10 deletions backend/src/controllers/v1/integrationAuthController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,31 @@ import { INTEGRATION_SET, INTEGRATION_OPTIONS } from '../../variables';
import { IntegrationService } from '../../services';
import { getApps, revokeAccess } from '../../integrations';

/***
* Return integration authorization with id [integrationAuthId]
*/
export const getIntegrationAuth = async (req: Request, res: Response) => {
let integrationAuth;
try {
const { integrationAuthId } = req.params;
integrationAuth = await IntegrationAuth.findById(integrationAuthId);

if (!integrationAuth) return res.status(400).send({
message: 'Failed to find integration authorization'
});
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed to get integration authorization'
});
}

return res.status(200).send({
integrationAuth
});
}

export const getIntegrationOptions = async (
req: Request,
res: Response
Expand All @@ -31,7 +56,6 @@ export const oAuthExchange = async (
) => {
try {
const { workspaceId, code, integration } = req.body;

if (!INTEGRATION_SET.has(integration))
throw new Error('Failed to validate integration');

Expand All @@ -40,14 +64,16 @@ export const oAuthExchange = async (
throw new Error("Failed to get environments")
}

const integrationDetails = await IntegrationService.handleOAuthExchange({
const integrationAuth = await IntegrationService.handleOAuthExchange({
workspaceId,
integration,
code,
environment: environments[0].slug,
});

return res.status(200).send(integrationDetails);
return res.status(200).send({
integrationAuth
});
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
Expand Down Expand Up @@ -79,6 +105,13 @@ export const saveIntegrationAccessToken = async (
integration: string;
} = req.body;

const bot = await Bot.findOne({
workspace: new Types.ObjectId(workspaceId),
isActive: true
});

if (!bot) throw new Error('Bot must be enabled to save integration access token');

integrationAuth = await IntegrationAuth.findOneAndUpdate({
workspace: new Types.ObjectId(workspaceId),
integration
Expand All @@ -89,13 +122,6 @@ export const saveIntegrationAccessToken = async (
new: true,
upsert: true
});

const bot = await Bot.findOne({
workspace: new Types.ObjectId(workspaceId),
isActive: true
});

if (!bot) throw new Error('Bot must be enabled to save integration access token');

// encrypt and save integration access token
integrationAuth = await IntegrationService.setIntegrationAuthAccess({
Expand Down
37 changes: 30 additions & 7 deletions backend/src/controllers/v1/integrationController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Request, Response } from 'express';
import { Types } from 'mongoose';
import * as Sentry from '@sentry/node';
import {
Integration,
Expand All @@ -16,20 +17,42 @@ import { eventPushSecrets } from '../../events';
* @returns
*/
export const createIntegration = async (req: Request, res: Response) => {

// TODO: make this more versatile

let integration;
try {
const {
integrationAuthId,
app,
appId,
isActive,
sourceEnvironment,
targetEnvironment,
owner
} = req.body;

// TODO: validate [sourceEnvironment] and [targetEnvironment]

// initialize new integration after saving integration access token
integration = await new Integration({
workspace: req.integrationAuth.workspace._id,
isActive: false,
app: null,
environment: req.integrationAuth.workspace?.environments[0].slug,
environment: sourceEnvironment,
isActive,
app,
appId,
targetEnvironment,
owner,
integration: req.integrationAuth.integration,
integrationAuth: req.integrationAuth._id
integrationAuth: new Types.ObjectId(integrationAuthId)
}).save();

if (integration) {
// trigger event - push secrets
EventService.handleEvent({
event: eventPushSecrets({
workspaceId: integration.workspace.toString()
})
});
}

} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
Expand Down
18 changes: 2 additions & 16 deletions backend/src/helpers/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ interface Update {
* @param {String} obj.workspaceId - id of workspace
* @param {String} obj.integration - name of integration
* @param {String} obj.code - code
* @returns {IntegrationAuth} integrationAuth - integration auth after OAuth2 code-token exchange
*/
const handleOAuthExchangeHelper = async ({
workspaceId,
Expand All @@ -42,9 +43,7 @@ const handleOAuthExchangeHelper = async ({
code: string;
environment: string;
}) => {
let action;
let integrationAuth;
let newIntegration;
try {
const bot = await Bot.findOne({
workspace: workspaceId,
Expand Down Expand Up @@ -99,26 +98,13 @@ const handleOAuthExchangeHelper = async ({
accessExpiresAt: res.accessExpiresAt
});
}

// initialize new integration after exchange
newIntegration = await new Integration({
workspace: workspaceId,
isActive: false,
app: null,
environment,
integration,
integrationAuth: integrationAuth._id
}).save();
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
throw new Error('Failed to handle OAuth2 code-token exchange')
}

return ({
integrationAuth,
integration: newIntegration
});
return integrationAuth;
}
/**
* Sync/push environment variables in workspace with id [workspaceId] to
Expand Down
8 changes: 4 additions & 4 deletions backend/src/integrations/exchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const exchangeCodeAzure = async ({
scope: 'https://vault.azure.net/.default openid offline_access', // TODO: do we need all these permissions?
client_id: CLIENT_ID_AZURE,
client_secret: CLIENT_SECRET_AZURE,
redirect_uri: `${SITE_URL}/azure-key-vault`
redirect_uri: `${SITE_URL}/integrations/azure-key-vault/oauth2/callback`
} as any)
)).data;

Expand Down Expand Up @@ -227,7 +227,7 @@ const exchangeCodeVercel = async ({ code }: { code: string }) => {
code: code,
client_id: CLIENT_ID_VERCEL,
client_secret: CLIENT_SECRET_VERCEL,
redirect_uri: `${SITE_URL}/vercel`
redirect_uri: `${SITE_URL}/integrations/vercel/oauth2/callback`
} as any)
)
).data;
Expand Down Expand Up @@ -267,7 +267,7 @@ const exchangeCodeNetlify = async ({ code }: { code: string }) => {
code: code,
client_id: CLIENT_ID_NETLIFY,
client_secret: CLIENT_SECRET_NETLIFY,
redirect_uri: `${SITE_URL}/netlify`
redirect_uri: `${SITE_URL}/integrations/netlify/oauth2/callback`
} as any)
)
).data;
Expand Down Expand Up @@ -319,7 +319,7 @@ const exchangeCodeGithub = async ({ code }: { code: string }) => {
client_id: CLIENT_ID_GITHUB,
client_secret: CLIENT_SECRET_GITHUB,
code: code,
redirect_uri: `${SITE_URL}/github`
redirect_uri: `${SITE_URL}/integrations/github/oauth2/callback`
},
headers: {
Accept: 'application/json'
Expand Down
2 changes: 0 additions & 2 deletions backend/src/integrations/sync.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import axios from 'axios';
import * as Sentry from '@sentry/node';
import { Octokit } from '@octokit/rest';
// import * as sodium from 'libsodium-wrappers';
import sodium from 'libsodium-wrappers';
// const sodium = require('libsodium-wrappers');
import { IIntegration, IIntegrationAuth } from '../models';
import {
INTEGRATION_AZURE_KEY_VAULT,
Expand Down
Loading

0 comments on commit 747cc11

Please sign in to comment.