mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-13 22:29:33 +00:00
Update org settings > general tab ui
This commit is contained in:
@@ -21,10 +21,10 @@ import {
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
const LDAPFormSchema = z.object({
|
||||
url: z.string().min(1, "URL is requiredx"),
|
||||
bindDN: z.string().min(1, "Bind DN is requiredx"),
|
||||
bindPass: z.string().min(1, "Bind Pass is required"),
|
||||
searchBase: z.string().min(1, "Search Base is required"),
|
||||
url: z.string().default(""),
|
||||
bindDN: z.string().default(""),
|
||||
bindPass: z.string().default(""),
|
||||
searchBase: z.string().default(""),
|
||||
caCert: z.string().optional()
|
||||
});
|
||||
|
||||
@@ -122,7 +122,7 @@ export const LDAPModal = ({
|
||||
reset();
|
||||
}}
|
||||
>
|
||||
<ModalContent title="Add LDAP">
|
||||
<ModalContent title="Manage LDAP configuration">
|
||||
<form onSubmit={handleSubmit(onSSOModalSubmit)}>
|
||||
<Controller
|
||||
control={control}
|
||||
|
||||
+2
-2
@@ -60,7 +60,7 @@ export const OrgGeneralAuthSection = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="py-4">
|
||||
{/* <div className="py-4">
|
||||
<div className="mb-2 flex justify-between">
|
||||
<h3 className="text-md text-mineshaft-100">Allow users to send invites</h3>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Sso}>
|
||||
@@ -75,7 +75,7 @@ export const OrgGeneralAuthSection = () => {
|
||||
</OrgPermissionCan>
|
||||
</div>
|
||||
<p className="text-sm text-mineshaft-300">Allow members to invite new users to this organization</p>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="py-4">
|
||||
<div className="mb-2 flex justify-between">
|
||||
<h3 className="text-md text-mineshaft-100">Enforce SAML SSO</h3>
|
||||
|
||||
+19
-17
@@ -104,24 +104,26 @@ export const OrgLDAPSection = (): JSX.Element => {
|
||||
</div>
|
||||
<p className="text-sm text-mineshaft-300">Manage LDAP authentication configuration</p>
|
||||
</div>
|
||||
<div className="py-4">
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
<h2 className="text-md text-mineshaft-100">Enable LDAP</h2>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Ldap}>
|
||||
{(isAllowed) => (
|
||||
<Switch
|
||||
id="enable-saml-sso"
|
||||
onCheckedChange={(value) => handleLDAPToggle(value)}
|
||||
isChecked={data ? data.isActive : false}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Enable
|
||||
</Switch>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
{data && (
|
||||
<div className="py-4">
|
||||
<div className="mb-2 flex items-center justify-between">
|
||||
<h2 className="text-md text-mineshaft-100">Enable LDAP</h2>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Ldap}>
|
||||
{(isAllowed) => (
|
||||
<Switch
|
||||
id="enable-saml-sso"
|
||||
onCheckedChange={(value) => handleLDAPToggle(value)}
|
||||
isChecked={data ? data.isActive : false}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Enable
|
||||
</Switch>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
</div>
|
||||
<p className="text-sm text-mineshaft-300">Allow members to authenticate into Infisical with LDAP</p>
|
||||
</div>
|
||||
<p className="text-sm text-mineshaft-300">Allow members to authenticate into Infisical with LDAP</p>
|
||||
</div>
|
||||
)}
|
||||
<LDAPModal
|
||||
popUp={popUp}
|
||||
handlePopUpClose={handlePopUpClose}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import * as yup from "yup";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
import {
|
||||
@@ -32,16 +32,16 @@ const ssoAuthProviders = [
|
||||
{ label: "Google SAML", value: AuthProvider.GOOGLE_SAML }
|
||||
];
|
||||
|
||||
const schema = yup
|
||||
const schema = z
|
||||
.object({
|
||||
authProvider: yup.string().required("SSO Type is required"),
|
||||
entryPoint: yup.string().required("IdP entrypoint is required"),
|
||||
issuer: yup.string().required("Issuer string is required"),
|
||||
cert: yup.string().required("IdP's public signing certificate is required")
|
||||
authProvider: z.string().min(1, "SSO Type is required"),
|
||||
entryPoint: z.string().default(""),
|
||||
issuer: z.string().default(""),
|
||||
cert: z.string().default("")
|
||||
})
|
||||
.required();
|
||||
|
||||
export type AddSSOFormData = yup.InferType<typeof schema>;
|
||||
export type AddSSOFormData = z.infer<typeof schema>;
|
||||
|
||||
type Props = {
|
||||
popUp: UsePopUpState<["addSSO"]>;
|
||||
@@ -60,7 +60,7 @@ export const SSOModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
|
||||
defaultValues: {
|
||||
authProvider: AuthProvider.OKTA_SAML
|
||||
},
|
||||
resolver: yupResolver(schema)
|
||||
resolver: zodResolver(schema)
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -173,7 +173,7 @@ export const SSOModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props)
|
||||
reset();
|
||||
}}
|
||||
>
|
||||
<ModalContent title="Add SSO">
|
||||
<ModalContent title="Manage SAML configuration">
|
||||
<form onSubmit={handleSubmit(onSSOModalSubmit)}>
|
||||
<Controller
|
||||
control={control}
|
||||
|
||||
+16
-13
@@ -45,18 +45,21 @@ export const OrgDeleteSection = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<p className="mb-4 text-xl font-semibold text-mineshaft-100">Danger Zone</p>
|
||||
<Button
|
||||
isLoading={isLoading}
|
||||
colorSchema="danger"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
onClick={() => handlePopUpOpen("deleteOrg")}
|
||||
isDisabled={Boolean(membership && membership.role !== "admin")}
|
||||
>
|
||||
{`Delete ${currentOrg?.name}`}
|
||||
</Button>
|
||||
<>
|
||||
<hr className="border-mineshaft-600" />
|
||||
<div className="py-4">
|
||||
<p className="mb-4 text-md text-mineshaft-100">Danger Zone</p>
|
||||
<Button
|
||||
isLoading={isLoading}
|
||||
colorSchema="danger"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
onClick={() => handlePopUpOpen("deleteOrg")}
|
||||
isDisabled={Boolean(membership && membership.role !== "admin")}
|
||||
>
|
||||
{`Delete ${currentOrg?.name}`}
|
||||
</Button>
|
||||
</div>
|
||||
<DeleteActionModal
|
||||
isOpen={popUp.deleteOrg.isOpen}
|
||||
title="Are you sure want to delete this organization?"
|
||||
@@ -65,6 +68,6 @@ export const OrgDeleteSection = () => {
|
||||
deleteKey="confirm"
|
||||
onDeleteApproved={handleDeleteOrgSubmit}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+1
-4
@@ -3,15 +3,12 @@ import { useOrgPermission } from "@app/context";
|
||||
import { OrgDeleteSection } from "../OrgDeleteSection";
|
||||
import { OrgIncidentContactsSection } from "../OrgIncidentContactsSection";
|
||||
import { OrgNameChangeSection } from "../OrgNameChangeSection";
|
||||
import { OrgSlugChangeSection } from "../OrgSlugChangeSection";
|
||||
|
||||
export const OrgGeneralTab = () => {
|
||||
const { membership } = useOrgPermission();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-6">
|
||||
<OrgNameChangeSection />
|
||||
<OrgSlugChangeSection />
|
||||
<OrgIncidentContactsSection />
|
||||
{membership && membership.role === "admin" && <OrgDeleteSection />}
|
||||
</div>
|
||||
|
||||
+12
-9
@@ -18,9 +18,10 @@ export const OrgIncidentContactsSection = () => {
|
||||
const { permission } = useOrgPermission();
|
||||
|
||||
return (
|
||||
<div className="p-4 bg-mineshaft-900 mb-6 rounded-lg border border-mineshaft-600">
|
||||
<div className="flex justify-between mb-4">
|
||||
<p className="min-w-max text-xl font-semibold">{t("section.incident.incident-contacts")}</p>
|
||||
<>
|
||||
<hr className="border-mineshaft-600" />
|
||||
<div className="flex items-center justify-between pt-4">
|
||||
<p className="text-md text-mineshaft-100">{t("section.incident.incident-contacts")}</p>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Create} a={OrgPermissionSubjects.IncidentAccount}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
@@ -35,16 +36,18 @@ export const OrgIncidentContactsSection = () => {
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
</div>
|
||||
{permission.can(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount) ? (
|
||||
<OrgIncidentContactsTable />
|
||||
) : (
|
||||
<PermissionDeniedBanner />
|
||||
)}
|
||||
<div className="py-4">
|
||||
{permission.can(OrgPermissionActions.Read, OrgPermissionSubjects.IncidentAccount) ? (
|
||||
<OrgIncidentContactsTable />
|
||||
) : (
|
||||
<PermissionDeniedBanner />
|
||||
)}
|
||||
</div>
|
||||
<AddOrgIncidentContactModal
|
||||
popUp={popUp}
|
||||
handlePopUpClose={handlePopUpClose}
|
||||
handlePopUpToggle={handlePopUpToggle}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+37
-15
@@ -10,7 +10,12 @@ import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@a
|
||||
import { useUpdateOrg } from "@app/hooks/api";
|
||||
|
||||
const formSchema = yup.object({
|
||||
name: yup.string().required().label("Project Name")
|
||||
name: yup.string().required().label("Organization Name"),
|
||||
slug: yup
|
||||
.string()
|
||||
.matches(/^[a-zA-Z0-9-]+$/, "Name must only contain alphanumeric characters or hyphens")
|
||||
.required()
|
||||
.label("Organization Slug")
|
||||
});
|
||||
|
||||
type FormData = yup.InferType<typeof formSchema>;
|
||||
@@ -25,40 +30,44 @@ export const OrgNameChangeSection = (): JSX.Element => {
|
||||
|
||||
useEffect(() => {
|
||||
if (currentOrg) {
|
||||
reset({ name: currentOrg.name });
|
||||
reset({
|
||||
name: currentOrg.name,
|
||||
slug: currentOrg.slug
|
||||
});
|
||||
}
|
||||
}, [currentOrg]);
|
||||
|
||||
const onFormSubmit = async ({ name }: FormData) => {
|
||||
const onFormSubmit = async ({ name, slug }: FormData) => {
|
||||
try {
|
||||
if (!currentOrg?.id) return;
|
||||
if (name === "") return;
|
||||
|
||||
await mutateAsync({ orgId: currentOrg?.id, name });
|
||||
await mutateAsync({
|
||||
orgId: currentOrg?.id,
|
||||
name,
|
||||
slug
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully renamed organization",
|
||||
text: "Successfully updated organization details",
|
||||
type: "success"
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
createNotification({
|
||||
text: "Failed to rename organization",
|
||||
text: "Failed to update organization details",
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={handleSubmit(onFormSubmit)}
|
||||
className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"
|
||||
>
|
||||
<p className="mb-4 text-xl font-semibold text-mineshaft-100">Organization Name</p>
|
||||
<div className="mb-2 max-w-md">
|
||||
<form onSubmit={handleSubmit(onFormSubmit)} className="py-4">
|
||||
<div className="">
|
||||
<h2 className="mb-2 text-md text-mineshaft-100">Organization Name</h2>
|
||||
<Controller
|
||||
defaultValue=""
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl isError={Boolean(error)} errorText={error?.message}>
|
||||
<FormControl isError={Boolean(error)} errorText={error?.message} className="max-w-md">
|
||||
<Input placeholder="Acme Corp" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
@@ -66,6 +75,19 @@ export const OrgNameChangeSection = (): JSX.Element => {
|
||||
name="name"
|
||||
/>
|
||||
</div>
|
||||
<div className="py-4">
|
||||
<h2 className="mb-2 text-md text-mineshaft-100">Organization Slug</h2>
|
||||
<Controller
|
||||
defaultValue=""
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl isError={Boolean(error)} errorText={error?.message} className="max-w-md">
|
||||
<Input placeholder="acme" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
control={control}
|
||||
name="slug"
|
||||
/>
|
||||
</div>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Settings}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
@@ -81,4 +103,4 @@ export const OrgNameChangeSection = (): JSX.Element => {
|
||||
</OrgPermissionCan>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
};
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
import { useEffect } from "react";
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import * as yup from "yup";
|
||||
|
||||
import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider";
|
||||
import { OrgPermissionCan } from "@app/components/permissions";
|
||||
import { Button, FormControl, Input } from "@app/components/v2";
|
||||
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
||||
import { useUpdateOrg } from "@app/hooks/api";
|
||||
|
||||
const formSchema = yup.object({
|
||||
slug: yup
|
||||
.string()
|
||||
.matches(/^[a-zA-Z0-9-]+$/, "Name must only contain alphanumeric characters or hyphens")
|
||||
.required()
|
||||
.label("Project Slug")
|
||||
});
|
||||
|
||||
type FormData = yup.InferType<typeof formSchema>;
|
||||
|
||||
export const OrgSlugChangeSection = (): JSX.Element => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { createNotification } = useNotificationContext();
|
||||
const { handleSubmit, control, reset } = useForm<FormData>({
|
||||
resolver: yupResolver(formSchema)
|
||||
});
|
||||
const { mutateAsync, isLoading } = useUpdateOrg();
|
||||
|
||||
useEffect(() => {
|
||||
if (currentOrg) {
|
||||
reset({ slug: currentOrg.slug });
|
||||
}
|
||||
}, [currentOrg]);
|
||||
|
||||
const onFormSubmit = async ({ slug }: FormData) => {
|
||||
try {
|
||||
if (!currentOrg?.id) return;
|
||||
if (slug === "") return;
|
||||
|
||||
await mutateAsync({ orgId: currentOrg?.id, slug });
|
||||
createNotification({
|
||||
text: "Successfully updated organization slug",
|
||||
type: "success"
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
createNotification({
|
||||
text: "Failed to update organization slug",
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={handleSubmit(onFormSubmit)}
|
||||
className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"
|
||||
>
|
||||
<p className="mb-4 text-xl font-semibold text-mineshaft-100">Organization Slug</p>
|
||||
<div className="mb-2 max-w-md">
|
||||
<Controller
|
||||
defaultValue=""
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
<FormControl isError={Boolean(error)} errorText={error?.message}>
|
||||
<Input placeholder="acme" {...field} />
|
||||
</FormControl>
|
||||
)}
|
||||
control={control}
|
||||
name="slug"
|
||||
/>
|
||||
</div>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Settings}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
isLoading={isLoading}
|
||||
isDisabled={!isAllowed}
|
||||
colorSchema="primary"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { OrgSlugChangeSection } from "./OrgSlugChangeSection";
|
||||
Reference in New Issue
Block a user