mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-11 16:29:00 +00:00
Preliminary Vercel integration
This commit is contained in:
@@ -33,8 +33,6 @@ const CloudIntegration = ({
|
||||
integrationOptionPress,
|
||||
integrationAuths
|
||||
}: Props) => {
|
||||
console.log('cloudIntegrationOption', cloudIntegrationOption);
|
||||
console.log('integrationAuths', integrationAuths);
|
||||
return integrationAuths ? (
|
||||
<div
|
||||
className={`relative ${
|
||||
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
reverseEnvMapping
|
||||
envMapping,
|
||||
reverseEnvMapping
|
||||
} from "../../public/data/frequentConstants";
|
||||
import updateIntegration from "../../pages/api/integrations/updateIntegration"
|
||||
import deleteIntegration from "../../pages/api/integrations/DeleteIntegration"
|
||||
@@ -37,6 +38,7 @@ const Integration = ({
|
||||
const router = useRouter();
|
||||
const [apps, setApps] = useState([]);
|
||||
const [integrationApp, setIntegrationApp] = useState(null);
|
||||
const [integrationTarget, setIntegrationTarget] = useState(null);
|
||||
|
||||
useEffect(async () => {
|
||||
const tempApps = await getIntegrationApps({
|
||||
@@ -48,54 +50,70 @@ const Integration = ({
|
||||
setIntegrationApp(
|
||||
integration.app ? integration.app : tempAppNames[0]
|
||||
);
|
||||
setIntegrationTarget("Development");
|
||||
}, []);
|
||||
|
||||
return (integrationApp && apps.length > 0) ? (
|
||||
<div className="flex flex-col max-w-5xl justify-center bg-white/5 p-6 rounded-md mx-6 mt-8">
|
||||
<div className="relative px-4 flex flex-row items-center justify-between mb-4">
|
||||
<div className="flex flex-row">
|
||||
<div>
|
||||
<div className="text-gray-400 self-start ml-1 mb-1 text-xs font-semibold tracking-wide">
|
||||
ENVIRONMENT
|
||||
</div>
|
||||
<ListBox
|
||||
data={
|
||||
!integration.isActive && [
|
||||
"Development",
|
||||
"Staging",
|
||||
"Testing",
|
||||
"Production",
|
||||
]
|
||||
}
|
||||
selected={integrationEnvironment}
|
||||
onChange={setIntegrationEnvironment}
|
||||
/>
|
||||
</div>
|
||||
|
||||
if (!integrationApp || apps.length === 0) return <div></div>
|
||||
|
||||
return (
|
||||
<div className="max-w-5xl p-6 mx-6 mb-8 rounded-md bg-white/5 flex justify-between">
|
||||
<div className="flex">
|
||||
<div>
|
||||
<p className="text-gray-400 text-xs font-semibold mb-2">ENVIRONMENT</p>
|
||||
<ListBox data={!integration.isActive ? [
|
||||
"Development",
|
||||
"Staging",
|
||||
"Testing",
|
||||
"Production",
|
||||
] : null}
|
||||
selected={integrationEnvironment}
|
||||
onChange={setIntegrationEnvironment}
|
||||
isFull={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="pt-2">
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowRight}
|
||||
className="mx-4 text-gray-400 mt-8"
|
||||
/>
|
||||
<div className="mr-2">
|
||||
<div className="text-gray-400 self-start ml-1 mb-1 text-xs font-semibold tracking-wide">
|
||||
INTEGRATION
|
||||
</div>
|
||||
<div className="py-2.5 bg-white/[.07] rounded-md pl-4 pr-20 text-sm font-semibold text-gray-300">
|
||||
{integration.integration.charAt(0).toUpperCase() +
|
||||
integration.integration.slice(1)}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-gray-400 self-start ml-1 mb-1 text-xs font-semibold tracking-wide">
|
||||
HEROKU APP
|
||||
</div>
|
||||
<ListBox
|
||||
data={!integration.isActive && apps}
|
||||
selected={integrationApp}
|
||||
onChange={setIntegrationApp}
|
||||
/>
|
||||
/>
|
||||
</div>
|
||||
<div className="mr-2">
|
||||
<p className="text-gray-400 text-xs font-semibold mb-2">
|
||||
INTEGRATION
|
||||
</p>
|
||||
<div className="py-2.5 bg-white/[.07] rounded-md pl-4 pr-10 text-sm font-semibold text-gray-300">
|
||||
{integration.integration.charAt(0).toUpperCase() +
|
||||
integration.integration.slice(1)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row mt-6">
|
||||
<div className="mr-2">
|
||||
<div className="text-gray-400 text-xs font-semibold mb-2">
|
||||
APP
|
||||
</div>
|
||||
<ListBox
|
||||
data={!integration.isActive && apps}
|
||||
selected={integrationApp}
|
||||
onChange={setIntegrationApp}
|
||||
/>
|
||||
</div>
|
||||
{integration.integration === "vercel" && (
|
||||
<div>
|
||||
<div className="text-gray-400 text-xs font-semibold mb-2">
|
||||
ENVIRONMENT
|
||||
</div>
|
||||
<ListBox
|
||||
data={!integration.isActive && [
|
||||
"Production",
|
||||
"Preview",
|
||||
"Development"
|
||||
]}
|
||||
selected={integrationTarget}
|
||||
onChange={setIntegrationTarget}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-end">
|
||||
{integration.isActive ? (
|
||||
<div className="max-w-5xl flex flex-row items-center bg-white/5 p-2 rounded-md px-4">
|
||||
<FontAwesomeIcon
|
||||
@@ -112,7 +130,8 @@ const Integration = ({
|
||||
integrationId: integration._id,
|
||||
environment: envMapping[integrationEnvironment],
|
||||
app: integrationApp,
|
||||
isActive: true
|
||||
isActive: true,
|
||||
target: integrationTarget.toLowerCase()
|
||||
});
|
||||
router.reload();
|
||||
}}
|
||||
@@ -133,12 +152,9 @@ const Integration = ({
|
||||
icon={faX}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div></div>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export default Integration;
|
||||
@@ -16,7 +16,7 @@ const ProjectIntegrationSection = ({
|
||||
return integrations.length > 0 ? (
|
||||
<div className="mb-12">
|
||||
<div className="flex flex-col justify-between items-start mx-4 mb-4 mt-6 text-xl max-w-5xl px-2">
|
||||
<h1 className="font-semibold text-3xl">Current Project Integrations</h1>
|
||||
<h1 className="font-semibold text-3xl">Current Integrations</h1>
|
||||
<p className="text-base text-gray-400">
|
||||
Manage your integrations of Infisical with third-party services.
|
||||
</p>
|
||||
|
||||
@@ -9,13 +9,15 @@ import SecurityClient from "~/utilities/SecurityClient";
|
||||
* @param {String} obj.app - name of app
|
||||
* @param {String} obj.environment - project environment to push secrets from
|
||||
* @param {Boolean} obj.isActive - active state
|
||||
* @param {String} obj.target - (optional) target (environment)
|
||||
* @returns
|
||||
*/
|
||||
const updateIntegration = ({
|
||||
integrationId,
|
||||
app,
|
||||
environment,
|
||||
isActive
|
||||
environment,
|
||||
isActive,
|
||||
target
|
||||
}) => {
|
||||
return SecurityClient.fetchCall(
|
||||
"/api/v1/integration/" + integrationId,
|
||||
@@ -27,7 +29,8 @@ const updateIntegration = ({
|
||||
body: JSON.stringify({
|
||||
app,
|
||||
environment,
|
||||
isActive
|
||||
isActive,
|
||||
target
|
||||
}),
|
||||
}
|
||||
).then(async (res) => {
|
||||
|
||||
@@ -16,17 +16,17 @@ export default function Heroku() {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
useEffect(async () => {
|
||||
try {
|
||||
if (state == localStorage.getItem("latestCSRFToken")) {
|
||||
if (state === localStorage.getItem('latestCSRFToken')) {
|
||||
localStorage.removeItem('latestCSRFToken');
|
||||
await AuthorizeIntegration({
|
||||
workspaceId: localStorage.getItem("projectData.id"),
|
||||
workspaceId: localStorage.getItem('projectData.id'),
|
||||
code,
|
||||
integration: "heroku",
|
||||
});
|
||||
router.push("/integrations/" + localStorage.getItem("projectData.id"));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.log("Error - Not logged in yet");
|
||||
console.error('Heroku integration error: ', error);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
@@ -113,7 +113,7 @@ export default function Integrations() {
|
||||
* @returns
|
||||
*/
|
||||
const handleIntegrationOption = async ({ integrationOption }) => {
|
||||
// TODO: modularize
|
||||
// TODO: modularize and handle switch by slug
|
||||
|
||||
// generate CSRF token for OAuth2 code-token exchange integrations
|
||||
const csrfToken = crypto.randomBytes(16).toString("hex");
|
||||
@@ -121,8 +121,13 @@ export default function Integrations() {
|
||||
|
||||
switch (integrationOption.name) {
|
||||
case 'Heroku':
|
||||
window.location = `https://id.heroku.com/oauth/authorize?client_id=7b1311a1-1cb2-4938-8adf-f37a399ec41b&response_type=code&scope=write-protected&state=${csrfToken}`;
|
||||
return;
|
||||
// console.log('Heroku integration ', integrationOption);
|
||||
window.location = `https://id.heroku.com/oauth/authorize?client_id=${integrationOption.clientId}&response_type=code&scope=write-protected&state=${csrfToken}`;
|
||||
break;
|
||||
case 'Vercel':
|
||||
console.log('Vercel integration ', integrationOption);
|
||||
window.location = `https://vercel.com/integrations/infisical/new?state=${csrfToken}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,17 +7,40 @@ import AuthorizeIntegration from "./api/integrations/authorizeIntegration";
|
||||
export default function Vercel() {
|
||||
const router = useRouter();
|
||||
const parsedUrl = queryString.parse(router.asPath.split("?")[1]);
|
||||
const code = parsedUrl.code;
|
||||
const state = parsedUrl.state
|
||||
|
||||
// modify comment here
|
||||
|
||||
/**
|
||||
* 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);
|
||||
console.log('parsedUrl for vercel ', parsedUrl);
|
||||
if (state === localStorage.getItem('latestCSRFToken')) {
|
||||
localStorage.removeItem('latestCSRFToken');
|
||||
|
||||
console.log('integ');
|
||||
console.log('code', code);
|
||||
console.log('state', state);
|
||||
|
||||
await AuthorizeIntegration({
|
||||
workspaceId: localStorage.getItem('projectData.id'),
|
||||
code,
|
||||
integration: "vercel"
|
||||
});
|
||||
|
||||
router.push("/integrations/" + localStorage.getItem("projectData.id"));
|
||||
}
|
||||
// parsedUrl.code
|
||||
// parsedUrl.configurationId
|
||||
// parsedUrl.next
|
||||
// parsedUrl.state
|
||||
try {
|
||||
|
||||
|
||||
} catch (err) {
|
||||
|
||||
console.error('Vercel integration error: ', err);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
"image": "Heroku",
|
||||
"isAvailable": true,
|
||||
"type": "oauth2",
|
||||
"clientId": "bc132901-935a-4590-b010-f1857efc380d"
|
||||
"clientId": "7b1311a1-1cb2-4938-8adf-f37a399ec41b"
|
||||
},
|
||||
{
|
||||
"name": "Netlify",
|
||||
"name": "Vercel",
|
||||
"slug": "netlify",
|
||||
"image": "Netlify",
|
||||
"isAvailable": false,
|
||||
"type": "oauth2",
|
||||
"isAvailable": true,
|
||||
"type": "vercel",
|
||||
"clientId": ""
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user