import { useEffect, useState } from "react"; import { Helmet } from "react-helmet"; import { Controller, useForm } from "react-hook-form"; import { faArrowUpRightFromSquare, faBookOpen, faBugs } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; import { useNavigate, useSearch } from "@tanstack/react-router"; import { motion } from "framer-motion"; import { z } from "zod"; import { Button, Card, CardTitle, FormControl, Input, Modal, ModalContent, Select, SelectItem, Switch, Tab, TabList, TabPanel, Tabs } from "@app/components/v2"; import { SecretPathInput } from "@app/components/v2/SecretPathInput"; import { ROUTE_PATHS } from "@app/const/routes"; import { useWorkspace } from "@app/context"; import { usePopUp } from "@app/hooks"; import { useCreateIntegration } from "@app/hooks/api"; import { useGetIntegrationAuthApps, useGetIntegrationAuthById, useGetIntegrationAuthTeams } from "@app/hooks/api/integrationAuth"; const gitLabEntities = [ { name: "Individual", value: "individual" }, { name: "Group", value: "group" } ] as const; enum TabSections { Connection = "connection", Options = "options" } const schema = z.object({ targetEntity: z.enum([gitLabEntities[0].value, gitLabEntities[1].value]), targetTeamId: z.string().optional(), selectedSourceEnvironment: z.string(), secretPath: z.string(), targetAppId: z.string(), targetEnvironment: z.string().optional(), secretPrefix: z.string().optional(), secretSuffix: z.string().optional(), shouldMaskSecrets: z.boolean().optional(), shouldProtectSecrets: z.boolean() }); type FormData = z.infer; export const GitlabConfigurePage = () => { const navigate = useNavigate(); const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([ "confirmIntegration" ] as const); const { currentWorkspace } = useWorkspace(); const { control, handleSubmit, setValue, watch } = useForm({ resolver: zodResolver(schema), defaultValues: { targetEntity: "individual", secretPath: "/", secretPrefix: "", secretSuffix: "", selectedSourceEnvironment: currentWorkspace.environments[0].slug } }); const selectedSourceEnvironment = watch("selectedSourceEnvironment"); const targetEntity = watch("targetEntity"); const targetTeamId = watch("targetTeamId"); const targetAppIdValue = watch("targetAppId"); const { mutateAsync } = useCreateIntegration(); const integrationAuthId = useSearch({ from: ROUTE_PATHS.SecretManager.Integratons.GitlabConfigurePage.id, select: (el) => el.integrationAuthId }); const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? ""); const { data: integrationAuthApps, isLoading: isIntegrationAuthAppsLoading } = useGetIntegrationAuthApps({ integrationAuthId: (integrationAuthId as string) ?? "", ...(targetTeamId ? { teamId: targetTeamId } : {}) }); const { data: integrationAuthTeams, isLoading: isintegrationAuthTeamsLoading } = useGetIntegrationAuthTeams((integrationAuthId as string) ?? ""); const [isLoading, setIsLoading] = useState(false); useEffect(() => { if (integrationAuthApps) { if (integrationAuthApps.length > 0) { setValue("targetAppId", String(integrationAuthApps[0].appId as string)); } else { setValue("targetAppId", "none"); } } }, [integrationAuthApps]); useEffect(() => { if (targetEntity === "group" && integrationAuthTeams && integrationAuthTeams.length > 0) { if (integrationAuthTeams) { if (integrationAuthTeams.length > 0) { // case: user is part of at least 1 group in GitLab setValue("targetTeamId", String(integrationAuthTeams[0].id)); } else { // case: user is not part of any groups in GitLab setValue("targetTeamId", "none"); } } } else if (targetEntity === "individual") { setValue("targetTeamId", undefined); } }, [targetEntity, integrationAuthTeams]); const onFormSubmit = async ({ selectedSourceEnvironment: sse, secretPath, targetAppId, targetEnvironment, secretPrefix, secretSuffix, shouldMaskSecrets, shouldProtectSecrets }: FormData) => { try { setIsLoading(true); if (!integrationAuth?.id) return; await mutateAsync({ integrationAuthId: integrationAuth?.id, isActive: true, app: integrationAuthApps?.find( (integrationAuthApp) => String(integrationAuthApp.appId) === targetAppId )?.name, appId: String(targetAppId), sourceEnvironment: sse, targetEnvironment: targetEnvironment === "" ? "*" : targetEnvironment, secretPath, metadata: { secretPrefix, secretSuffix, shouldMaskSecrets, shouldProtectSecrets } }); setIsLoading(false); navigate({ to: "/secret-manager/$projectId/integrations", params: { projectId: currentWorkspace.id } }); } catch (err) { console.error(err); setIsLoading(false); } }; return integrationAuth && selectedSourceEnvironment && integrationAuthApps && integrationAuthTeams ? (
{ if (!data.secretPrefix && !data.secretSuffix) { handlePopUpOpen("confirmIntegration", data); return; } onFormSubmit(data); })} className="flex h-full w-full flex-col items-center justify-center" > Set Up GitLab Integration
Gitlab logo
GitLab Integration
Docs
Connection Options
( )} /> ( )} /> ( )} /> {targetEntity === "group" && targetTeamId && ( ( )} /> )} { return ( ); }} /> ( )} />
( onChange(isChecked)} isChecked={value} >
Mark Infisical secrets in Gitlab as 'Masked' secrets
)} />
( onChange(isChecked)} isChecked={value} > Mark Infisical secrets in Gitlab as 'Protected' secrets )} />
( )} /> ( )} />
{/*
Pro Tip
After creating an integration, your secrets will start syncing immediately. This might cause an unexpected override of current secrets in GitLab with secrets from Infisical.
*/} handlePopUpToggle("confirmIntegration", isOpen)} >
} >

You're about to overwrite any existing secrets in GitLab.

To avoid this behavior, you may consider adding a secret prefix/suffix in the options tab.

) : (
Set Up GitLab Integration {isIntegrationAuthAppsLoading || isintegrationAuthTeamsLoading ? ( infisical loading indicator ) : (

Something went wrong. Please contact{" "} support@infisical.com {" "} if the issue persists.

)}
); };