mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-16 06:45:28 +00:00
merge main
This commit is contained in:
@@ -10,6 +10,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import queryString from "query-string";
|
||||
import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { SecretPathInput } from "@app/components/v2/SecretPathInput";
|
||||
import { useCreateIntegration } from "@app/hooks/api";
|
||||
import { IntegrationSyncBehavior } from "@app/hooks/api/integrations/types";
|
||||
@@ -19,9 +20,11 @@ import {
|
||||
Card,
|
||||
CardTitle,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Input,
|
||||
Select,
|
||||
SelectItem
|
||||
SelectItem,
|
||||
Switch
|
||||
} from "../../../components/v2";
|
||||
import { useGetIntegrationAuthById } from "../../../hooks/api/integrationAuth";
|
||||
import { useGetWorkspaceById } from "../../../hooks/api/workspace";
|
||||
@@ -39,7 +42,9 @@ const schema = z.object({
|
||||
secretPath: z.string().trim().min(1, { message: "Secret path is required" }),
|
||||
sourceEnvironment: z.string().trim().min(1, { message: "Source environment is required" }),
|
||||
initialSyncBehavior: z.nativeEnum(IntegrationSyncBehavior),
|
||||
secretPrefix: z.string().default("")
|
||||
secretPrefix: z.string().default(""),
|
||||
useLabels: z.boolean().default(false),
|
||||
azureLabel: z.string().min(1).optional()
|
||||
});
|
||||
|
||||
type TFormSchema = z.infer<typeof schema>;
|
||||
@@ -60,6 +65,7 @@ export default function AzureAppConfigurationCreateIntegration() {
|
||||
const router = useRouter();
|
||||
const {
|
||||
control,
|
||||
watch,
|
||||
setValue,
|
||||
handleSubmit,
|
||||
formState: { isSubmitting }
|
||||
@@ -85,16 +91,28 @@ export default function AzureAppConfigurationCreateIntegration() {
|
||||
}
|
||||
}, [workspace]);
|
||||
|
||||
const shouldUseLabels = watch("useLabels");
|
||||
|
||||
const handleIntegrationSubmit = async ({
|
||||
secretPath,
|
||||
useLabels,
|
||||
sourceEnvironment,
|
||||
baseUrl,
|
||||
initialSyncBehavior,
|
||||
secretPrefix
|
||||
secretPrefix,
|
||||
azureLabel
|
||||
}: TFormSchema) => {
|
||||
try {
|
||||
if (!integrationAuth?.id) return;
|
||||
|
||||
if (useLabels && !azureLabel) {
|
||||
createNotification({
|
||||
type: "error",
|
||||
text: "Label must be provided when 'Use Labels' is enabled"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await mutateAsync({
|
||||
integrationAuthId: integrationAuth?.id,
|
||||
isActive: true,
|
||||
@@ -103,7 +121,8 @@ export default function AzureAppConfigurationCreateIntegration() {
|
||||
secretPath,
|
||||
metadata: {
|
||||
initialSyncBehavior,
|
||||
secretPrefix
|
||||
secretPrefix,
|
||||
...(useLabels && { azureLabel })
|
||||
}
|
||||
});
|
||||
|
||||
@@ -155,35 +174,70 @@ export default function AzureAppConfigurationCreateIntegration() {
|
||||
</div>
|
||||
</CardTitle>
|
||||
<div className="px-6">
|
||||
<Controller
|
||||
control={control}
|
||||
name="sourceEnvironment"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Project Environment"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
<Select
|
||||
className="w-full border border-mineshaft-500"
|
||||
dropdownContainerClassName="max-w-full"
|
||||
value={field.value}
|
||||
onValueChange={(val) => {
|
||||
field.onChange(val);
|
||||
}}
|
||||
<div className="">
|
||||
<Controller
|
||||
control={control}
|
||||
name="sourceEnvironment"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
label="Project Environment"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
{workspace?.environments.map((sourceEnvironment) => (
|
||||
<SelectItem
|
||||
value={sourceEnvironment.slug}
|
||||
key={`source-environment-${sourceEnvironment.slug}`}
|
||||
<Select
|
||||
className="w-full border border-mineshaft-500"
|
||||
dropdownContainerClassName="max-w-full"
|
||||
value={field.value}
|
||||
onValueChange={(val) => {
|
||||
field.onChange(val);
|
||||
}}
|
||||
>
|
||||
{workspace?.environments.map((sourceEnvironment) => (
|
||||
<SelectItem
|
||||
value={sourceEnvironment.slug}
|
||||
key={`source-environment-${sourceEnvironment.slug}`}
|
||||
>
|
||||
{sourceEnvironment.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="mb-2 flex w-full flex-col gap-1">
|
||||
<Controller
|
||||
control={control}
|
||||
name="useLabels"
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<Switch
|
||||
id="use-environment-labels"
|
||||
onCheckedChange={(isChecked) => onChange(isChecked)}
|
||||
isChecked={value}
|
||||
>
|
||||
<FormLabel label="Use Labels" />
|
||||
</Switch>
|
||||
)}
|
||||
/>
|
||||
|
||||
{shouldUseLabels && (
|
||||
<Controller
|
||||
control={control}
|
||||
name="azureLabel"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
className=""
|
||||
// label="Label"
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error)}
|
||||
>
|
||||
{sourceEnvironment.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Input {...field} placeholder="pre-prod" />
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<Controller
|
||||
control={control}
|
||||
name="secretPath"
|
||||
|
||||
@@ -62,7 +62,8 @@ enum ProjectOrderBy {
|
||||
const formatTitle = (type: ProjectType) => {
|
||||
if (type === ProjectType.SecretManager) return "Secret Management";
|
||||
if (type === ProjectType.CertificateManager) return "Cert Management";
|
||||
return "Key Management";
|
||||
if (type === ProjectType.KMS) return "Key Management";
|
||||
return "SSH";
|
||||
};
|
||||
|
||||
const formatDescription = (type: ProjectType) => {
|
||||
@@ -70,7 +71,9 @@ const formatDescription = (type: ProjectType) => {
|
||||
return "Securely store, manage, and rotate various application secrets, such as database credentials, API keys, etc.";
|
||||
if (type === ProjectType.CertificateManager)
|
||||
return "Manage your PKI infrastructure and issue digital certificates for services, applications, and devices.";
|
||||
return "Centralize the management of keys for cryptographic operations, such as encryption and decryption.";
|
||||
if (type === ProjectType.KMS)
|
||||
return "Centralize the management of keys for cryptographic operations, such as encryption and decryption.";
|
||||
return "Generate SSH credentials to provide secure and centralized SSH access control for your infrastructure.";
|
||||
};
|
||||
|
||||
type Props = {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
import { ProductOverview } from "../secret-manager/overview";
|
||||
|
||||
const SshManagerOverviewPage = () => <ProductOverview type={ProjectType.SSH} />;
|
||||
|
||||
Object.assign(SshManagerOverviewPage, { requireAuth: true });
|
||||
|
||||
export default SshManagerOverviewPage;
|
||||
@@ -0,0 +1,21 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Head from "next/head";
|
||||
|
||||
import { IPAllowlistPage } from "@app/views/Project/IPAllowListPage";
|
||||
|
||||
const ProjectAllowlist = () => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t("common.head-title", { title: t("settings.project.title") })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Head>
|
||||
<IPAllowlistPage />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectAllowlist;
|
||||
|
||||
ProjectAllowlist.requireAuth = true;
|
||||
@@ -0,0 +1,18 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import Head from "next/head";
|
||||
|
||||
import { SshCaPage } from "@app/views/Project/SshCaPage";
|
||||
|
||||
export default function SshCa() {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>SSH Certificate Authority</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Head>
|
||||
<SshCaPage />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
SshCa.requireAuth = true;
|
||||
@@ -0,0 +1,20 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Head from "next/head";
|
||||
|
||||
import { IdentityDetailsPage } from "@app/views/Project/IdentityDetailsPage";
|
||||
|
||||
export default function ProjectIdentityDetailsPage() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Head>
|
||||
<IdentityDetailsPage />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
ProjectIdentityDetailsPage.requireAuth = true;
|
||||
@@ -0,0 +1,20 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Head from "next/head";
|
||||
|
||||
import { MemberDetailsPage } from "@app/views/Project/MemberDetailsPage";
|
||||
|
||||
export default function Page() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Head>
|
||||
<MemberDetailsPage />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Page.requireAuth = true;
|
||||
@@ -0,0 +1,21 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Head from "next/head";
|
||||
|
||||
import { MembersPage } from "@app/views/Project/MembersPage";
|
||||
|
||||
export default function WorkspaceMemberSettings() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t("common.head-title", { title: t("settings.members.title") })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Head>
|
||||
<MembersPage />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
WorkspaceMemberSettings.requireAuth = true;
|
||||
@@ -0,0 +1,20 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Head from "next/head";
|
||||
|
||||
import { RolePage } from "@app/views/Project/RolePage";
|
||||
|
||||
export default function Role() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t("common.head-title", { title: "Project Settings" })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Head>
|
||||
<RolePage />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Role.requireAuth = true;
|
||||
@@ -0,0 +1,22 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Head from "next/head";
|
||||
|
||||
import { ProjectSettingsPage } from "@app/views/Settings/ProjectSettingsPage";
|
||||
|
||||
const ProjectSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{t("common.head-title", { title: t("settings.project.title") })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
</Head>
|
||||
<ProjectSettingsPage />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProjectSettings;
|
||||
|
||||
ProjectSettings.requireAuth = true;
|
||||
@@ -0,0 +1,23 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Head from "next/head";
|
||||
|
||||
import { SshPage } from "@app/views/Project/SshPage";
|
||||
|
||||
const Ssh = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="h-full bg-bunker-800">
|
||||
<Head>
|
||||
<title>{t("common.head-title", { title: "Certificates" })}</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
<meta property="og:image" content="/images/message.png" />
|
||||
</Head>
|
||||
<SshPage />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Ssh;
|
||||
|
||||
Ssh.requireAuth = true;
|
||||
Reference in New Issue
Block a user