Modularize integrations into json files, continue refactoring integrations frontend

This commit is contained in:
Tuan Dang
2022-12-12 00:23:13 -05:00
parent 182db69ee1
commit 10d57e9d88
14 changed files with 217 additions and 213 deletions

View File

@@ -22,31 +22,6 @@ interface PushSecret {
type: 'shared' | 'personal';
}
/**
* Return list of all available integrations on Infisical
* @param req
* @param res
* @returns
*/
export const getIntegrations = async (req: Request, res: Response) => {
let integrations;
try {
integrations = JSON.parse(
readFileSync('./src/json/integrations.json').toString()
);
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed to get integrations'
});
}
return res.status(200).send({
integrations
});
};
/**
* Change environment or name of integration with id [integrationId]
* @param req

View File

@@ -1,50 +0,0 @@
{
"heroku": {
"name": "Heroku",
"type": "oauth2",
"clientId": "bc132901-935a-4590-b010-f1857efc380d",
"docsLink": ""
},
"netlify": {
"name": "Netlify",
"type": "oauth2",
"clientId": "",
"docsLink": ""
},
"digitalocean": {
"name": "Digital Ocean",
"type": "oauth2",
"clientId": "",
"docsLink": ""
},
"gcp": {
"name": "Google Cloud Platform",
"type": "oauth2",
"clientId": "",
"docsLink": ""
},
"aws": {
"name": "Amazon Web Services",
"type": "oauth2",
"clientId": "",
"docsLink": ""
},
"azure": {
"name": "Microsoft Azure",
"type": "oauth2",
"clientId": "",
"docsLink": ""
},
"travisci": {
"name": "Travis CI",
"type": "oauth2",
"clientId": "",
"docsLink": ""
},
"circleci": {
"name": "Circle CI",
"type": "oauth2",
"clientId": "",
"docsLink": ""
}
}

View File

@@ -9,8 +9,6 @@ import { ADMIN, MEMBER, GRANTED } from '../variables';
import { body, param } from 'express-validator';
import { integrationController } from '../controllers';
router.get('/integrations', requireAuth, integrationController.getIntegrations);
router.patch(
'/:integrationId',
requireAuth,

View File

@@ -28,7 +28,7 @@ const CloudIntegration = ({
deleteIntegrationAuth,
authorizations
}: Props) => {
return (
return authorizations ? (
<div
className={`relative ${
["Heroku"].includes(integration.name)
@@ -106,7 +106,7 @@ const CloudIntegration = ({
</div>
)}
</div>
);
) : <div></div>
}
export default CloudIntegration;

View File

@@ -28,21 +28,22 @@ const CloudIntegrationSection = ({
return (
<>
<div className={`flex flex-col justify-between items-start m-4 ${projectIntegrations.length > 0 ? 'mt-12' : 'mt-6'} text-xl max-w-5xl px-2`}>
<h1 className="font-semibold text-3xl">Cloud Integrations</h1>
<p className="text-base text-gray-400">
Click on an integration to begin syncing secrets to it.
</p>
<h1 className="font-semibold text-3xl">Cloud Integrations</h1>
<p className="text-base text-gray-400">
Click on an integration to begin syncing secrets to it.
</p>
</div>
<div className="grid gap-4 grid-cols-4 grid-rows-2 mx-6 max-w-5xl">
{integrations.map((integration) => (
<CloudIntegration
integration={integration}
setSelectedIntegrationOption={setSelectedIntegrationOption}
integrationOptionPress={integrationOptionPress}
deleteIntegrationAuth={deleteIntegrationAuth}
authorizations={authorizations}
/>
))}
{integrations.map((integration) => (
<CloudIntegration
integration={integration}
setSelectedIntegrationOption={setSelectedIntegrationOption}
integrationOptionPress={integrationOptionPress}
deleteIntegrationAuth={deleteIntegrationAuth}
authorizations={authorizations}
key={`cloud-integration-${integration.slug}`}
/>
))}
</div>
</>
);

View File

@@ -3,8 +3,9 @@ import Image from "next/image";
interface Framework {
name: string;
link: string;
slug: string;
image: string;
docsLink: string;
}
const FrameworkIntegration = ({
@@ -13,13 +14,12 @@ const FrameworkIntegration = ({
framework: Framework;
}) => {
return (
<div key={framework.name}>
<a
href={framework.link}
href={framework.docsLink}
rel="noopener"
className={`relative flex flex-row items-center justify-center bg-bunker-500 hover:bg-gradient-to-tr hover:from-sky-400 hover:to-primary duration-200 h-32 rounded-md p-0.5 items-center cursor-pointer`}
className={`relative flex flex-row items-center justify-center bg-bunker-500 hover:bg-gradient-to-tr duration-200 h-32 rounded-md p-0.5 items-center cursor-pointer`}
>
<div className={`font-semibold bg-bunker-500 flex flex-col items-center justify-center h-full w-full rounded-md text-gray-300 group-hover:text-gray-200 duration-200 ${framework?.name?.split(" ").length > 1 ? "text-sm px-1" : "text-xl px-2"} text-center w-full max-w-xs`}>
<div className={`hover:bg-white/10 duration-200 cursor-pointer font-semibold bg-bunker-500 flex flex-col items-center justify-center h-full w-full rounded-md text-gray-300 group-hover:text-gray-200 duration-200 ${framework?.name?.split(" ").length > 1 ? "text-sm px-1" : "text-xl px-2"} text-center w-full max-w-xs`}>
{framework?.image && <Image
src={`/images/integrations/${framework.image}.png`}
height={framework?.name ? 60 : 90}
@@ -30,7 +30,6 @@ const FrameworkIntegration = ({
{framework?.name && framework.name}
</div>
</a>
</div>
);
}

View File

@@ -22,7 +22,10 @@ const FrameworkIntegrationSection = ({ frameworks }: Props) => {
</div>
<div className="grid gap-4 grid-cols-7 grid-rows-2 mx-6 mt-4 max-w-5xl">
{frameworks.map((framework) => (
<FrameworkIntegration framework={framework} />
<FrameworkIntegration
framework={framework}
key={`framework-integration-${framework.slug}`}
/>
))}
</div>
</>

View File

@@ -1,18 +0,0 @@
import SecurityClient from '~/utilities/SecurityClient';
const getIntegrations = () => {
return SecurityClient.fetchCall('/api/v1/integration/integrations', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}).then(async (res) => {
if (res && res.status == 200) {
return (await res.json()).integrations;
} else {
console.log('Failed to get project integrations');
}
});
};
export default getIntegrations;

View File

@@ -5,7 +5,6 @@ const queryString = require("query-string");
import AuthorizeIntegration from "./api/integrations/authorizeIntegration";
export default function Heroku() {
console.log('HEROKU PAGE');
const router = useRouter();
const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
const code = parsedUrl.code;
@@ -17,11 +16,7 @@ export default function Heroku() {
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(async () => {
try {
console.log('A');
console.log(state);
console.log(localStorage.getItem('latestCSRFToken'));
if (state == localStorage.getItem("latestCSRFToken")) {
console.log('B');
await AuthorizeIntegration({
workspaceId: localStorage.getItem("projectData.id"),
code,

View File

@@ -7,12 +7,9 @@ import Integration from "~/components/integrations/Integration";
import FrameworkIntegrationSection from "~/components/integrations/FrameworkIntegrationSection";
import CloudIntegrationSection from "~/components/integrations/CloudIntegrationSection";
import ProjectIntegrationSection from "~/components/integrations/ProjectIntegrationSection";
import guidGenerator from "~/utilities/randomId";
import {
frameworks
} from "../../public/data/frequentConstants";
import frameworkIntegrations from "../../public/json/frameworkIntegrations.json";
import cloudIntegrations from "../../public/json/cloudIntegrations.json";
import deleteIntegrationAuth from "../api/integrations/DeleteIntegrationAuth";
import getIntegrations from "../api/integrations/GetIntegrations";
import getWorkspaceAuthorizations from "../api/integrations/getWorkspaceAuthorizations";
import getWorkspaceIntegrations from "../api/integrations/getWorkspaceIntegrations";
import getBot from "../api/bot/getBot";
@@ -26,7 +23,6 @@ const {
const crypto = require("crypto");
export default function Integrations() {
const [integrations, setIntegrations] = useState([]);
const [projectIntegrations, setProjectIntegrations] = useState([]);
const [authorizations, setAuthorizations] = useState();
const [bot, setBot] = useState(null);
@@ -54,14 +50,7 @@ export default function Integrations() {
workspaceId: router.query.id
});
setBot(bot.bot);
// get cloud integration options
let integrationOptions = await getIntegrations();
integrationOptions = Object
.keys(integrationOptions)
.map(integrationOption => integrationOptions[integrationOption]);
setIntegrations(integrationOptions);
} catch (err) {
console.log(err);
}
@@ -160,7 +149,7 @@ export default function Integrations() {
}
}
return integrations ? (
return (
<div className="bg-bunker-800 max-h-screen flex flex-col justify-between text-white">
<Head>
<title>Dashboard</title>
@@ -181,7 +170,6 @@ export default function Integrations() {
handleBotActivate={handleBotActivate}
handleIntegrationOption={handleIntegrationOption}
/>
{projectIntegrations.length > 0 && (
<ProjectIntegrationSection
projectIntegrations={projectIntegrations}
@@ -189,25 +177,17 @@ export default function Integrations() {
)}
<CloudIntegrationSection
projectIntegrations={projectIntegrations}
integrations={integrations}
integrations={cloudIntegrations}
setSelectedIntegrationOption={setSelectedIntegrationOption}
integrationOptionPress={integrationOptionPress}
deleteIntegrationAuth={deleteIntegrationAuth}
authorizations={authorizations}
/>
<FrameworkIntegrationSection frameworks={frameworks} />
<FrameworkIntegrationSection
frameworks={frameworkIntegrations}
/>
</div>
</div>
) : (
<div className="relative z-10 w-10/12 mr-auto h-full ml-2 bg-bunker-800 flex flex-col items-center justify-center">
<div className="absolute top-0 bg-bunker h-14 border-b border-mineshaft-700 w-full"></div>
<Image
src="/images/loading/loading.gif"
height={70}
width={120}
alt="loading animation"
></Image>
</div>
);
}

29
frontend/pages/vercel.js Normal file
View File

@@ -0,0 +1,29 @@
import React, { useEffect } from "react";
import Head from "next/head";
import { useRouter } from "next/router";
const queryString = require("query-string");
import AuthorizeIntegration from "./api/integrations/authorizeIntegration";
export default function Vercel() {
const router = useRouter();
const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
/**
* Here we forward to the default workspace if a user opens this url
*/
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(async () => {
console.log('parsedUrl, xxx', parsedUrl);
try {
} catch (err) {
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return <div></div>;
}
Vercel.requireAuth = true;

View File

@@ -12,71 +12,7 @@ const reverseEnvMapping = {
test: "Testing",
};
const frameworks = [{
"name": "Docker",
"image": "Docker",
"link": "https://infisical.com/docs/integrations/platforms/docker"
}, {
"name": "Docker Compose",
"image": "Docker Compose",
"link": "https://infisical.com/docs/integrations/platforms/docker-compose"
}, {
"name": "React",
"image": "React",
"link": "https://infisical.com/docs/integrations/frameworks/react"
}, {
"name": "Vue",
"image": "Vue",
"link": "https://infisical.com/docs/integrations/frameworks/vue"
}, {
"image": "Express",
"link": "https://infisical.com/docs/integrations/frameworks/express"
},{
"image": "Next.js",
"link": "https://infisical.com/docs/integrations/frameworks/nextjs"
}, {
"name": "Django",
"image": "Django",
"link": "https://infisical.com/docs/integrations/frameworks/django"
}, {
"name": "NestJS",
"image": "NestJS",
"link": "https://infisical.com/docs/integrations/frameworks/nestjs"
}, {
"name": "Nuxt",
"image": "Nuxt",
"link": "https://infisical.com/docs/integrations/frameworks/nuxt"
}, {
"name": "Gatsby",
"image": "Gatsby",
"link": "https://infisical.com/docs/integrations/frameworks/gatsby"
}, {
"name": "Remix",
"image": "Remix",
"link": "https://infisical.com/docs/integrations/frameworks/remix"
}, {
"name": "Vite",
"image": "Vite",
"link": "https://infisical.com/docs/integrations/frameworks/vite"
}, {
"image": "Fiber",
"link": "https://infisical.com/docs/integrations/frameworks/fiber"
}, {
"name": "Flask",
"image": "Flask",
"link": "https://infisical.com/docs/integrations/frameworks/flask"
}, {
"name": "Laravel",
"image": "Laravel",
"link": "https://infisical.com/docs/integrations/frameworks/laravel"
}, {
"image": "Rails",
"link": "https://infisical.com/docs/integrations/frameworks/rails"
}
]
export {
envMapping,
frameworks,
reverseEnvMapping
};

View File

@@ -0,0 +1,58 @@
[
{
"name": "Heroku",
"slug": "heroku",
"image": "Heroku",
"type": "oauth2",
"clientId": "bc132901-935a-4590-b010-f1857efc380d"
},
{
"name": "Netlify",
"slug": "netlify",
"image": "Netlify",
"type": "oauth2",
"clientId": ""
},
{
"name": "Digital Ocean",
"slug": "digital-ocean",
"image": "Digital Ocean",
"type": "",
"clientId": ""
},
{
"name": "Google Cloud Platform",
"slug": "gcp",
"image": "Google Cloud Platform",
"type": "",
"clientId": ""
},
{
"name": "Amazon Web Services",
"slug": "aws",
"image": "Amazon Web Services",
"type": "",
"clientId": ""
},
{
"name": "Microsoft Azure",
"slug": "azure",
"image": "Microsoft Azure",
"type": "",
"clientId": ""
},
{
"name": "Travis CI",
"slug": "travisci",
"image": "Travis CI",
"type": "",
"clientId": ""
},
{
"name": "Circle CI",
"slug": "circleci",
"image": "Circle CI",
"type": "",
"clientId": ""
}
]

View File

@@ -0,0 +1,98 @@
[
{
"name": "Docker",
"slug": "docker",
"image": "Docker",
"docsLink": "https://infisical.com/docs/integrations/platforms/docker"
},
{
"name": "Docker Compose",
"slug": "docker-compose",
"image": "Docker Compose",
"docsLink": "https://infisical.com/docs/integrations/platforms/docker-compose"
},
{
"name": "React",
"slug": "react",
"image": "React",
"docsLink": "https://infisical.com/docs/integrations/frameworks/react"
},
{
"name": "Vue",
"slug": "vue",
"image": "Vue",
"docsLink": "https://infisical.com/docs/integrations/frameworks/vue"
},
{
"name": "Express",
"slug": "express",
"image": "Express",
"docsLink": "https://infisical.com/docs/integrations/frameworks/express"
},
{
"name": "Next.js",
"slug": "nextjs",
"image": "Next.js",
"docsLink": "https://infisical.com/docs/integrations/frameworks/nextjs"
},
{
"name": "Django",
"slug": "django",
"image": "Django",
"docsLink": "https://infisical.com/docs/integrations/frameworks/django"
},
{
"name": "NestJS",
"slug": "nestjs",
"image": "NestJS",
"docsLink": "https://infisical.com/docs/integrations/frameworks/nestjs"
},
{
"name": "Nuxt",
"slug": "nuxt",
"image": "Nuxt",
"docsLink": "https://infisical.com/docs/integrations/frameworks/nuxt"
},
{
"name": "Gatsby",
"slug": "gatsby",
"image": "Gatsby",
"docsLink": "https://infisical.com/docs/integrations/frameworks/gatsby"
},
{
"name": "Remix",
"slug": "remix",
"image": "Remix",
"docsLink": "https://infisical.com/docs/integrations/frameworks/remix"
},
{
"name": "Vite",
"slug": "vite",
"image": "Vite",
"docsLink": "https://infisical.com/docs/integrations/frameworks/vite"
},
{
"name": "Fiber",
"slug": "fiber",
"image": "Fiber",
"docsLink": "https://infisical.com/docs/integrations/frameworks/fiber"
},
{
"name": "Flask",
"slug": "flask",
"image": "Flask",
"docsLink": "https://infisical.com/docs/integrations/frameworks/flask"
},
{
"name": "Laravel",
"slug": "laravel",
"image": "Laravel",
"docsLink": "https://infisical.com/docs/integrations/frameworks/laravel"
},
{
"name": "Rails",
"slug": "rails",
"image": "Rails",
"docsLink": "https://infisical.com/docs/integrations/frameworks/rails"
}
]