diff --git a/backend/src/controllers/integrationAuthController.ts b/backend/src/controllers/integrationAuthController.ts index b5c9167aa..fc2767e0a 100644 --- a/backend/src/controllers/integrationAuthController.ts +++ b/backend/src/controllers/integrationAuthController.ts @@ -5,7 +5,7 @@ import { readFileSync } from 'fs'; import { IntegrationAuth, Integration } from '../models'; import { INTEGRATION_SET, ENV_DEV } from '../variables'; import { IntegrationService } from '../services'; -import { getApps } from '../integrations'; +import { getApps, revokeAccess } from '../integrations'; /** * Perform OAuth2 code-token exchange as part of integration [integration] for workspace with id [workspaceId] @@ -74,46 +74,22 @@ export const getIntegrationAuthApps = async (req: Request, res: Response) => { * @returns */ export const deleteIntegrationAuth = async (req: Request, res: Response) => { - // TODO: unfinished - disable application via Heroku API and make compatible with other integration types try { const { integrationAuthId } = req.params; - // TODO: disable application via Heroku API; figure out what authorization id is - - const integrations = JSON.parse( - readFileSync('./src/json/integrations.json').toString() - ); - - let authorizationId; - switch (req.integrationAuth.integration) { - case 'heroku': - authorizationId = integrations.heroku.clientId; - } - - // not sure what authorizationId is? - // // revoke authorization - // const res2 = await axios.delete( - // `https://api.heroku.com/oauth/authorizations/${authorizationId}`, - // { - // headers: { - // 'Accept': 'application/vnd.heroku+json; version=3', - // 'Authorization': 'Bearer ' + req.accessToken - // } - // } - // ); - - const deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({ - _id: integrationAuthId + await revokeAccess({ + integrationAuth: req.integrationAuth, + accessToken: req.accessToken }); - - if (deletedIntegrationAuth) { - await Integration.deleteMany({ - integrationAuth: deletedIntegrationAuth._id - }); - } } catch (err) { + Sentry.setUser(null); + Sentry.captureException(err); return res.status(400).send({ message: 'Failed to delete integration authorization' }); } -}; + + return res.status(200).send({ + message: 'Successfully deleted integration authorization' + }); +} \ No newline at end of file diff --git a/backend/src/integrations/index.ts b/backend/src/integrations/index.ts index 3d8e8cc95..86c22de0c 100644 --- a/backend/src/integrations/index.ts +++ b/backend/src/integrations/index.ts @@ -2,10 +2,12 @@ import { exchangeCode } from './exchange'; import { exchangeRefresh } from './refresh'; import { getApps } from './apps'; import { syncSecrets } from './sync'; +import { revokeAccess } from './revoke'; export { exchangeCode, exchangeRefresh, getApps, - syncSecrets + syncSecrets, + revokeAccess } \ No newline at end of file diff --git a/backend/src/integrations/revoke.ts b/backend/src/integrations/revoke.ts new file mode 100644 index 000000000..833e6c88a --- /dev/null +++ b/backend/src/integrations/revoke.ts @@ -0,0 +1,50 @@ +import axios from 'axios'; +import * as Sentry from '@sentry/node'; +import { + IIntegrationAuth, + IntegrationAuth, + Integration +} from '../models'; +import { + INTEGRATION_HEROKU, + INTEGRATION_VERCEL, + INTEGRATION_NETLIFY +} from '../variables'; + +const revokeAccess = async ({ + integrationAuth, + accessToken +}: { + integrationAuth: IIntegrationAuth, + accessToken: String +}) => { + try { + // add any integration-specific revocation logic + switch (integrationAuth.integration) { + case INTEGRATION_HEROKU: + break; + case INTEGRATION_VERCEL: + break; + case INTEGRATION_NETLIFY: + break; + } + + const deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({ + _id: integrationAuth._id + }); + + if (deletedIntegrationAuth) { + await Integration.deleteMany({ + integrationAuth: deletedIntegrationAuth._id + }); + } + } catch (err) { + Sentry.setUser(null); + Sentry.captureException(err); + throw new Error('Failed to delete integration authorization'); + } +} + +export { + revokeAccess +} \ No newline at end of file diff --git a/frontend/components/integrations/CloudIntegration.tsx b/frontend/components/integrations/CloudIntegration.tsx index f3f1ad153..b9bbb08c8 100644 --- a/frontend/components/integrations/CloudIntegration.tsx +++ b/frontend/components/integrations/CloudIntegration.tsx @@ -1,5 +1,6 @@ import React from "react"; import Image from "next/image"; +import { useRouter } from "next/router"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCheck, @@ -33,6 +34,7 @@ const CloudIntegration = ({ integrationOptionPress, integrationAuths }: Props) => { + const router = useRouter(); return integrationAuths ? (