diff --git a/frontend/src/views/IntegrationsPage/IntegrationPage.utils.tsx b/frontend/src/views/IntegrationsPage/IntegrationPage.utils.tsx index 3a8c3e130..3db86abf2 100644 --- a/frontend/src/views/IntegrationsPage/IntegrationPage.utils.tsx +++ b/frontend/src/views/IntegrationsPage/IntegrationPage.utils.tsx @@ -1,17 +1,17 @@ -import crypto from 'crypto'; +import crypto from "crypto"; -import { UserWsKeyPair, TCloudIntegration } from '@app/hooks/api/types'; +import { UserWsKeyPair, TCloudIntegration } from "@app/hooks/api/types"; import { decryptAssymmetric, encryptAssymmetric -} from '../../components/utilities/cryptography/crypto'; +} from "../../components/utilities/cryptography/crypto"; export const generateBotKey = (botPublicKey: string, latestKey: UserWsKeyPair) => { - const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY'); + const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); if (!PRIVATE_KEY) { - throw new Error('Private Key missing'); + throw new Error("Private Key missing"); } const WORKSPACE_KEY = decryptAssymmetric({ @@ -33,64 +33,67 @@ export const generateBotKey = (botPublicKey: string, latestKey: UserWsKeyPair) = export const redirectForProviderAuth = (integrationOption: TCloudIntegration) => { try { // generate CSRF token for OAuth2 code-token exchange integrations - const state = crypto.randomBytes(16).toString('hex'); - localStorage.setItem('latestCSRFToken', state); + const state = crypto.randomBytes(16).toString("hex"); + localStorage.setItem("latestCSRFToken", state); - let link = ''; + let link = ""; switch (integrationOption.slug) { - case 'azure-key-vault': + case "azure-key-vault": link = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${window.location.origin}/integrations/azure-key-vault/oauth2/callback&response_mode=query&scope=https://vault.azure.net/.default openid offline_access&state=${state}`; break; - case 'aws-parameter-store': + case "aws-parameter-store": link = `${window.location.origin}/integrations/aws-parameter-store/authorize`; break; - case 'aws-secret-manager': + case "aws-secret-manager": link = `${window.location.origin}/integrations/aws-secret-manager/authorize`; break; - case 'heroku': + case "heroku": link = `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${state}`; break; - case 'vercel': + case "vercel": link = `https://vercel.com/integrations/${integrationOption.clientSlug}/new?state=${state}`; break; - case 'netlify': + case "netlify": link = `https://app.netlify.com/authorize?client_id=${integrationOption.clientId}&response_type=code&state=${state}&redirect_uri=${window.location.origin}/integrations/netlify/oauth2/callback`; break; - case 'github': + case "github": link = `https://github.com/login/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=repo&redirect_uri=${window.location.origin}/integrations/github/oauth2/callback&state=${state}`; break; - case 'gitlab': + case "gitlab": link = `https://gitlab.com/oauth/authorize?client_id=${integrationOption.clientId}&redirect_uri=${window.location.origin}/integrations/gitlab/oauth2/callback&response_type=code&state=${state}`; break; - case 'render': + case "render": link = `${window.location.origin}/integrations/render/authorize`; break; - case 'flyio': + case "flyio": link = `${window.location.origin}/integrations/flyio/authorize`; break; - case 'circleci': + case "circleci": link = `${window.location.origin}/integrations/circleci/authorize`; break; - case 'travisci': + case "travisci": link = `${window.location.origin}/integrations/travisci/authorize`; break; - case 'supabase': + case "supabase": link = `${window.location.origin}/integrations/supabase/authorize`; break; - case 'checkly': + case "checkly": link = `${window.location.origin}/integrations/checkly/authorize`; break; - case 'railway': + case "railway": link = `${window.location.origin}/integrations/railway/authorize`; break; - case 'hashicorp-vault': + case "hashicorp-vault": link = `${window.location.origin}/integrations/hashicorp-vault/authorize`; break; + case "cloudflare-pages": + link = `${window.location.origin}/integrations/cloudflare-pages/authorize`; + break; default: break; } - if (link !== '') { + if (link !== "") { window.location.assign(link); } } catch (err) { diff --git a/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx b/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx index e90cabf13..54f859f99 100644 --- a/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx +++ b/frontend/src/views/IntegrationsPage/IntegrationsPage.tsx @@ -1,12 +1,12 @@ -import { useCallback, useEffect } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useRouter } from 'next/router'; +import { useCallback, useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { useRouter } from "next/router"; -import { useNotificationContext } from '@app/components/context/Notifications/NotificationProvider'; -import NavHeader from '@app/components/navigation/NavHeader'; -import { Button,Modal, ModalContent } from '@app/components/v2'; -import { useWorkspace } from '@app/context'; -import { usePopUp } from '@app/hooks'; +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; +import NavHeader from "@app/components/navigation/NavHeader"; +import { Button, Modal, ModalContent } from "@app/components/v2"; +import { useWorkspace } from "@app/context"; +import { usePopUp } from "@app/hooks"; import { useDeleteIntegration, useDeleteIntegrationAuth, @@ -15,17 +15,18 @@ import { useGetWorkspaceAuthorizations, useGetWorkspaceBot, useGetWorkspaceIntegrations, - useUpdateBotActiveStatus} from '@app/hooks/api'; -import { IntegrationAuth } from '@app/hooks/api/types'; + useUpdateBotActiveStatus +} from "@app/hooks/api"; +import { IntegrationAuth } from "@app/hooks/api/types"; -import { CloudIntegrationSection } from './components/CloudIntegrationSection'; -import { FrameworkIntegrationSection } from './components/FrameworkIntegrationSection'; -import { IntegrationsSection } from './components/IntegrationsSection'; +import { CloudIntegrationSection } from "./components/CloudIntegrationSection"; +import { FrameworkIntegrationSection } from "./components/FrameworkIntegrationSection"; +import { IntegrationsSection } from "./components/IntegrationsSection"; import { generateBotKey, redirectForProviderAuth, redirectToIntegrationAppConfigScreen -} from './IntegrationPage.utils'; +} from "./IntegrationPage.utils"; type Props = { frameworkIntegrations: Array<{ name: string; slug: string; image: string; docsLink: string }>; @@ -37,15 +38,15 @@ export const IntegrationsPage = ({ frameworkIntegrations }: Props) => { const router = useRouter(); const { currentWorkspace } = useWorkspace(); - const workspaceId = currentWorkspace?._id || ''; + const workspaceId = currentWorkspace?._id || ""; const environments = currentWorkspace?.environments || []; const { data: latestWsKey } = useGetUserWsKey(workspaceId); const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([ - 'activeBot', - 'revokeProviderPermissionConf', - 'removeIntegrationConf' + "activeBot", + "revokeProviderPermissionConf", + "removeIntegrationConf" ] as const); const { data: cloudIntegrations, isLoading: isCloudIntegrationsLoading } = @@ -126,7 +127,7 @@ export const IntegrationsPage = ({ frameworkIntegrations }: Props) => { // confirmation to user passing the bot key for provider to get secret access const handleProviderIntegrationStart = (provider: string) => { if (!bot?.isActive) { - handlePopUpOpen('activeBot', { provider }); + handlePopUpOpen("activeBot", { provider }); return; } handleProviderIntegration(provider); @@ -135,7 +136,7 @@ export const IntegrationsPage = ({ frameworkIntegrations }: Props) => { const handleUserAcceptBotCondition = () => { const { provider } = popUp.activeBot?.data as { provider: string }; handleProviderIntegration(provider); - handlePopUpClose('activeBot'); + handlePopUpClose("activeBot"); }; const handleIntegrationDelete = async (integrationId: string, cb: () => void) => { @@ -143,14 +144,14 @@ export const IntegrationsPage = ({ frameworkIntegrations }: Props) => { await deleteIntegration({ id: integrationId, workspaceId }); if (cb) cb(); createNotification({ - type: 'success', - text: 'Deleted integration' + type: "success", + text: "Deleted integration" }); } catch (err) { console.log(err); createNotification({ - type: 'error', - text: 'Failed to delete integration' + type: "error", + text: "Failed to delete integration" }); } }; @@ -165,21 +166,21 @@ export const IntegrationsPage = ({ frameworkIntegrations }: Props) => { }); if (cb) cb(); createNotification({ - type: 'success', - text: 'Revoked provider authentication' + type: "success", + text: "Revoked provider authentication" }); } catch (err) { console.error(err); createNotification({ - type: 'error', - text: 'Failed to revoke provider authentication' + type: "error", + text: "Failed to revoke provider authentication" }); } }; return (