feat: added handling of using same connection with different projects

This commit is contained in:
Sheen Capadngan
2024-10-15 03:37:11 +08:00
parent faf2c6df90
commit 73382c5363
15 changed files with 287 additions and 38 deletions
@@ -24,7 +24,7 @@ export default function GithubIntegrationAuthModeSelectionPage() {
<Card className="mb-12 max-w-lg rounded-md border border-mineshaft-600">
<CardTitle
className="px-6 text-left text-xl"
subTitle="Select how you'd like to integrate with GitHub. For more precise control, we recommend using the GitHub App method."
subTitle="Select how you'd like to integrate with GitHub. We recommend using the GitHub App method for fine-grained access."
>
<div className="flex flex-row items-center">
<div className="flex items-center pb-0.5">
@@ -61,7 +61,7 @@ export default function GithubIntegrationAuthModeSelectionPage() {
router.push("/integrations/select-integration-auth?integrationSlug=github");
}}
>
Connect with Github App
Connect with App
</Button>
<Button
colorSchema="primary"
@@ -78,7 +78,7 @@ export default function GithubIntegrationAuthModeSelectionPage() {
);
}}
>
Connect with Github OAuth
Connect with OAuth
</Button>
</div>
</Card>
@@ -6,46 +6,93 @@ import Image from "next/image";
import { useRouter } from "next/router";
import { Button, Card, CardTitle } from "@app/components/v2";
import { useWorkspace } from "@app/context";
import { useGetCloudIntegrations, useGetWorkspaceAuthorizations } from "@app/hooks/api";
import { useOrganization, useWorkspace } from "@app/context";
import {
useDuplicateIntegrationAuth,
useGetCloudIntegrations,
useGetOrgIntegrationAuths
} from "@app/hooks/api";
import { IntegrationAuth } from "@app/hooks/api/types";
export default function SelectIntegrationAuthPage() {
const router = useRouter();
const { data: cloudIntegrations } = useGetCloudIntegrations();
const { currentOrg } = useOrganization();
const { currentWorkspace } = useWorkspace();
const workspaceId = currentWorkspace?.id || "";
const orgId = currentOrg?.id || "";
const integrationSlug = router.query.integrationSlug as string;
const currentIntegration = cloudIntegrations?.find(
(integration) => integration.slug === integrationSlug
);
const { mutateAsync: duplicateIntegrationAuth, isLoading: isIntegrationAuthSelectLoading } =
useDuplicateIntegrationAuth();
// for Github, we want to reuse the same connection across the Infisical organization
// when we do need to reuse this page for other integrations, add handling to fetch workspace integration auths instead
const { data: integrationAuths, isLoading: isLoadingIntegrationAuths } =
useGetWorkspaceAuthorizations(
workspaceId,
useCallback((data: IntegrationAuth[]) => {
const filteredIntegrationAuths = data.filter(
(integrationAuth) => integrationAuth.integration === integrationSlug
);
if (integrationSlug === "github") {
// for now, we only display the integration auths for Github apps
return filteredIntegrationAuths.filter((integrationAuth) =>
Boolean(integrationAuth.metadata?.installationName)
useGetOrgIntegrationAuths(
orgId,
useCallback(
(data: IntegrationAuth[]) => {
const filteredIntegrationAuths = data.filter(
(integrationAuth) => integrationAuth.integration === integrationSlug
);
}
return [];
}, [])
if (integrationSlug === "github") {
const sameProjectIntegrationAuths = filteredIntegrationAuths.filter(
(auth) => auth.projectId === currentWorkspace?.id
);
const differentProjectIntegrationAuths = filteredIntegrationAuths.filter(
(auth) => auth.projectId !== currentWorkspace?.id
);
const installationIds = new Set<string>();
// for now, we only display the integration auths for Github apps
return (
// we concatenate it this way so that integration auths from the same project are prioritized for display
sameProjectIntegrationAuths
.concat(differentProjectIntegrationAuths)
.filter((integrationAuth) => Boolean(integrationAuth.metadata?.installationId))
// we filter it so that we only show unique installations because the same installation/connection
// can be used in multiple integration auths
.filter((integrationAuth) => {
const isProcessedInstallationId = installationIds.has(
integrationAuth.metadata.installationId as string
);
if (!isProcessedInstallationId) {
installationIds.add(integrationAuth.metadata.installationId as string);
}
return !isProcessedInstallationId;
})
);
}
return [];
},
[integrationSlug]
)
);
const logo = integrationSlug === "github" ? "/images/integrations/GitHub.png" : "";
const handleConnectionSelect = (integrationAuthId: string) => {
const handleConnectionSelect = async (integrationAuth: IntegrationAuth) => {
if (integrationSlug === "github") {
router.push(`/integrations/github/create?integrationAuthId=${integrationAuthId}`);
if (integrationAuth.projectId === currentWorkspace?.id) {
router.push(`/integrations/github/create?integrationAuthId=${integrationAuth.id}`);
} else {
// we create a copy of the existing integration auth from another project to the current project
const newIntegrationAuth = await duplicateIntegrationAuth({
projectId: currentWorkspace?.id || "",
integrationAuthId: integrationAuth.id
});
router.push(`/integrations/github/create?integrationAuthId=${newIntegrationAuth.id}`);
}
}
};
@@ -93,10 +140,11 @@ export default function SelectIntegrationAuthPage() {
colorSchema="gray"
variant="outline"
className="mt-3 w-3/4"
isDisabled={isIntegrationAuthSelectLoading}
key={integrationAuth.id}
size="sm"
type="submit"
onClick={() => handleConnectionSelect(integrationAuth.id)}
onClick={() => handleConnectionSelect(integrationAuth)}
>
{connectionName}
</Button>