Skip to content

Commit

Permalink
Merge pull request #114 from l3montree-dev/feature/child-projects
Browse files Browse the repository at this point in the history
Feature/child projects
  • Loading branch information
timbastin authored Dec 27, 2024
2 parents d6fd1f3 + d705f62 commit c89113f
Show file tree
Hide file tree
Showing 26 changed files with 1,309 additions and 648 deletions.
72 changes: 66 additions & 6 deletions leaks-baseline.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,71 @@
[
{
"Description": "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.",
"StartLine": 9,
"EndLine": 9,
"StartColumn": 5,
"EndColumn": 79,
"Match": "Secret\": \"d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82\"",
"Secret": "d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82",
"File": "leaks-baseline.json",
"SymlinkFile": "",
"Commit": "a8aa8e4025ffdacc24b6ac5e3c8c7076fe8f1760",
"Entropy": 3.8594732,
"Author": "timbastin",
"Email": "[email protected]",
"Date": "2024-08-14T17:37:24Z",
"Message": "adds gitleaks baseline",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "a8aa8e4025ffdacc24b6ac5e3c8c7076fe8f1760:leaks-baseline.json:generic-api-key:9"
},
{
"Description": "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.",
"StartLine": 29,
"EndLine": 29,
"StartColumn": 5,
"EndColumn": 79,
"Match": "Secret\": \"d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82\"",
"Secret": "d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82",
"File": "leaks-baseline.json",
"SymlinkFile": "",
"Commit": "a8aa8e4025ffdacc24b6ac5e3c8c7076fe8f1760",
"Entropy": 3.8594732,
"Author": "timbastin",
"Email": "[email protected]",
"Date": "2024-08-14T17:37:24Z",
"Message": "adds gitleaks baseline",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "a8aa8e4025ffdacc24b6ac5e3c8c7076fe8f1760:leaks-baseline.json:generic-api-key:29"
},
{
"Description": "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.",
"StartLine": 49,
"EndLine": 49,
"StartColumn": 5,
"EndColumn": 79,
"Match": "Secret\": \"cb76b2575012202a6fdf4bdcabb35f0cb873e54eddfd1795bced05f1cd3c361a\"",
"Secret": "cb76b2575012202a6fdf4bdcabb35f0cb873e54eddfd1795bced05f1cd3c361a",
"File": "leaks-baseline.json",
"SymlinkFile": "",
"Commit": "a8aa8e4025ffdacc24b6ac5e3c8c7076fe8f1760",
"Entropy": 3.8406746,
"Author": "timbastin",
"Email": "[email protected]",
"Date": "2024-08-14T17:37:24Z",
"Message": "adds gitleaks baseline",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "a8aa8e4025ffdacc24b6ac5e3c8c7076fe8f1760:leaks-baseline.json:generic-api-key:49"
},
{
"Description": "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.",
"StartLine": 185,
"EndLine": 185,
"StartColumn": 145,
"StartColumn": 143,
"EndColumn": 216,
"Match": "token=\"d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82\"",
"Match": "--token=\"d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82\"",
"Secret": "d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82",
"File": "README.md",
"SymlinkFile": "",
Expand All @@ -23,9 +83,9 @@
"Description": "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.",
"StartLine": 188,
"EndLine": 188,
"StartColumn": 170,
"StartColumn": 168,
"EndColumn": 241,
"Match": "token=\"d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82\"",
"Match": "--token=\"d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82\"",
"Secret": "d4ff2f36b983b69dd36e441f58fcc0bc4f372ace1d12ecc040f1d860ea254f82",
"File": "README.md",
"SymlinkFile": "",
Expand All @@ -43,9 +103,9 @@
"Description": "Detected a Generic API Key, potentially exposing access to various services and sensitive operations.",
"StartLine": 178,
"EndLine": 178,
"StartColumn": 188,
"StartColumn": 186,
"EndColumn": 259,
"Match": "token=\"cb76b2575012202a6fdf4bdcabb35f0cb873e54eddfd1795bced05f1cd3c361a\"",
"Match": "--token=\"cb76b2575012202a6fdf4bdcabb35f0cb873e54eddfd1795bced05f1cd3c361a\"",
"Secret": "cb76b2575012202a6fdf4bdcabb35f0cb873e54eddfd1795bced05f1cd3c361a",
"File": "README.md",
"SymlinkFile": "",
Expand Down
240 changes: 240 additions & 0 deletions src/components/ConnectToRepoSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
import React, { FunctionComponent, useState } from "react";
import Section from "./common/Section";
import ListItem from "./common/ListItem";
import { Button, buttonVariants } from "./ui/button";
import { Combobox } from "./common/Combobox";
import useRepositorySearch from "../hooks/useRepositorySearch";
import Image from "next/image";
import { useActiveOrg } from "../hooks/useActiveOrg";
import Link from "next/link";
import { cn } from "../lib/utils";
import Callout from "./common/Callout";

interface Props {
parentRepositoryId?: string;
parentRepositoryName?: string;
repositoryName?: string;
repositoryId?: string;
repositories: Array<{ value: string; label: string }> | null; // will be null, if repos could not be loaded - probably due to a missing github app installation
onUpdate: (
data: Partial<{ repositoryName: string; repositoryId: string }>,
) => Promise<void>;
}
const ConnectToRepoSection: FunctionComponent<Props> = ({
repositoryName,
repositoryId,
repositories,
onUpdate,
parentRepositoryId,
parentRepositoryName,
}) => {
const activeOrg = useActiveOrg();
const { repos, searchLoading, handleSearchRepos } =
useRepositorySearch(repositories);
const [editRepo, setEditRepo] = useState(!Boolean(repositoryId));

const [selectedRepo, setSelectedRepo] = useState<{
id: string;
name: string;
} | null>(repositoryId ? { id: repositoryId!, name: repositoryName! } : null);

return (
<Section
title="Connect to a repository"
description="Connect this asset to a repository to enable automatic scanning and other features."
>
{Boolean(parentRepositoryId) && (
<div>
<ListItem
Title={
<>
<span className="relative mr-2 inline-flex h-3 w-3">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-500 opacity-75"></span>
<span className="relative inline-flex h-3 w-3 rounded-full bg-green-500"></span>
</span>

{parentRepositoryName}
</>
}
description={
"This asset is connected to a " +
(repositoryId?.startsWith("github:") ? "GitHub" : "GitLab") +
" repository "
}
Button={
<>
<Button
variant={"destructiveOutline"}
onClick={async () => {
await onUpdate({ repositoryId: "" });
setEditRepo(true);
}}
>
Remove connection
</Button>
<Button
variant={"secondary"}
onClick={() => {
setEditRepo(true);
}}
>
Change
</Button>
</>
}
/>
</div>
)}
{parentRepositoryId && (
<>
<hr />
<Callout intent="info">
The parent project is already connected to a repository. You can
override this connection by connecting this asset to a different
repository.
</Callout>
</>
)}
{Boolean(repositoryId) && repositories && !editRepo ? (
<div>
<ListItem
Title={
<>
<span className="relative mr-2 inline-flex h-3 w-3">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-500 opacity-75"></span>
<span className="relative inline-flex h-3 w-3 rounded-full bg-green-500"></span>
</span>

{repositoryName}
</>
}
description={
"This asset is connected to a " +
(repositoryId?.startsWith("github:") ? "GitHub" : "GitLab") +
" repository "
}
Button={
<>
<Button
variant={"destructiveOutline"}
onClick={async () => {
await onUpdate({ repositoryId: "" });
setEditRepo(true);
}}
>
Remove connection
</Button>
<Button
variant={"secondary"}
onClick={() => {
setEditRepo(true);
}}
>
Change
</Button>
</>
}
/>
</div>
) : repositories && editRepo ? (
<ListItem
Title={
<div className="flex flex-row gap-2">
<div className="flex-1">
<Combobox
onValueChange={handleSearchRepos}
placeholder="Search repository..."
items={repos}
loading={searchLoading}
onSelect={(repoId: string) => {
const repo = repos.find((r) => r.value === repoId);

if (repo) {
setSelectedRepo({ id: repo.value, name: repo.label });
}
}}
value={selectedRepo?.id ?? undefined}
emptyMessage="No repositories found"
/>
</div>
<Button
onClick={async () => {
if (selectedRepo) {
await onUpdate({
repositoryId: selectedRepo.id,
repositoryName: selectedRepo.name,
});
setEditRepo(false);
}
}}
disabled={!Boolean(selectedRepo)}
>
Connect
</Button>
</div>
}
description={
"Select a repository to connect this asset to. This list contains all repositories of all GitHub App Installations belonging to this organization."
}
/>
) : (
<>
<ListItem
Title={
<div className="flex flex-row items-center">
<Image
src="/assets/github.svg"
alt="GitHub"
width={20}
height={20}
className="mr-2 inline-block dark:invert"
/>
Add a GitHub App
</div>
}
description="DevGuard uses a GitHub App to access your repositories and interact with your code. Due to the excessive permissions granted to the app, it can only be done by the organization owner."
Button={
<Link
className={cn(
buttonVariants({ variant: "secondary" }),
"hover:no-underline",
)}
href={"/" + activeOrg.slug + "/settings"}
>
Go to organization settings
</Link>
}
/>
<ListItem
Title={
<div className="flex flex-row items-center">
<Image
src="/assets/gitlab.svg"
alt="GitHub"
width={20}
height={20}
className="mr-2 inline-block"
/>
Integrate with GitLab
</div>
}
description="DevGuard uses a personal, group or project access token to access your repositories and interact with your code. Due to the excessive permissions granted to the app, it can only be done by the organization owner."
Button={
<Link
className={cn(
buttonVariants({ variant: "secondary" }),
"hover:no-underline",
)}
href={"/" + activeOrg.slug + "/settings"}
>
Go to organization settings
</Link>
}
/>
</>
)}
</Section>
);
};

export default ConnectToRepoSection;
13 changes: 3 additions & 10 deletions src/components/common/AssetTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { useActiveProject } from "@/hooks/useActiveProject";
import Link from "next/link";
import React from "react";
import { Badge } from "../ui/badge";
import { ProjectElement } from "./ProjectTitle";

const AssetTitle = () => {
const activeOrg = useActiveOrg();
const project = useActiveProject();
const project = useActiveProject()!;
const asset = useActiveAsset();

return (
Expand All @@ -22,15 +23,7 @@ const AssetTitle = () => {
</Badge>
</Link>
<span className="opacity-75">/</span>
<Link
className="flex flex-row items-center gap-1 !text-white hover:no-underline"
href={`/${activeOrg.slug}/projects/${project?.slug}/assets`}
>
{project?.name}
<Badge className="font-body font-normal !text-white" variant="outline">
Project
</Badge>
</Link>
<ProjectElement project={project} activeOrg={activeOrg} />
<span className="opacity-75">/</span>
<Link
className="flex items-center gap-1 text-white hover:no-underline"
Expand Down
Loading

0 comments on commit c89113f

Please sign in to comment.