mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-21 01:16:49 +00:00
Merge branch 'main' into ENG-3506-LDAP
This commit is contained in:
@@ -13,7 +13,7 @@ import {
|
||||
Select,
|
||||
SelectItem
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
useCreatePkiAlert,
|
||||
useGetPkiAlertById,
|
||||
@@ -60,15 +60,15 @@ type Props = {
|
||||
};
|
||||
|
||||
export const PkiAlertModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
const { data: alert } = useGetPkiAlertById(
|
||||
(popUp?.pkiAlert?.data as { alertId: string })?.alertId || ""
|
||||
);
|
||||
|
||||
const { data: pkiCollections } = useListWorkspacePkiCollections({
|
||||
workspaceId: projectId
|
||||
projectId
|
||||
});
|
||||
|
||||
const { mutateAsync: createPkiAlert } = useCreatePkiAlert();
|
||||
|
||||
@@ -4,7 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { useDeletePkiAlert } from "@app/hooks/api";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -12,8 +12,8 @@ import { PkiAlertModal } from "./PkiAlertModal";
|
||||
import { PkiAlertsTable } from "./PkiAlertsTable";
|
||||
|
||||
export const PkiAlertsSection = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
const { mutateAsync: deletePkiAlert } = useDeletePkiAlert();
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { useListWorkspacePkiAlerts } from "@app/hooks/api";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -24,11 +24,11 @@ type Props = {
|
||||
};
|
||||
|
||||
export const PkiAlertsTable = ({ handlePopUpOpen }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
const { data, isPending } = useListWorkspacePkiAlerts({
|
||||
workspaceId: projectId
|
||||
projectId
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -6,7 +6,7 @@ import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
useCreatePkiCollection,
|
||||
useGetPkiCollectionById,
|
||||
@@ -28,8 +28,8 @@ type Props = {
|
||||
|
||||
export const PkiCollectionModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const navigate = useNavigate();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
const { data: pkiCollection } = useGetPkiCollectionById(
|
||||
(popUp?.pkiCollection?.data as { collectionId: string })?.collectionId || ""
|
||||
|
||||
@@ -4,7 +4,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { useDeletePkiCollection } from "@app/hooks/api";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -12,8 +12,8 @@ import { PkiCollectionModal } from "./PkiCollectionModal";
|
||||
import { PkiCollectionTable } from "./PkiCollectionTable";
|
||||
|
||||
export const PkiCollectionSection = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
const { mutateAsync: deletePkiCollection } = useDeletePkiCollection();
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { useListWorkspacePkiCollections } from "@app/hooks/api";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -32,11 +32,11 @@ type Props = {
|
||||
|
||||
export const PkiCollectionTable = ({ handlePopUpOpen }: Props) => {
|
||||
const navigate = useNavigate();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
const { data, isPending } = useListWorkspacePkiCollections({
|
||||
workspaceId: projectId
|
||||
projectId
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { CaType, useDeleteCa, useGetCa } from "@app/hooks/api";
|
||||
import { TInternalCertificateAuthority } from "@app/hooks/api/ca/types";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
} from "./components";
|
||||
|
||||
const Page = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const navigate = useNavigate();
|
||||
const params = useParams({
|
||||
from: ROUTE_PATHS.CertManager.CertAuthDetailsByIDPage.id
|
||||
@@ -38,11 +38,11 @@ const Page = () => {
|
||||
const { caName } = params as { caName: string };
|
||||
const { data } = useGetCa({
|
||||
caName,
|
||||
projectId: currentWorkspace?.id || "",
|
||||
projectId: currentProject?.id || "",
|
||||
type: CaType.INTERNAL
|
||||
}) as { data: TInternalCertificateAuthority };
|
||||
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
const { mutateAsync: deleteCa } = useDeleteCa();
|
||||
|
||||
@@ -55,11 +55,11 @@ const Page = () => {
|
||||
|
||||
const onRemoveCaSubmit = async () => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await deleteCa({
|
||||
caName,
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
type: CaType.INTERNAL
|
||||
});
|
||||
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@ import { format } from "date-fns";
|
||||
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { Button, IconButton, Tooltip } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { useTimedReset } from "@app/hooks";
|
||||
import { CaStatus, CaType, InternalCaType, useGetCa } from "@app/hooks/api";
|
||||
import { caStatusToNameMap, caTypeToNameMap } from "@app/hooks/api/ca/constants";
|
||||
@@ -21,7 +21,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const [copyTextId, isCopyingId, setCopyTextId] = useTimedReset<string>({
|
||||
initialState: "Copy ID to clipboard"
|
||||
});
|
||||
@@ -31,7 +31,7 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
|
||||
|
||||
const { data } = useGetCa({
|
||||
caName,
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
type: CaType.INTERNAL
|
||||
});
|
||||
|
||||
|
||||
+3
-3
@@ -13,7 +13,7 @@ import {
|
||||
Select,
|
||||
SelectItem
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
CaRenewalType,
|
||||
useRenewCa
|
||||
@@ -45,8 +45,8 @@ type Props = {
|
||||
};
|
||||
|
||||
export const CaRenewalModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectSlug = currentWorkspace?.slug || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectSlug = currentProject?.slug || "";
|
||||
|
||||
const popUpData = popUp?.renewCa?.data as {
|
||||
caId: string;
|
||||
|
||||
+5
-5
@@ -8,7 +8,7 @@ import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FormControl, IconButton, TextArea, Tooltip } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { useTimedReset } from "@app/hooks";
|
||||
import { useGetCaCsr, useImportCaCertificate } from "@app/hooks/api";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
@@ -26,7 +26,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const ExternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const [copyTextCaCsr, isCopyingCaCsr, setCopyTextCaCsr] = useTimedReset<string>({
|
||||
initialState: "Copy to clipboard"
|
||||
});
|
||||
@@ -41,7 +41,7 @@ export const ExternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
|
||||
});
|
||||
|
||||
const { data: csr } = useGetCaCsr(caId);
|
||||
const { mutateAsync: importCaCertificate } = useImportCaCertificate(currentWorkspace.id);
|
||||
const { mutateAsync: importCaCertificate } = useImportCaCertificate(currentProject.id);
|
||||
|
||||
useEffect(() => {
|
||||
reset();
|
||||
@@ -49,11 +49,11 @@ export const ExternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
|
||||
|
||||
const onFormSubmit = async ({ certificate, certificateChain }: FormData) => {
|
||||
try {
|
||||
if (!csr || !caId || !currentWorkspace?.slug) return;
|
||||
if (!csr || !caId || !currentProject?.slug) return;
|
||||
|
||||
await importCaCertificate({
|
||||
caId,
|
||||
projectSlug: currentWorkspace?.slug,
|
||||
projectSlug: currentProject?.slug,
|
||||
certificate,
|
||||
certificateChain
|
||||
});
|
||||
|
||||
+6
-6
@@ -6,7 +6,7 @@ import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FormControl, Input, Select, SelectItem } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
CaStatus,
|
||||
useGetCaById,
|
||||
@@ -46,16 +46,16 @@ type Props = {
|
||||
};
|
||||
|
||||
export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { data: cas } = useListWorkspaceCas({
|
||||
projectSlug: currentWorkspace?.slug ?? "",
|
||||
projectId: currentProject.id,
|
||||
status: CaStatus.ACTIVE
|
||||
});
|
||||
const { data: ca } = useGetCaById(caId);
|
||||
const { data: csr } = useGetCaCsr(caId);
|
||||
|
||||
const { mutateAsync: signIntermediate } = useSignIntermediate();
|
||||
const { mutateAsync: importCaCertificate } = useImportCaCertificate(currentWorkspace.id);
|
||||
const { mutateAsync: importCaCertificate } = useImportCaCertificate(currentProject.id);
|
||||
|
||||
const {
|
||||
control,
|
||||
@@ -102,7 +102,7 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
|
||||
|
||||
const onFormSubmit = async ({ notAfter, maxPathLength }: FormData) => {
|
||||
try {
|
||||
if (!csr || !caId || !currentWorkspace?.slug) return;
|
||||
if (!csr || !caId || !currentProject?.slug) return;
|
||||
|
||||
const { certificate, certificateChain } = await signIntermediate({
|
||||
caId: parentCaId,
|
||||
@@ -114,7 +114,7 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
|
||||
|
||||
await importCaCertificate({
|
||||
caId,
|
||||
projectSlug: currentWorkspace?.slug,
|
||||
projectSlug: currentProject?.slug,
|
||||
certificate,
|
||||
certificateChain
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
Switch
|
||||
// DatePicker
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
CaStatus,
|
||||
CaType,
|
||||
@@ -84,10 +84,10 @@ const caTypes = [
|
||||
];
|
||||
|
||||
export const CaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { data: ca } = useGetCa({
|
||||
caName: (popUp?.ca?.data as { name: string })?.name || "",
|
||||
projectId: currentWorkspace?.id || "",
|
||||
projectId: currentProject?.id || "",
|
||||
type: CaType.INTERNAL
|
||||
});
|
||||
|
||||
@@ -178,13 +178,13 @@ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
configuration
|
||||
}: FormData) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
if (ca) {
|
||||
// update
|
||||
await updateMutateAsync({
|
||||
caName: ca.name,
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
name,
|
||||
type: CaType.INTERNAL,
|
||||
status,
|
||||
@@ -193,7 +193,7 @@ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
} else {
|
||||
// create
|
||||
await createMutateAsync({
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
name,
|
||||
type,
|
||||
status,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { CaStatus, CaType, useDeleteCa, useUpdateCa } from "@app/hooks/api";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -15,7 +15,7 @@ import { CaModal } from "./CaModal";
|
||||
import { CaTable } from "./CaTable";
|
||||
|
||||
export const CaSection = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { mutateAsync: deleteCa } = useDeleteCa();
|
||||
const { mutateAsync: updateCa } = useUpdateCa();
|
||||
|
||||
@@ -30,9 +30,9 @@ export const CaSection = () => {
|
||||
|
||||
const onRemoveCaSubmit = async (caName: string) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await deleteCa({ caName, projectId: currentWorkspace.id, type: CaType.INTERNAL });
|
||||
await deleteCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL });
|
||||
|
||||
createNotification({
|
||||
text: "Successfully deleted CA",
|
||||
@@ -50,9 +50,9 @@ export const CaSection = () => {
|
||||
|
||||
const onUpdateCaStatus = async ({ caName, status }: { caName: string; status: CaStatus }) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await updateCa({ caName, projectId: currentWorkspace.id, type: CaType.INTERNAL, status });
|
||||
await updateCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL, status });
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`,
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { CaStatus, CaType, useListCasByTypeAndProjectId } from "@app/hooks/api";
|
||||
import {
|
||||
caStatusToNameMap,
|
||||
@@ -49,8 +49,8 @@ type Props = {
|
||||
|
||||
export const CaTable = ({ handlePopUpOpen }: Props) => {
|
||||
const navigate = useNavigate();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { data, isPending } = useListCasByTypeAndProjectId(CaType.INTERNAL, currentWorkspace.id);
|
||||
const { currentProject } = useProject();
|
||||
const { data, isPending } = useListCasByTypeAndProjectId(CaType.INTERNAL, currentProject.id);
|
||||
const cas = data as TInternalCertificateAuthority[];
|
||||
|
||||
return (
|
||||
@@ -80,7 +80,7 @@ export const CaTable = ({ handlePopUpOpen }: Props) => {
|
||||
navigate({
|
||||
to: "/projects/cert-management/$projectId/ca/$caName",
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
caName: ca.name
|
||||
}
|
||||
})
|
||||
|
||||
+12
-9
@@ -4,6 +4,7 @@ import { SingleValue } from "react-select";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { AppConnectionOption } from "@app/components/app-connections";
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import {
|
||||
Button,
|
||||
@@ -16,7 +17,7 @@ import {
|
||||
SelectItem,
|
||||
Switch
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { APP_CONNECTION_MAP } from "@app/helpers/appConnections";
|
||||
import {
|
||||
TAvailableAppConnection,
|
||||
@@ -127,11 +128,11 @@ const caTypes = [
|
||||
];
|
||||
|
||||
export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { data: ca, isLoading: isCaLoading } = useGetCa({
|
||||
caName: (popUp?.ca?.data as { name: string })?.name || "",
|
||||
projectId: currentWorkspace?.id || "",
|
||||
projectId: currentProject?.id || "",
|
||||
type: (popUp?.ca?.data as { type: CaType })?.type || ""
|
||||
});
|
||||
|
||||
@@ -201,17 +202,17 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
}, [popUp?.ca?.isOpen, popUp?.ca?.data, reset, ca]);
|
||||
|
||||
const { data: availableRoute53Connections, isPending: isRoute53Pending } =
|
||||
useListAvailableAppConnections(AppConnection.AWS, {
|
||||
useListAvailableAppConnections(AppConnection.AWS, currentProject.id, {
|
||||
enabled: caType === CaType.ACME
|
||||
});
|
||||
|
||||
const { data: availableCloudflareConnections, isPending: isCloudflarePending } =
|
||||
useListAvailableAppConnections(AppConnection.Cloudflare, {
|
||||
useListAvailableAppConnections(AppConnection.Cloudflare, currentProject.id, {
|
||||
enabled: caType === CaType.ACME
|
||||
});
|
||||
|
||||
const { data: availableAzureConnections, isPending: isAzurePending } =
|
||||
useListAvailableAppConnections(AppConnection.AzureADCS, {
|
||||
useListAvailableAppConnections(AppConnection.AzureADCS, currentProject.id, {
|
||||
enabled: caType === CaType.AZURE_AD_CS
|
||||
});
|
||||
|
||||
@@ -297,7 +298,7 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
configuration: formConfiguration
|
||||
}: FormData) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
let configPayload: any;
|
||||
|
||||
@@ -321,7 +322,7 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
if (ca) {
|
||||
await updateMutateAsync({
|
||||
caName: ca.name,
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
name,
|
||||
type,
|
||||
status,
|
||||
@@ -330,7 +331,7 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
});
|
||||
} else {
|
||||
await createMutateAsync({
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
name,
|
||||
type,
|
||||
status,
|
||||
@@ -457,6 +458,7 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
placeholder="Select connection..."
|
||||
getOptionLabel={(option) => option.name}
|
||||
getOptionValue={(option) => option.id}
|
||||
components={{ Option: AppConnectionOption }}
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
@@ -599,6 +601,7 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
placeholder="Select connection..."
|
||||
getOptionLabel={(option) => option.name}
|
||||
getOptionValue={(option) => option.id}
|
||||
components={{ Option: AppConnectionOption }}
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
|
||||
+6
-6
@@ -5,7 +5,7 @@ import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { CaStatus, CaType, useDeleteCa, useUpdateCa } from "@app/hooks/api";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ExternalCaModal } from "./ExternalCaModal";
|
||||
import { ExternalCaTable } from "./ExternalCaTable";
|
||||
|
||||
export const ExternalCaSection = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { mutateAsync: deleteCa } = useDeleteCa();
|
||||
const { mutateAsync: updateCa } = useUpdateCa();
|
||||
|
||||
@@ -26,9 +26,9 @@ export const ExternalCaSection = () => {
|
||||
|
||||
const onRemoveCaSubmit = async (caName: string, type: CaType) => {
|
||||
try {
|
||||
if (!currentWorkspace?.id) return;
|
||||
if (!currentProject?.id) return;
|
||||
|
||||
await deleteCa({ caName, type, projectId: currentWorkspace.id });
|
||||
await deleteCa({ caName, type, projectId: currentProject.id });
|
||||
|
||||
createNotification({
|
||||
text: "Successfully deleted CA",
|
||||
@@ -54,9 +54,9 @@ export const ExternalCaSection = () => {
|
||||
status: CaStatus;
|
||||
}) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await updateCa({ caName: name, type, status, projectId: currentWorkspace.id });
|
||||
await updateCa({ caName: name, type, status, projectId: currentProject.id });
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`,
|
||||
|
||||
+3
-3
@@ -26,7 +26,7 @@ import {
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { CaStatus, CaType, useListExternalCasByProjectId } from "@app/hooks/api";
|
||||
import { caStatusToNameMap, getCaStatusBadgeVariant } from "@app/hooks/api/ca/constants";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
@@ -44,8 +44,8 @@ type Props = {
|
||||
};
|
||||
|
||||
export const ExternalCaTable = ({ handlePopUpOpen }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { data, isPending } = useListExternalCasByProjectId(currentWorkspace.id);
|
||||
const { currentProject } = useProject();
|
||||
const { data, isPending } = useListExternalCasByProjectId(currentProject.id);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
+5
-5
@@ -14,7 +14,7 @@ import {
|
||||
SelectItem,
|
||||
TextArea
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { useGetCert, useImportCertificate, useListWorkspacePkiCollections } from "@app/hooks/api";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -48,13 +48,13 @@ type TCertificateDetails = {
|
||||
|
||||
export const CertificateImportModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const [certificateDetails, setCertificateDetails] = useState<TCertificateDetails | null>(null);
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { data: cert } = useGetCert(
|
||||
(popUp?.certificateImport?.data as { serialNumber: string })?.serialNumber || ""
|
||||
);
|
||||
|
||||
const { data } = useListWorkspacePkiCollections({
|
||||
workspaceId: currentWorkspace?.id || ""
|
||||
projectId: currentProject?.id || ""
|
||||
});
|
||||
|
||||
const { mutateAsync: importCertificate } = useImportCertificate();
|
||||
@@ -76,10 +76,10 @@ export const CertificateImportModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
collectionId
|
||||
}: FormData) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
const { serialNumber, certificate, certificateChain, privateKey } = await importCertificate({
|
||||
projectSlug: currentWorkspace.slug,
|
||||
projectSlug: currentProject.slug,
|
||||
|
||||
certificatePem,
|
||||
privateKeyPem,
|
||||
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
SelectItem,
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
CaStatus,
|
||||
useCreateCertificate,
|
||||
@@ -89,22 +89,22 @@ const CERT_TEMPLATE_NONE_VALUE = "none";
|
||||
|
||||
export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const [certificateDetails, setCertificateDetails] = useState<TCertificateDetails | null>(null);
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { data: cert } = useGetCert(
|
||||
(popUp?.certificate?.data as { serialNumber: string })?.serialNumber || ""
|
||||
);
|
||||
|
||||
const { data: cas } = useListWorkspaceCas({
|
||||
projectSlug: currentWorkspace?.slug ?? "",
|
||||
projectId: currentProject.id,
|
||||
status: CaStatus.ACTIVE
|
||||
});
|
||||
|
||||
const { data } = useListWorkspacePkiCollections({
|
||||
workspaceId: currentWorkspace?.id || ""
|
||||
projectId: currentProject?.id || ""
|
||||
});
|
||||
|
||||
const { data: templatesData } = useListWorkspaceCertificateTemplates({
|
||||
workspaceId: currentWorkspace?.id || ""
|
||||
projectId: currentProject?.id || ""
|
||||
});
|
||||
|
||||
const { mutateAsync: createCertificate } = useCreateCertificate();
|
||||
@@ -191,12 +191,12 @@ export const CertificateModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
extendedKeyUsages
|
||||
}: FormData) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
const { serialNumber, certificate, certificateChain, privateKey } = await createCertificate({
|
||||
caId: !selectedCertTemplate ? caId : undefined,
|
||||
certificateTemplateId: selectedCertTemplate ? selectedCertTemplateId : undefined,
|
||||
projectSlug: currentWorkspace.slug,
|
||||
projectSlug: currentProject.slug,
|
||||
pkiCollectionId: collectionId,
|
||||
friendlyName,
|
||||
commonName,
|
||||
|
||||
+4
-4
@@ -4,7 +4,7 @@ import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FormControl, Modal, ModalContent, Select, SelectItem } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { useRevokeCert } from "@app/hooks/api";
|
||||
import { crlReasons } from "@app/hooks/api/certificates/constants";
|
||||
import { CrlReason } from "@app/hooks/api/certificates/enums";
|
||||
@@ -35,7 +35,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const CertificateRevocationModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { mutateAsync: revokeCertificate } = useRevokeCert();
|
||||
|
||||
const {
|
||||
@@ -49,12 +49,12 @@ export const CertificateRevocationModal = ({ popUp, handlePopUpToggle }: Props)
|
||||
|
||||
const onFormSubmit = async ({ revocationReason }: FormData) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
const { serialNumber } = popUp.revokeCertificate.data as { serialNumber: string };
|
||||
|
||||
await revokeCertificate({
|
||||
projectSlug: currentWorkspace.slug,
|
||||
projectSlug: currentProject.slug,
|
||||
serialNumber,
|
||||
revocationReason
|
||||
});
|
||||
|
||||
+7
-7
@@ -22,7 +22,7 @@ import {
|
||||
SelectItem,
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
CaStatus,
|
||||
useCreateCertTemplate,
|
||||
@@ -82,7 +82,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { data: ca } = useGetCaById(caId);
|
||||
|
||||
@@ -91,12 +91,12 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro
|
||||
);
|
||||
|
||||
const { data: cas } = useListWorkspaceCas({
|
||||
projectSlug: currentWorkspace?.slug ?? "",
|
||||
projectId: currentProject?.id,
|
||||
status: CaStatus.ACTIVE
|
||||
});
|
||||
|
||||
const { data: collectionsData } = useListWorkspacePkiCollections({
|
||||
workspaceId: currentWorkspace?.id || ""
|
||||
projectId: currentProject?.id || ""
|
||||
});
|
||||
|
||||
const { mutateAsync: createCertTemplate } = useCreateCertTemplate();
|
||||
@@ -155,7 +155,7 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro
|
||||
keyUsages,
|
||||
extendedKeyUsages
|
||||
}: FormData) => {
|
||||
if (!currentWorkspace?.id) {
|
||||
if (!currentProject?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro
|
||||
if (certTemplate) {
|
||||
await updateCertTemplate({
|
||||
id: certTemplate.id,
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
pkiCollectionId: collectionId,
|
||||
caId,
|
||||
name,
|
||||
@@ -184,7 +184,7 @@ export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Pro
|
||||
});
|
||||
} else {
|
||||
await createCertTemplate({
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
pkiCollectionId: collectionId,
|
||||
caId,
|
||||
name,
|
||||
|
||||
+4
-4
@@ -12,7 +12,7 @@ import { DeleteActionModal, IconButton } from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionPkiTemplateActions,
|
||||
ProjectPermissionSub,
|
||||
useWorkspace
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useDeleteCertTemplate } from "@app/hooks/api";
|
||||
@@ -33,18 +33,18 @@ export const CertificateTemplatesSection = ({ caId }: Props) => {
|
||||
"upgradePlan"
|
||||
] as const);
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { mutateAsync: deleteCertTemplate } = useDeleteCertTemplate();
|
||||
|
||||
const onRemoveCertificateTemplateSubmit = async (id: string) => {
|
||||
if (!currentWorkspace?.id) {
|
||||
if (!currentProject?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await deleteCertTemplate({
|
||||
id,
|
||||
projectId: currentWorkspace.id
|
||||
projectId: currentProject.id
|
||||
});
|
||||
|
||||
createNotification({
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionCertificateActions,
|
||||
ProjectPermissionSub,
|
||||
useWorkspace
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { useDeleteCert } from "@app/hooks/api";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
@@ -19,7 +19,7 @@ import { CertificateRevocationModal } from "./CertificateRevocationModal";
|
||||
import { CertificatesTable } from "./CertificatesTable";
|
||||
|
||||
export const CertificatesSection = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { mutateAsync: deleteCert } = useDeleteCert();
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
|
||||
@@ -32,9 +32,9 @@ export const CertificatesSection = () => {
|
||||
|
||||
const onRemoveCertificateSubmit = async (serialNumber: string) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await deleteCert({ serialNumber, projectSlug: currentWorkspace.slug });
|
||||
await deleteCert({ serialNumber, projectSlug: currentProject.slug });
|
||||
|
||||
createNotification({
|
||||
text: "Successfully deleted certificate",
|
||||
|
||||
@@ -33,7 +33,7 @@ import {
|
||||
import {
|
||||
ProjectPermissionCertificateActions,
|
||||
ProjectPermissionSub,
|
||||
useWorkspace
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { useListWorkspaceCertificates } from "@app/hooks/api";
|
||||
import { caSupportsCapability } from "@app/hooks/api/ca/constants";
|
||||
@@ -62,15 +62,15 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
const [page, setPage] = useState(1);
|
||||
const [perPage, setPerPage] = useState(PER_PAGE_INIT);
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { data, isPending } = useListWorkspaceCertificates({
|
||||
projectSlug: currentWorkspace?.slug ?? "",
|
||||
projectId: currentProject?.slug ?? "",
|
||||
offset: (page - 1) * perPage,
|
||||
limit: perPage
|
||||
});
|
||||
|
||||
// Fetch CA data to determine capabilities
|
||||
const { data: caData } = useListCasByProjectId(currentWorkspace?.id ?? "");
|
||||
const { data: caData } = useListCasByProjectId(currentProject?.id ?? "");
|
||||
|
||||
// Create mapping from caId to CA type for capability checking
|
||||
const caCapabilityMap = useMemo(() => {
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@ import {
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { useDeletePkiCollection, useGetPkiCollectionById } from "@app/hooks/api";
|
||||
import { PkiItemType } from "@app/hooks/api/pkiCollections/constants";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
@@ -30,8 +30,8 @@ export const PkiCollectionPage = () => {
|
||||
from: ROUTE_PATHS.CertManager.PkiCollectionDetailsByIDPage.id
|
||||
});
|
||||
const collectionId = params.collectionId as string;
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
const { data } = useGetPkiCollectionById(collectionId);
|
||||
const { mutateAsync: deletePkiCollection } = useDeletePkiCollection();
|
||||
|
||||
+4
-4
@@ -4,7 +4,7 @@ import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FormControl, Modal, ModalContent, Select, SelectItem } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
CaStatus,
|
||||
useAddItemToPkiCollection,
|
||||
@@ -41,15 +41,15 @@ export const AddPkiCollectionItemModal = ({
|
||||
popUp,
|
||||
handlePopUpToggle
|
||||
}: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { data: cas } = useListWorkspaceCas({
|
||||
projectSlug: currentWorkspace?.slug || "",
|
||||
projectId: currentProject?.id || "",
|
||||
status: CaStatus.ACTIVE
|
||||
});
|
||||
|
||||
const { data } = useListWorkspaceCertificates({
|
||||
projectSlug: currentWorkspace?.slug || "",
|
||||
projectId: currentProject?.slug || "",
|
||||
offset: 0,
|
||||
limit: 25
|
||||
});
|
||||
|
||||
+3
-3
@@ -19,7 +19,7 @@ import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import {
|
||||
ProjectPermissionPkiSubscriberActions,
|
||||
ProjectPermissionSub,
|
||||
useWorkspace
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { useDeletePkiSubscriber, useGetPkiSubscriber } from "@app/hooks/api";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
@@ -29,8 +29,8 @@ import { PkiSubscriberCertificatesSection, PkiSubscriberDetailsSection } from ".
|
||||
|
||||
const Page = () => {
|
||||
const navigate = useNavigate();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace.id;
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject.id;
|
||||
const subscriberName = useParams({
|
||||
from: ROUTE_PATHS.CertManager.PkiSubscriberDetailsByIDPage.id,
|
||||
select: (el) => el.subscriberName
|
||||
|
||||
+5
-5
@@ -27,8 +27,8 @@ import {
|
||||
import {
|
||||
ProjectPermissionPkiSubscriberActions,
|
||||
ProjectPermissionSub,
|
||||
useProjectPermission,
|
||||
useWorkspace
|
||||
useProject,
|
||||
useProjectPermission
|
||||
} from "@app/context";
|
||||
import { useGetPkiSubscriberCertificates } from "@app/hooks/api";
|
||||
import { caSupportsCapability } from "@app/hooks/api/ca/constants";
|
||||
@@ -45,8 +45,8 @@ type Props = {
|
||||
const PER_PAGE_INIT = 25;
|
||||
|
||||
export const PkiSubscriberCertificatesTable = ({ subscriberName, handlePopUpOpen }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace.id;
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject.id;
|
||||
const { permission } = useProjectPermission();
|
||||
const [page, setPage] = useState(1);
|
||||
const [perPage, setPerPage] = useState(PER_PAGE_INIT);
|
||||
@@ -64,7 +64,7 @@ export const PkiSubscriberCertificatesTable = ({ subscriberName, handlePopUpOpen
|
||||
);
|
||||
|
||||
// Fetch CA data to determine capabilities
|
||||
const { data: caData } = useListCasByProjectId(currentWorkspace.id);
|
||||
const { data: caData } = useListCasByProjectId(currentProject.id);
|
||||
|
||||
// Create mapping from caId to CA type for capability checking
|
||||
const caCapabilityMap = useMemo(() => {
|
||||
|
||||
+4
-4
@@ -16,8 +16,8 @@ import {
|
||||
import {
|
||||
ProjectPermissionPkiSubscriberActions,
|
||||
ProjectPermissionSub,
|
||||
useProjectPermission,
|
||||
useWorkspace
|
||||
useProject,
|
||||
useProjectPermission
|
||||
} from "@app/context";
|
||||
import { useTimedReset } from "@app/hooks";
|
||||
import {
|
||||
@@ -44,8 +44,8 @@ type TCertificateDetails = {
|
||||
};
|
||||
|
||||
export const PkiSubscriberDetailsSection = ({ subscriberName, handlePopUpOpen }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace.id;
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject.id;
|
||||
const { permission } = useProjectPermission();
|
||||
const [certificateDetails, setCertificateDetails] = useState<TCertificateDetails | null>(null);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
|
||||
+3
-3
@@ -22,7 +22,7 @@ import {
|
||||
TabPanel,
|
||||
Tabs
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
CaType,
|
||||
useCreatePkiSubscriber,
|
||||
@@ -158,8 +158,8 @@ const schema = z
|
||||
export type FormData = z.infer<typeof schema>;
|
||||
|
||||
export const PkiSubscriberModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace.id;
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject.id;
|
||||
const { data: subscribers } = useListWorkspacePkiSubscribers(projectId);
|
||||
const { data: cas } = useListCasByProjectId(projectId);
|
||||
const [tabValue, setTabValue] = useState<FormTab>(FormTab.Configuration);
|
||||
|
||||
+4
-4
@@ -7,7 +7,7 @@ import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionPkiSubscriberActions,
|
||||
ProjectPermissionSub,
|
||||
useWorkspace
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { useDeletePkiSubscriber, useUpdatePkiSubscriber } from "@app/hooks/api";
|
||||
import { PkiSubscriberStatus } from "@app/hooks/api/pkiSubscriber/types";
|
||||
@@ -17,8 +17,8 @@ import { PkiSubscriberModal } from "./PkiSubscriberModal";
|
||||
import { PkiSubscribersTable } from "./PkiSubscribersTable";
|
||||
|
||||
export const PkiSubscriberSection = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace.id;
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject.id;
|
||||
const { mutateAsync: deletePkiSubscriber } = useDeletePkiSubscriber();
|
||||
const { mutateAsync: updatePkiSubscriber } = useUpdatePkiSubscriber();
|
||||
|
||||
@@ -55,7 +55,7 @@ export const PkiSubscriberSection = () => {
|
||||
status: PkiSubscriberStatus;
|
||||
}) => {
|
||||
try {
|
||||
if (!currentWorkspace?.slug) return;
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await updatePkiSubscriber({ subscriberName, projectId, status });
|
||||
|
||||
|
||||
+4
-4
@@ -30,7 +30,7 @@ import {
|
||||
import {
|
||||
ProjectPermissionPkiSubscriberActions,
|
||||
ProjectPermissionSub,
|
||||
useWorkspace
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { useListWorkspacePkiSubscribers } from "@app/hooks/api";
|
||||
import {
|
||||
@@ -49,8 +49,8 @@ type Props = {
|
||||
|
||||
export const PkiSubscribersTable = ({ handlePopUpOpen }: Props) => {
|
||||
const navigate = useNavigate();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { data, isPending } = useListWorkspacePkiSubscribers(currentWorkspace?.id || "");
|
||||
const { currentProject } = useProject();
|
||||
const { data, isPending } = useListWorkspacePkiSubscribers(currentProject?.id || "");
|
||||
return (
|
||||
<div>
|
||||
<TableContainer>
|
||||
@@ -77,7 +77,7 @@ export const PkiSubscribersTable = ({ handlePopUpOpen }: Props) => {
|
||||
navigate({
|
||||
to: "/projects/cert-management/$projectId/subscribers/$subscriberName",
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
subscriberName: subscriber.name
|
||||
}
|
||||
})
|
||||
|
||||
@@ -42,8 +42,8 @@ import {
|
||||
import {
|
||||
ProjectPermissionPkiTemplateActions,
|
||||
ProjectPermissionSub,
|
||||
useSubscription,
|
||||
useWorkspace
|
||||
useProject,
|
||||
useSubscription
|
||||
} from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useDeleteCertTemplateV2 } from "@app/hooks/api";
|
||||
@@ -55,7 +55,7 @@ import { PkiTemplateForm } from "./components/PkiTemplateForm";
|
||||
const PER_PAGE_INIT = 25;
|
||||
export const PkiTemplateListPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const [page, setPage] = useState(1);
|
||||
const [perPage, setPerPage] = useState(PER_PAGE_INIT);
|
||||
const { handlePopUpToggle, popUp, handlePopUpOpen, handlePopUpClose } = usePopUp([
|
||||
@@ -68,7 +68,7 @@ export const PkiTemplateListPage = () => {
|
||||
const { subscription } = useSubscription();
|
||||
|
||||
const { data, isPending } = useListCertificateTemplates({
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
offset: (page - 1) * perPage,
|
||||
limit: perPage
|
||||
});
|
||||
@@ -78,7 +78,7 @@ export const PkiTemplateListPage = () => {
|
||||
const onRemovePkiSubscriberSubmit = async () => {
|
||||
try {
|
||||
const pkiTemplate = await deleteCertTemplate.mutateAsync({
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
templateName: popUp?.deleteTemplate?.data?.name
|
||||
});
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
Input,
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
useCreateCertTemplateV2,
|
||||
useListCasByProjectId,
|
||||
@@ -72,9 +72,9 @@ type Props = {
|
||||
};
|
||||
|
||||
export const PkiTemplateForm = ({ certTemplate, handlePopUpToggle }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { data: cas, isPending: isCaLoading } = useListCasByProjectId(currentWorkspace.id);
|
||||
const { data: cas, isPending: isCaLoading } = useListCasByProjectId(currentProject.id);
|
||||
|
||||
const { mutateAsync: createCertTemplate } = useCreateCertTemplateV2();
|
||||
const { mutateAsync: updateCertTemplate } = useUpdateCertTemplateV2();
|
||||
@@ -124,7 +124,7 @@ export const PkiTemplateForm = ({ certTemplate, handlePopUpToggle }: Props) => {
|
||||
extendedKeyUsages,
|
||||
ca
|
||||
}: FormData) => {
|
||||
if (!currentWorkspace?.id) {
|
||||
if (!currentProject?.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ export const PkiTemplateForm = ({ certTemplate, handlePopUpToggle }: Props) => {
|
||||
if (certTemplate) {
|
||||
await updateCertTemplate({
|
||||
templateName: certTemplate.name,
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
caName: ca.name,
|
||||
name,
|
||||
commonName,
|
||||
@@ -152,7 +152,7 @@ export const PkiTemplateForm = ({ certTemplate, handlePopUpToggle }: Props) => {
|
||||
});
|
||||
} else {
|
||||
await createCertTemplate({
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
caName: ca.name,
|
||||
name,
|
||||
commonName,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
import { BreadcrumbTypes } from "@app/components/v2";
|
||||
import { workspaceKeys } from "@app/hooks/api";
|
||||
import { projectKeys } from "@app/hooks/api";
|
||||
import { fetchProjectById } from "@app/hooks/api/projects/queries";
|
||||
import { fetchUserProjectPermissions, roleQueryKeys } from "@app/hooks/api/roles/queries";
|
||||
import { fetchWorkspaceById } from "@app/hooks/api/workspace/queries";
|
||||
import { PkiManagerLayout } from "@app/layouts/PkiManagerLayout";
|
||||
import { ProjectSelect } from "@app/layouts/ProjectLayout/components/ProjectSelect";
|
||||
|
||||
@@ -13,15 +13,15 @@ export const Route = createFileRoute(
|
||||
component: PkiManagerLayout,
|
||||
beforeLoad: async ({ params, context }) => {
|
||||
const project = await context.queryClient.ensureQueryData({
|
||||
queryKey: workspaceKeys.getWorkspaceById(params.projectId),
|
||||
queryFn: () => fetchWorkspaceById(params.projectId)
|
||||
queryKey: projectKeys.getProjectById(params.projectId),
|
||||
queryFn: () => fetchProjectById(params.projectId)
|
||||
});
|
||||
|
||||
await context.queryClient.ensureQueryData({
|
||||
queryKey: roleQueryKeys.getUserProjectPermissions({
|
||||
workspaceId: params.projectId
|
||||
projectId: params.projectId
|
||||
}),
|
||||
queryFn: () => fetchUserProjectPermissions({ workspaceId: params.projectId })
|
||||
queryFn: () => fetchUserProjectPermissions({ projectId: params.projectId })
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
ModalContent,
|
||||
TextArea
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { useCreateKmipClient, useUpdateKmipClient } from "@app/hooks/api/kmip";
|
||||
import { KmipPermission, TKmipClient } from "@app/hooks/api/kmip/types";
|
||||
|
||||
@@ -60,8 +60,8 @@ type FormProps = Pick<Props, "kmipClient"> & {
|
||||
const KmipClientForm = ({ onComplete, kmipClient }: FormProps) => {
|
||||
const createKmipClient = useCreateKmipClient();
|
||||
const updateKmipClient = useUpdateKmipClient();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace.id;
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject.id;
|
||||
const isUpdate = !!kmipClient;
|
||||
|
||||
const {
|
||||
|
||||
@@ -39,9 +39,9 @@ import {
|
||||
import {
|
||||
ProjectPermissionKmipActions,
|
||||
ProjectPermissionSub,
|
||||
useProject,
|
||||
useProjectPermission,
|
||||
useSubscription,
|
||||
useWorkspace
|
||||
useSubscription
|
||||
} from "@app/context";
|
||||
import {
|
||||
getUserTablePreference,
|
||||
@@ -59,9 +59,9 @@ import { KmipClientCertificateModal } from "./KmipClientCertificateModal";
|
||||
import { KmipClientModal } from "./KmipClientModal";
|
||||
|
||||
export const KmipClientTable = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const projectId = currentWorkspace?.id ?? "";
|
||||
const projectId = currentProject?.id ?? "";
|
||||
|
||||
const {
|
||||
offset,
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
SelectItem,
|
||||
TextArea
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { keyUsageDefaultOption, kmsKeyUsageOptions } from "@app/helpers/kms";
|
||||
import {
|
||||
AllowedEncryptionKeyAlgorithms,
|
||||
@@ -49,8 +49,8 @@ type FormProps = Pick<Props, "cmek"> & {
|
||||
const CmekForm = ({ onComplete, cmek }: FormProps) => {
|
||||
const createCmek = useCreateCmek();
|
||||
const updateCmek = useUpdateCmek();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace.id;
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject.id;
|
||||
const isUpdate = !!cmek;
|
||||
|
||||
const {
|
||||
|
||||
@@ -49,8 +49,8 @@ import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionCmekActions,
|
||||
ProjectPermissionSub,
|
||||
useProjectPermission,
|
||||
useWorkspace
|
||||
useProject,
|
||||
useProjectPermission
|
||||
} from "@app/context";
|
||||
import { kmsKeyUsageOptions } from "@app/helpers/kms";
|
||||
import {
|
||||
@@ -87,10 +87,10 @@ const getStatusBadgeProps = (
|
||||
};
|
||||
|
||||
export const CmekTable = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { permission } = useProjectPermission();
|
||||
|
||||
const projectId = currentWorkspace?.id ?? "";
|
||||
const projectId = currentProject?.id ?? "";
|
||||
|
||||
const {
|
||||
offset,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
import { BreadcrumbTypes } from "@app/components/v2";
|
||||
import { workspaceKeys } from "@app/hooks/api";
|
||||
import { projectKeys } from "@app/hooks/api";
|
||||
import { fetchProjectById } from "@app/hooks/api/projects/queries";
|
||||
import { fetchUserProjectPermissions, roleQueryKeys } from "@app/hooks/api/roles/queries";
|
||||
import { fetchWorkspaceById } from "@app/hooks/api/workspace/queries";
|
||||
import { KmsLayout } from "@app/layouts/KmsLayout";
|
||||
import { ProjectSelect } from "@app/layouts/ProjectLayout/components/ProjectSelect";
|
||||
|
||||
@@ -13,15 +13,15 @@ export const Route = createFileRoute(
|
||||
component: KmsLayout,
|
||||
beforeLoad: async ({ params, context }) => {
|
||||
const project = await context.queryClient.ensureQueryData({
|
||||
queryKey: workspaceKeys.getWorkspaceById(params.projectId),
|
||||
queryFn: () => fetchWorkspaceById(params.projectId)
|
||||
queryKey: projectKeys.getProjectById(params.projectId),
|
||||
queryFn: () => fetchProjectById(params.projectId)
|
||||
});
|
||||
|
||||
await context.queryClient.ensureQueryData({
|
||||
queryKey: roleQueryKeys.getUserProjectPermissions({
|
||||
workspaceId: params.projectId
|
||||
projectId: params.projectId
|
||||
}),
|
||||
queryFn: () => fetchUserProjectPermissions({ workspaceId: params.projectId })
|
||||
queryFn: () => fetchUserProjectPermissions({ projectId: params.projectId })
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
+3
-3
@@ -21,10 +21,10 @@ import {
|
||||
useAddUsersToOrg,
|
||||
useFetchServerStatus,
|
||||
useGetOrgRoles,
|
||||
useGetUserWorkspaces
|
||||
useGetUserProjects
|
||||
} from "@app/hooks/api";
|
||||
import { ProjectType, ProjectVersion } from "@app/hooks/api/projects/types";
|
||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||
import { ProjectType, ProjectVersion } from "@app/hooks/api/workspace/types";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
import { OrgInviteLink } from "./OrgInviteLink";
|
||||
@@ -76,7 +76,7 @@ export const AddOrgMemberModal = ({
|
||||
const { data: organizationRoles } = useGetOrgRoles(currentOrg?.id ?? "");
|
||||
const { data: serverDetails } = useFetchServerStatus();
|
||||
const { mutateAsync: addUsersMutateAsync } = useAddUsersToOrg();
|
||||
const { data: projects, isPending: isProjectsLoading } = useGetUserWorkspaces({
|
||||
const { data: projects, isPending: isProjectsLoading } = useGetUserProjects({
|
||||
includeRoles: true
|
||||
});
|
||||
|
||||
|
||||
+13
-56
@@ -1,24 +1,17 @@
|
||||
import { Helmet } from "react-helmet";
|
||||
import { faArrowUpRightFromSquare, faBookOpen, faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faInfoCircle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { OrgPermissionCan } from "@app/components/permissions";
|
||||
import { Button, PageHeader } from "@app/components/v2";
|
||||
import { PageHeader } from "@app/components/v2";
|
||||
import {
|
||||
OrgPermissionAppConnectionActions,
|
||||
OrgPermissionSubjects
|
||||
} from "@app/context/OrgPermissionContext/types";
|
||||
import { withPermission } from "@app/hoc";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import {
|
||||
AddAppConnectionModal,
|
||||
AppConnectionsTable
|
||||
} from "@app/pages/organization/AppConnections/AppConnectionsPage/components";
|
||||
import { AppConnectionsTable } from "@app/pages/organization/AppConnections/AppConnectionsPage/components";
|
||||
|
||||
export const AppConnectionsPage = withPermission(
|
||||
() => {
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["addConnection"] as const);
|
||||
|
||||
return (
|
||||
<div className="bg-bunker-800">
|
||||
<Helmet>
|
||||
@@ -30,54 +23,18 @@ export const AppConnectionsPage = withPermission(
|
||||
<div className="w-full max-w-7xl">
|
||||
<PageHeader
|
||||
className="w-full"
|
||||
title={
|
||||
<div className="flex w-full items-center">
|
||||
<span>App Connections</span>
|
||||
<a
|
||||
className="-mt-1.5"
|
||||
href="https://infisical.com/docs/integrations/app-connections/overview"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<div className="ml-2 inline-block rounded-md bg-yellow/20 px-1.5 text-sm font-normal text-yellow opacity-80 hover:opacity-100">
|
||||
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||
<span>Docs</span>
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowUpRightFromSquare}
|
||||
className="mb-[0.07rem] ml-1.5 text-[10px]"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
<OrgPermissionCan
|
||||
I={OrgPermissionAppConnectionActions.Create}
|
||||
a={OrgPermissionSubjects.AppConnections}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
type="submit"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => {
|
||||
handlePopUpOpen("addConnection");
|
||||
}}
|
||||
isDisabled={!isAllowed}
|
||||
className="ml-auto"
|
||||
>
|
||||
Add Connection
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
</div>
|
||||
}
|
||||
description="Create and configure connections with third-party apps for re-use across Infisical projects"
|
||||
title="App Connections"
|
||||
description="Manage organization App Connections"
|
||||
/>
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<AppConnectionsTable />
|
||||
<AddAppConnectionModal
|
||||
isOpen={popUp.addConnection.isOpen}
|
||||
onOpenChange={(isOpen) => handlePopUpToggle("addConnection", isOpen)}
|
||||
/>
|
||||
<div className="mb-4 flex w-full flex-col rounded-md border border-blue-500/50 bg-blue-500/30 px-4 py-2 text-sm text-blue-200">
|
||||
<div className="flex items-center">
|
||||
<FontAwesomeIcon icon={faInfoCircle} className="mb-0.5 mr-2 text-sm" />
|
||||
<span className="text-sm text-blue-200">
|
||||
App connections can also be created and managed independently in projects now.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<AppConnectionsTable />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+31
-7
@@ -3,6 +3,7 @@ import { useState } from "react";
|
||||
import { Modal, ModalContent } from "@app/components/v2";
|
||||
import { TAppConnection } from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
|
||||
import { AppConnectionForm } from "./AppConnectionForm";
|
||||
import { AppConnectionsSelect } from "./AppConnectionList";
|
||||
@@ -10,29 +11,44 @@ import { AppConnectionsSelect } from "./AppConnectionList";
|
||||
type Props = {
|
||||
isOpen: boolean;
|
||||
onOpenChange: (isOpen: boolean) => void;
|
||||
projectId?: string;
|
||||
projectType?: ProjectType;
|
||||
app?: AppConnection;
|
||||
onComplete?: (appConnection: TAppConnection) => void;
|
||||
};
|
||||
|
||||
type ContentProps = {
|
||||
onComplete: (appConnection: TAppConnection) => void;
|
||||
projectId?: string;
|
||||
projectType?: ProjectType;
|
||||
app?: AppConnection;
|
||||
};
|
||||
|
||||
const Content = ({ onComplete }: ContentProps) => {
|
||||
const Content = ({ onComplete, projectId, projectType, app }: ContentProps) => {
|
||||
const [selectedApp, setSelectedApp] = useState<AppConnection | null>(null);
|
||||
|
||||
if (selectedApp) {
|
||||
if (app ?? selectedApp) {
|
||||
return (
|
||||
<AppConnectionForm
|
||||
onComplete={onComplete}
|
||||
onBack={() => setSelectedApp(null)}
|
||||
app={selectedApp}
|
||||
onBack={app ? undefined : () => setSelectedApp(null)}
|
||||
app={(app ?? selectedApp)!}
|
||||
projectId={projectId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <AppConnectionsSelect onSelect={setSelectedApp} />;
|
||||
return <AppConnectionsSelect onSelect={setSelectedApp} projectType={projectType} />;
|
||||
};
|
||||
|
||||
export const AddAppConnectionModal = ({ isOpen, onOpenChange }: Props) => {
|
||||
export const AddAppConnectionModal = ({
|
||||
isOpen,
|
||||
onOpenChange,
|
||||
projectId,
|
||||
projectType,
|
||||
app,
|
||||
onComplete
|
||||
}: Props) => {
|
||||
return (
|
||||
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||
<ModalContent
|
||||
@@ -40,7 +56,15 @@ export const AddAppConnectionModal = ({ isOpen, onOpenChange }: Props) => {
|
||||
title="Add Connection"
|
||||
subTitle="Select a third-party app to connect to."
|
||||
>
|
||||
<Content onComplete={() => onOpenChange(false)} />
|
||||
<Content
|
||||
projectId={projectId}
|
||||
projectType={projectType}
|
||||
app={app}
|
||||
onComplete={(appConnection) => {
|
||||
if (onComplete) onComplete(appConnection);
|
||||
onOpenChange(false);
|
||||
}}
|
||||
/>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
+61
-20
@@ -52,12 +52,15 @@ type FormProps = {
|
||||
onComplete: (appConnection: TAppConnection) => void;
|
||||
} & ({ appConnection: TAppConnection } | { app: AppConnection });
|
||||
|
||||
type CreateFormProps = FormProps & { app: AppConnection };
|
||||
type CreateFormProps = FormProps & {
|
||||
app: AppConnection;
|
||||
projectId?: string;
|
||||
};
|
||||
type UpdateFormProps = FormProps & {
|
||||
appConnection: TAppConnection;
|
||||
};
|
||||
|
||||
const CreateForm = ({ app, onComplete }: CreateFormProps) => {
|
||||
const CreateForm = ({ app, onComplete, projectId }: CreateFormProps) => {
|
||||
const createAppConnection = useCreateAppConnection();
|
||||
const { name: appName } = APP_CONNECTION_MAP[app];
|
||||
|
||||
@@ -68,7 +71,10 @@ const CreateForm = ({ app, onComplete }: CreateFormProps) => {
|
||||
>
|
||||
) => {
|
||||
try {
|
||||
const connection = await createAppConnection.mutateAsync(formData);
|
||||
const connection = await createAppConnection.mutateAsync({
|
||||
...formData,
|
||||
projectId
|
||||
});
|
||||
createNotification({
|
||||
text: `Successfully added ${appName} Connection`,
|
||||
type: "success"
|
||||
@@ -88,15 +94,15 @@ const CreateForm = ({ app, onComplete }: CreateFormProps) => {
|
||||
case AppConnection.AWS:
|
||||
return <AwsConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.GitHub:
|
||||
return <GitHubConnectionForm />;
|
||||
return <GitHubConnectionForm projectId={projectId} />;
|
||||
case AppConnection.GitHubRadar:
|
||||
return <GitHubRadarConnectionForm />;
|
||||
return <GitHubRadarConnectionForm projectId={projectId} />;
|
||||
case AppConnection.GCP:
|
||||
return <GcpConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.AzureKeyVault:
|
||||
return <AzureKeyVaultConnectionForm onSubmit={onSubmit} />;
|
||||
return <AzureKeyVaultConnectionForm onSubmit={onSubmit} projectId={projectId} />;
|
||||
case AppConnection.AzureAppConfiguration:
|
||||
return <AzureAppConfigurationConnectionForm onSubmit={onSubmit} />;
|
||||
return <AzureAppConfigurationConnectionForm onSubmit={onSubmit} projectId={projectId} />;
|
||||
case AppConnection.AzureADCS:
|
||||
return <AzureADCSConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.Databricks:
|
||||
@@ -118,9 +124,9 @@ const CreateForm = ({ app, onComplete }: CreateFormProps) => {
|
||||
case AppConnection.Camunda:
|
||||
return <CamundaConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.AzureClientSecrets:
|
||||
return <AzureClientSecretsConnectionForm onSubmit={onSubmit} />;
|
||||
return <AzureClientSecretsConnectionForm onSubmit={onSubmit} projectId={projectId} />;
|
||||
case AppConnection.AzureDevOps:
|
||||
return <AzureDevOpsConnectionForm onSubmit={onSubmit} />;
|
||||
return <AzureDevOpsConnectionForm onSubmit={onSubmit} projectId={projectId} />;
|
||||
case AppConnection.Windmill:
|
||||
return <WindmillConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.Auth0:
|
||||
@@ -142,7 +148,7 @@ const CreateForm = ({ app, onComplete }: CreateFormProps) => {
|
||||
case AppConnection.Flyio:
|
||||
return <FlyioConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.GitLab:
|
||||
return <GitLabConnectionForm onSubmit={onSubmit} />;
|
||||
return <GitLabConnectionForm onSubmit={onSubmit} projectId={projectId} />;
|
||||
case AppConnection.Cloudflare:
|
||||
return <CloudflareConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.Bitbucket:
|
||||
@@ -200,16 +206,33 @@ const UpdateForm = ({ appConnection, onComplete }: UpdateFormProps) => {
|
||||
case AppConnection.AWS:
|
||||
return <AwsConnectionForm appConnection={appConnection} onSubmit={onSubmit} />;
|
||||
case AppConnection.GitHub:
|
||||
return <GitHubConnectionForm appConnection={appConnection} />;
|
||||
return (
|
||||
<GitHubConnectionForm appConnection={appConnection} projectId={appConnection.projectId} />
|
||||
);
|
||||
case AppConnection.GitHubRadar:
|
||||
return <GitHubRadarConnectionForm appConnection={appConnection} />;
|
||||
return (
|
||||
<GitHubRadarConnectionForm
|
||||
appConnection={appConnection}
|
||||
projectId={appConnection.projectId}
|
||||
/>
|
||||
);
|
||||
case AppConnection.GCP:
|
||||
return <GcpConnectionForm appConnection={appConnection} onSubmit={onSubmit} />;
|
||||
case AppConnection.AzureKeyVault:
|
||||
return <AzureKeyVaultConnectionForm appConnection={appConnection} onSubmit={onSubmit} />;
|
||||
return (
|
||||
<AzureKeyVaultConnectionForm
|
||||
appConnection={appConnection}
|
||||
onSubmit={onSubmit}
|
||||
projectId={appConnection.projectId}
|
||||
/>
|
||||
);
|
||||
case AppConnection.AzureAppConfiguration:
|
||||
return (
|
||||
<AzureAppConfigurationConnectionForm appConnection={appConnection} onSubmit={onSubmit} />
|
||||
<AzureAppConfigurationConnectionForm
|
||||
appConnection={appConnection}
|
||||
onSubmit={onSubmit}
|
||||
projectId={appConnection.projectId}
|
||||
/>
|
||||
);
|
||||
case AppConnection.AzureADCS:
|
||||
return <AzureADCSConnectionForm appConnection={appConnection} onSubmit={onSubmit} />;
|
||||
@@ -232,9 +255,21 @@ const UpdateForm = ({ appConnection, onComplete }: UpdateFormProps) => {
|
||||
case AppConnection.Camunda:
|
||||
return <CamundaConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||
case AppConnection.AzureClientSecrets:
|
||||
return <AzureClientSecretsConnectionForm appConnection={appConnection} onSubmit={onSubmit} />;
|
||||
return (
|
||||
<AzureClientSecretsConnectionForm
|
||||
appConnection={appConnection}
|
||||
onSubmit={onSubmit}
|
||||
projectId={appConnection.projectId}
|
||||
/>
|
||||
);
|
||||
case AppConnection.AzureDevOps:
|
||||
return <AzureDevOpsConnectionForm appConnection={appConnection} onSubmit={onSubmit} />;
|
||||
return (
|
||||
<AzureDevOpsConnectionForm
|
||||
appConnection={appConnection}
|
||||
onSubmit={onSubmit}
|
||||
projectId={appConnection.projectId}
|
||||
/>
|
||||
);
|
||||
case AppConnection.Windmill:
|
||||
return <WindmillConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||
case AppConnection.Auth0:
|
||||
@@ -256,7 +291,13 @@ const UpdateForm = ({ appConnection, onComplete }: UpdateFormProps) => {
|
||||
case AppConnection.Flyio:
|
||||
return <FlyioConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||
case AppConnection.GitLab:
|
||||
return <GitLabConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||
return (
|
||||
<GitLabConnectionForm
|
||||
onSubmit={onSubmit}
|
||||
appConnection={appConnection}
|
||||
projectId={appConnection.projectId}
|
||||
/>
|
||||
);
|
||||
case AppConnection.Cloudflare:
|
||||
return <CloudflareConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||
case AppConnection.Bitbucket:
|
||||
@@ -278,12 +319,12 @@ const UpdateForm = ({ appConnection, onComplete }: UpdateFormProps) => {
|
||||
}
|
||||
};
|
||||
|
||||
type Props = { onBack?: () => void } & Pick<FormProps, "onComplete"> &
|
||||
type Props = { onBack?: () => void; projectId?: string } & Pick<FormProps, "onComplete"> &
|
||||
(
|
||||
| { app: AppConnection; appConnection?: undefined }
|
||||
| { app?: undefined; appConnection: TAppConnection }
|
||||
);
|
||||
export const AppConnectionForm = ({ onBack, ...props }: Props) => {
|
||||
export const AppConnectionForm = ({ onBack, projectId, ...props }: Props) => {
|
||||
const { app, appConnection } = props;
|
||||
|
||||
return (
|
||||
@@ -296,7 +337,7 @@ export const AppConnectionForm = ({ onBack, ...props }: Props) => {
|
||||
{appConnection ? (
|
||||
<UpdateForm {...props} appConnection={appConnection} />
|
||||
) : (
|
||||
<CreateForm {...props} app={app} />
|
||||
<CreateForm {...props} app={app} projectId={projectId} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
+20
-3
@@ -6,7 +6,11 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Button, FormControl, Input, ModalClose, Select, SelectItem } from "@app/components/v2";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import {
|
||||
APP_CONNECTION_MAP,
|
||||
getAppConnectionMethodDetails,
|
||||
useGetAppConnectionOauthReturnUrl
|
||||
} from "@app/helpers/appConnections";
|
||||
import { isInfisicalCloud } from "@app/helpers/platform";
|
||||
import {
|
||||
AzureAppConfigurationConnectionMethod,
|
||||
@@ -15,6 +19,7 @@ import {
|
||||
} from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
|
||||
import { AzureAppConfigurationFormData } from "../../../OauthCallbackPage/OauthCallbackPage.types";
|
||||
import {
|
||||
genericAppConnectionFieldsSchema,
|
||||
GenericAppConnectionsFields
|
||||
@@ -25,6 +30,7 @@ type ClientSecretForm = z.infer<typeof clientSecretSchema>;
|
||||
type Props = {
|
||||
appConnection?: TAzureAppConfigurationConnection;
|
||||
onSubmit: (formData: ClientSecretForm) => Promise<void>;
|
||||
projectId: string | undefined | null;
|
||||
};
|
||||
|
||||
const baseSchema = genericAppConnectionFieldsSchema.extend({
|
||||
@@ -96,7 +102,11 @@ const getDefaultValues = (appConnection?: TAzureAppConfigurationConnection): Par
|
||||
return base;
|
||||
};
|
||||
|
||||
export const AzureAppConfigurationConnectionForm = ({ appConnection, onSubmit }: Props) => {
|
||||
export const AzureAppConfigurationConnectionForm = ({
|
||||
appConnection,
|
||||
onSubmit,
|
||||
projectId
|
||||
}: Props) => {
|
||||
const isUpdate = Boolean(appConnection);
|
||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||
|
||||
@@ -110,6 +120,8 @@ export const AzureAppConfigurationConnectionForm = ({ appConnection, onSubmit }:
|
||||
defaultValues: getDefaultValues(appConnection)
|
||||
});
|
||||
|
||||
const returnUrl = useGetAppConnectionOauthReturnUrl();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
@@ -128,7 +140,12 @@ export const AzureAppConfigurationConnectionForm = ({ appConnection, onSubmit }:
|
||||
localStorage.setItem("latestCSRFToken", state);
|
||||
localStorage.setItem(
|
||||
"azureAppConfigurationConnectionFormData",
|
||||
JSON.stringify({ ...formData, connectionId: appConnection?.id })
|
||||
JSON.stringify({
|
||||
...formData,
|
||||
connectionId: appConnection?.id,
|
||||
projectId,
|
||||
returnUrl
|
||||
} as AzureAppConfigurationFormData)
|
||||
);
|
||||
window.location.assign(
|
||||
`https://login.microsoftonline.com/${formData.tenantId || "common"}/oauth2/v2.0/authorize?client_id=${oauthClientId}&response_type=code&redirect_uri=${window.location.origin}/organization/app-connections/azure/oauth/callback&response_mode=query&scope=https://azconfig.io/.default%20openid%20offline_access&state=${state}<:>azure-app-configuration`
|
||||
|
||||
+16
-3
@@ -7,7 +7,11 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Button, FormControl, Input, ModalClose, Select, SelectItem } from "@app/components/v2";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import {
|
||||
APP_CONNECTION_MAP,
|
||||
getAppConnectionMethodDetails,
|
||||
useGetAppConnectionOauthReturnUrl
|
||||
} from "@app/helpers/appConnections";
|
||||
import { isInfisicalCloud } from "@app/helpers/platform";
|
||||
import {
|
||||
AzureClientSecretsConnectionMethod,
|
||||
@@ -16,6 +20,7 @@ import {
|
||||
} from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
|
||||
import { AzureClientSecretsFormData } from "../../../OauthCallbackPage/OauthCallbackPage.types";
|
||||
import {
|
||||
genericAppConnectionFieldsSchema,
|
||||
GenericAppConnectionsFields
|
||||
@@ -26,6 +31,7 @@ type ClientSecretForm = z.infer<typeof clientSecretSchema>;
|
||||
type Props = {
|
||||
appConnection?: TAzureClientSecretsConnection;
|
||||
onSubmit: (formData: ClientSecretForm) => Promise<void>;
|
||||
projectId: string | undefined | null;
|
||||
};
|
||||
|
||||
const baseSchema = genericAppConnectionFieldsSchema.extend({
|
||||
@@ -97,7 +103,7 @@ const getDefaultValues = (appConnection?: TAzureClientSecretsConnection): Partia
|
||||
return base;
|
||||
};
|
||||
|
||||
export const AzureClientSecretsConnectionForm = ({ appConnection, onSubmit }: Props) => {
|
||||
export const AzureClientSecretsConnectionForm = ({ appConnection, onSubmit, projectId }: Props) => {
|
||||
const isUpdate = Boolean(appConnection);
|
||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||
|
||||
@@ -111,6 +117,8 @@ export const AzureClientSecretsConnectionForm = ({ appConnection, onSubmit }: Pr
|
||||
defaultValues: getDefaultValues(appConnection)
|
||||
});
|
||||
|
||||
const returnUrl = useGetAppConnectionOauthReturnUrl();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
@@ -129,7 +137,12 @@ export const AzureClientSecretsConnectionForm = ({ appConnection, onSubmit }: Pr
|
||||
localStorage.setItem("latestCSRFToken", state);
|
||||
localStorage.setItem(
|
||||
"azureClientSecretsConnectionFormData",
|
||||
JSON.stringify({ ...formData, connectionId: appConnection?.id })
|
||||
JSON.stringify({
|
||||
...formData,
|
||||
connectionId: appConnection?.id,
|
||||
projectId,
|
||||
returnUrl
|
||||
} as AzureClientSecretsFormData)
|
||||
);
|
||||
window.location.assign(
|
||||
`https://login.microsoftonline.com/${formData.tenantId || "common"}/oauth2/v2.0/authorize?client_id=${oauthClientId}&response_type=code&redirect_uri=${window.location.origin}/organization/app-connections/azure/oauth/callback&response_mode=query&scope=https://graph.microsoft.com/.default%20openid%20offline_access&state=${state}<:>azure-client-secrets`
|
||||
|
||||
+16
-3
@@ -7,7 +7,11 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Button, FormControl, Input, ModalClose, Select, SelectItem } from "@app/components/v2";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import {
|
||||
APP_CONNECTION_MAP,
|
||||
getAppConnectionMethodDetails,
|
||||
useGetAppConnectionOauthReturnUrl
|
||||
} from "@app/helpers/appConnections";
|
||||
import { isInfisicalCloud } from "@app/helpers/platform";
|
||||
import {
|
||||
AzureDevOpsConnectionMethod,
|
||||
@@ -16,6 +20,7 @@ import {
|
||||
} from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
|
||||
import { AzureDevOpsFormData } from "../../../OauthCallbackPage/OauthCallbackPage.types";
|
||||
import {
|
||||
genericAppConnectionFieldsSchema,
|
||||
GenericAppConnectionsFields
|
||||
@@ -65,6 +70,7 @@ type OnSubmitForm = z.infer<typeof accessTokenSchema> | z.infer<typeof clientSec
|
||||
type Props = {
|
||||
appConnection?: TAzureDevOpsConnection;
|
||||
onSubmit: (formData: OnSubmitForm) => Promise<void>;
|
||||
projectId: string | undefined | null;
|
||||
};
|
||||
|
||||
const getDefaultValues = (appConnection?: TAzureDevOpsConnection): Partial<FormData> => {
|
||||
@@ -132,7 +138,7 @@ const getDefaultValues = (appConnection?: TAzureDevOpsConnection): Partial<FormD
|
||||
return base;
|
||||
};
|
||||
|
||||
export const AzureDevOpsConnectionForm = ({ appConnection, onSubmit }: Props) => {
|
||||
export const AzureDevOpsConnectionForm = ({ appConnection, onSubmit, projectId }: Props) => {
|
||||
const isUpdate = Boolean(appConnection);
|
||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||
|
||||
@@ -146,6 +152,8 @@ export const AzureDevOpsConnectionForm = ({ appConnection, onSubmit }: Props) =>
|
||||
defaultValues: getDefaultValues(appConnection)
|
||||
});
|
||||
|
||||
const returnUrl = useGetAppConnectionOauthReturnUrl();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
@@ -164,7 +172,12 @@ export const AzureDevOpsConnectionForm = ({ appConnection, onSubmit }: Props) =>
|
||||
localStorage.setItem("latestCSRFToken", state);
|
||||
localStorage.setItem(
|
||||
"azureDevOpsConnectionFormData",
|
||||
JSON.stringify({ ...formData, connectionId: appConnection?.id })
|
||||
JSON.stringify({
|
||||
...formData,
|
||||
connectionId: appConnection?.id,
|
||||
projectId,
|
||||
returnUrl
|
||||
} as AzureDevOpsFormData)
|
||||
);
|
||||
|
||||
window.location.assign(
|
||||
|
||||
+16
-3
@@ -6,7 +6,11 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Button, FormControl, Input, ModalClose, Select, SelectItem } from "@app/components/v2";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import {
|
||||
APP_CONNECTION_MAP,
|
||||
getAppConnectionMethodDetails,
|
||||
useGetAppConnectionOauthReturnUrl
|
||||
} from "@app/helpers/appConnections";
|
||||
import { isInfisicalCloud } from "@app/helpers/platform";
|
||||
import { useGetAppConnectionOption } from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
@@ -15,6 +19,7 @@ import {
|
||||
TAzureKeyVaultConnection
|
||||
} from "@app/hooks/api/appConnections/types/azure-key-vault-connection";
|
||||
|
||||
import { AzureKeyVaultFormData } from "../../../OauthCallbackPage/OauthCallbackPage.types";
|
||||
import {
|
||||
genericAppConnectionFieldsSchema,
|
||||
GenericAppConnectionsFields
|
||||
@@ -25,6 +30,7 @@ type ClientSecretForm = z.infer<typeof clientSecretSchema>;
|
||||
type Props = {
|
||||
appConnection?: TAzureKeyVaultConnection;
|
||||
onSubmit: (formData: ClientSecretForm) => Promise<void>;
|
||||
projectId: string | undefined | null;
|
||||
};
|
||||
|
||||
const baseSchema = genericAppConnectionFieldsSchema.extend({
|
||||
@@ -96,7 +102,7 @@ const getDefaultValues = (appConnection?: TAzureKeyVaultConnection): Partial<For
|
||||
return base;
|
||||
};
|
||||
|
||||
export const AzureKeyVaultConnectionForm = ({ appConnection, onSubmit }: Props) => {
|
||||
export const AzureKeyVaultConnectionForm = ({ appConnection, onSubmit, projectId }: Props) => {
|
||||
const isUpdate = Boolean(appConnection);
|
||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||
|
||||
@@ -110,6 +116,8 @@ export const AzureKeyVaultConnectionForm = ({ appConnection, onSubmit }: Props)
|
||||
defaultValues: getDefaultValues(appConnection)
|
||||
});
|
||||
|
||||
const returnUrl = useGetAppConnectionOauthReturnUrl();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
@@ -129,7 +137,12 @@ export const AzureKeyVaultConnectionForm = ({ appConnection, onSubmit }: Props)
|
||||
localStorage.setItem("latestCSRFToken", state);
|
||||
localStorage.setItem(
|
||||
"azureKeyVaultConnectionFormData",
|
||||
JSON.stringify({ ...formData, connectionId: appConnection?.id })
|
||||
JSON.stringify({
|
||||
...formData,
|
||||
connectionId: appConnection?.id,
|
||||
projectId,
|
||||
returnUrl
|
||||
} as AzureKeyVaultFormData)
|
||||
);
|
||||
window.location.assign(
|
||||
`https://login.microsoftonline.com/${formData.tenantId || "common"}/oauth2/v2.0/authorize?client_id=${oauthClientId}&response_type=code&redirect_uri=${window.location.origin}/organization/app-connections/azure/oauth/callback&response_mode=query&scope=https://vault.azure.net/.default%20openid%20offline_access&state=${state}<:>azure-key-vault`
|
||||
|
||||
+17
-3
@@ -25,7 +25,11 @@ import {
|
||||
OrgGatewayPermissionActions,
|
||||
OrgPermissionSubjects
|
||||
} from "@app/context/OrgPermissionContext/types";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import {
|
||||
APP_CONNECTION_MAP,
|
||||
getAppConnectionMethodDetails,
|
||||
useGetAppConnectionOauthReturnUrl
|
||||
} from "@app/helpers/appConnections";
|
||||
import { isInfisicalCloud } from "@app/helpers/platform";
|
||||
import { gatewaysQueryKeys } from "@app/hooks/api";
|
||||
import {
|
||||
@@ -35,6 +39,7 @@ import {
|
||||
} from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
|
||||
import { GithubFormData } from "../../../OauthCallbackPage/OauthCallbackPage.types";
|
||||
import {
|
||||
genericAppConnectionFieldsSchema,
|
||||
GenericAppConnectionsFields
|
||||
@@ -42,6 +47,7 @@ import {
|
||||
|
||||
type Props = {
|
||||
appConnection?: TGitHubConnection;
|
||||
projectId: string | undefined | null;
|
||||
};
|
||||
|
||||
const formSchema = genericAppConnectionFieldsSchema.extend({
|
||||
@@ -63,7 +69,7 @@ const formSchema = genericAppConnectionFieldsSchema.extend({
|
||||
|
||||
type FormData = z.infer<typeof formSchema>;
|
||||
|
||||
export const GitHubConnectionForm = ({ appConnection }: Props) => {
|
||||
export const GitHubConnectionForm = ({ appConnection, projectId }: Props) => {
|
||||
const isUpdate = Boolean(appConnection);
|
||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||
|
||||
@@ -98,13 +104,21 @@ export const GitHubConnectionForm = ({ appConnection }: Props) => {
|
||||
const selectedMethod = watch("method");
|
||||
const instanceType = watch("credentials.instanceType");
|
||||
|
||||
const returnUrl = useGetAppConnectionOauthReturnUrl();
|
||||
|
||||
const onSubmit = (formData: FormData) => {
|
||||
setIsRedirecting(true);
|
||||
const state = crypto.randomBytes(16).toString("hex");
|
||||
localStorage.setItem("latestCSRFToken", state);
|
||||
localStorage.setItem(
|
||||
"githubConnectionFormData",
|
||||
JSON.stringify({ ...formData, connectionId: appConnection?.id })
|
||||
JSON.stringify({
|
||||
...formData,
|
||||
credentials: formData.credentials as TGitHubConnection["credentials"],
|
||||
connectionId: appConnection?.id,
|
||||
projectId,
|
||||
returnUrl
|
||||
} as GithubFormData)
|
||||
);
|
||||
|
||||
const githubHost =
|
||||
|
||||
+16
-3
@@ -6,7 +6,11 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Button, FormControl, ModalClose, Select, SelectItem } from "@app/components/v2";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import {
|
||||
APP_CONNECTION_MAP,
|
||||
getAppConnectionMethodDetails,
|
||||
useGetAppConnectionOauthReturnUrl
|
||||
} from "@app/helpers/appConnections";
|
||||
import { isInfisicalCloud } from "@app/helpers/platform";
|
||||
import {
|
||||
GitHubRadarConnectionMethod,
|
||||
@@ -15,6 +19,7 @@ import {
|
||||
} from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
|
||||
import { GithubRadarFormData } from "../../../OauthCallbackPage/OauthCallbackPage.types";
|
||||
import {
|
||||
genericAppConnectionFieldsSchema,
|
||||
GenericAppConnectionsFields
|
||||
@@ -22,6 +27,7 @@ import {
|
||||
|
||||
type Props = {
|
||||
appConnection?: TGitHubRadarConnection;
|
||||
projectId: string | undefined | null;
|
||||
};
|
||||
|
||||
const formSchema = genericAppConnectionFieldsSchema.extend({
|
||||
@@ -31,7 +37,7 @@ const formSchema = genericAppConnectionFieldsSchema.extend({
|
||||
|
||||
type FormData = z.infer<typeof formSchema>;
|
||||
|
||||
export const GitHubRadarConnectionForm = ({ appConnection }: Props) => {
|
||||
export const GitHubRadarConnectionForm = ({ appConnection, projectId }: Props) => {
|
||||
const isUpdate = Boolean(appConnection);
|
||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||
|
||||
@@ -48,6 +54,8 @@ export const GitHubRadarConnectionForm = ({ appConnection }: Props) => {
|
||||
}
|
||||
});
|
||||
|
||||
const returnUrl = useGetAppConnectionOauthReturnUrl();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
@@ -63,7 +71,12 @@ export const GitHubRadarConnectionForm = ({ appConnection }: Props) => {
|
||||
localStorage.setItem("latestCSRFToken", state);
|
||||
localStorage.setItem(
|
||||
"githubRadarConnectionFormData",
|
||||
JSON.stringify({ ...formData, connectionId: appConnection?.id })
|
||||
JSON.stringify({
|
||||
...formData,
|
||||
connectionId: appConnection?.id,
|
||||
projectId,
|
||||
returnUrl
|
||||
} as GithubRadarFormData)
|
||||
);
|
||||
|
||||
switch (formData.method) {
|
||||
|
||||
+14
-4
@@ -16,7 +16,11 @@ import {
|
||||
Select,
|
||||
SelectItem
|
||||
} from "@app/components/v2";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import {
|
||||
APP_CONNECTION_MAP,
|
||||
getAppConnectionMethodDetails,
|
||||
useGetAppConnectionOauthReturnUrl
|
||||
} from "@app/helpers/appConnections";
|
||||
import { isInfisicalCloud } from "@app/helpers/platform";
|
||||
import { useGetAppConnectionOption } from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
@@ -26,6 +30,7 @@ import {
|
||||
TGitLabConnection
|
||||
} from "@app/hooks/api/appConnections/types/gitlab-connection";
|
||||
|
||||
import { GitLabFormData } from "../../../OauthCallbackPage/OauthCallbackPage.types";
|
||||
import {
|
||||
genericAppConnectionFieldsSchema,
|
||||
GenericAppConnectionsFields
|
||||
@@ -34,6 +39,7 @@ import {
|
||||
type Props = {
|
||||
appConnection?: TGitLabConnection;
|
||||
onSubmit: (formData: FormData) => Promise<void>;
|
||||
projectId: string | undefined | null;
|
||||
};
|
||||
|
||||
const formSchema = z.discriminatedUnion("method", [
|
||||
@@ -72,7 +78,7 @@ const formSchema = z.discriminatedUnion("method", [
|
||||
|
||||
type FormData = z.infer<typeof formSchema>;
|
||||
|
||||
export const GitLabConnectionForm = ({ appConnection, onSubmit: formSubmit }: Props) => {
|
||||
export const GitLabConnectionForm = ({ appConnection, onSubmit: formSubmit, projectId }: Props) => {
|
||||
const isUpdate = Boolean(appConnection);
|
||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||
|
||||
@@ -98,6 +104,8 @@ export const GitLabConnectionForm = ({ appConnection, onSubmit: formSubmit }: Pr
|
||||
} as FormData))
|
||||
});
|
||||
|
||||
const returnUrl = useGetAppConnectionOauthReturnUrl();
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
@@ -132,8 +140,10 @@ export const GitLabConnectionForm = ({ appConnection, onSubmit: formSubmit }: Pr
|
||||
JSON.stringify({
|
||||
...formData,
|
||||
connectionId: appConnection?.id,
|
||||
isUpdate
|
||||
})
|
||||
isUpdate,
|
||||
projectId,
|
||||
returnUrl
|
||||
} as GitLabFormData)
|
||||
);
|
||||
|
||||
// Redirect to Gitlab OAuth
|
||||
|
||||
+4
-2
@@ -9,14 +9,16 @@ import { APP_CONNECTION_MAP } from "@app/helpers/appConnections";
|
||||
import { usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
|
||||
import { useAppConnectionOptions } from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
|
||||
type Props = {
|
||||
onSelect: (app: AppConnection) => void;
|
||||
projectType?: ProjectType;
|
||||
};
|
||||
|
||||
export const AppConnectionsSelect = ({ onSelect }: Props) => {
|
||||
export const AppConnectionsSelect = ({ onSelect, projectType }: Props) => {
|
||||
const { subscription } = useSubscription();
|
||||
const { isPending, data: appConnectionOptions } = useAppConnectionOptions();
|
||||
const { isPending, data: appConnectionOptions } = useAppConnectionOptions(projectType);
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["upgradePlan"] as const);
|
||||
|
||||
|
||||
+127
-44
@@ -1,19 +1,23 @@
|
||||
import { useCallback } from "react";
|
||||
import { subject } from "@casl/ability";
|
||||
import {
|
||||
faAsterisk,
|
||||
faBuilding,
|
||||
faCheck,
|
||||
faCopy,
|
||||
faEdit,
|
||||
faEllipsisV,
|
||||
faInfoCircle,
|
||||
faServer,
|
||||
faTable,
|
||||
faTrash
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { OrgPermissionCan } from "@app/components/permissions";
|
||||
import { VariablePermissionCan } from "@app/components/permissions";
|
||||
import {
|
||||
Badge,
|
||||
DropdownMenu,
|
||||
@@ -25,9 +29,11 @@ import {
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { OrgPermissionSubjects } from "@app/context";
|
||||
import { OrgPermissionSubjects, ProjectPermissionSub } from "@app/context";
|
||||
import { OrgPermissionAppConnectionActions } from "@app/context/OrgPermissionContext/types";
|
||||
import { ProjectPermissionAppConnectionActions } from "@app/context/ProjectPermissionContext/types";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import { useToggle } from "@app/hooks";
|
||||
import { TAppConnection } from "@app/hooks/api/appConnections";
|
||||
|
||||
@@ -36,15 +42,18 @@ type Props = {
|
||||
onDelete: (appConnection: TAppConnection) => void;
|
||||
onEditCredentials: (appConnection: TAppConnection) => void;
|
||||
onEditDetails: (appConnection: TAppConnection) => void;
|
||||
isProjectView: boolean;
|
||||
};
|
||||
|
||||
export const AppConnectionRow = ({
|
||||
appConnection,
|
||||
onDelete,
|
||||
onEditCredentials,
|
||||
onEditDetails
|
||||
onEditDetails,
|
||||
isProjectView
|
||||
}: Props) => {
|
||||
const { id, name, method, app, description, isPlatformManagedCredentials } = appConnection;
|
||||
const { id, name, method, app, description, isPlatformManagedCredentials, project } =
|
||||
appConnection;
|
||||
|
||||
const [isIdCopied, setIsIdCopied] = useToggle(false);
|
||||
|
||||
@@ -111,7 +120,38 @@ export const AppConnectionRow = ({
|
||||
{methodDetails.name}
|
||||
</p>
|
||||
</Td>
|
||||
|
||||
{!isProjectView && (
|
||||
<Td className="!min-w-[8rem] max-w-0">
|
||||
{project ? (
|
||||
<Link
|
||||
// @ts-expect-error app-connections aren't in kms/ssh
|
||||
to={`${getProjectBaseURL(project.type)}/app-connections`}
|
||||
params={{
|
||||
projectId: project.id
|
||||
}}
|
||||
className="underline"
|
||||
>
|
||||
<p className="truncate">
|
||||
<FontAwesomeIcon
|
||||
size="sm"
|
||||
className="mr-1.5 text-mineshaft-300/75"
|
||||
icon={faTable}
|
||||
/>
|
||||
{project.name}
|
||||
</p>
|
||||
</Link>
|
||||
) : (
|
||||
<p className="truncate">
|
||||
<FontAwesomeIcon
|
||||
size="sm"
|
||||
className="mr-1.5 text-mineshaft-300/75"
|
||||
icon={faBuilding}
|
||||
/>
|
||||
Organization
|
||||
</p>
|
||||
)}
|
||||
</Td>
|
||||
)}
|
||||
<Td>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
{isPlatformManagedCredentials && (
|
||||
@@ -143,48 +183,91 @@ export const AppConnectionRow = ({
|
||||
>
|
||||
Copy Connection ID
|
||||
</DropdownMenuItem>
|
||||
<OrgPermissionCan
|
||||
I={OrgPermissionAppConnectionActions.Edit}
|
||||
a={OrgPermissionSubjects.AppConnections}
|
||||
>
|
||||
{(isAllowed: boolean) => (
|
||||
<DropdownMenuItem
|
||||
isDisabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faEdit} />}
|
||||
onClick={() => onEditDetails(appConnection)}
|
||||
{(isProjectView || !project) && (
|
||||
<>
|
||||
<VariablePermissionCan
|
||||
type={isProjectView ? "project" : "org"}
|
||||
I={
|
||||
isProjectView
|
||||
? ProjectPermissionAppConnectionActions.Edit
|
||||
: OrgPermissionAppConnectionActions.Edit
|
||||
}
|
||||
a={
|
||||
isProjectView
|
||||
? subject(ProjectPermissionSub.AppConnections, {
|
||||
connectionId: id
|
||||
})
|
||||
: subject(OrgPermissionSubjects.AppConnections, {
|
||||
connectionId: id
|
||||
})
|
||||
}
|
||||
>
|
||||
Edit Details
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
<OrgPermissionCan
|
||||
I={OrgPermissionAppConnectionActions.Edit}
|
||||
a={OrgPermissionSubjects.AppConnections}
|
||||
>
|
||||
{(isAllowed: boolean) => (
|
||||
<DropdownMenuItem
|
||||
isDisabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faAsterisk} />}
|
||||
onClick={() => onEditCredentials(appConnection)}
|
||||
{(isAllowed: boolean) => (
|
||||
<DropdownMenuItem
|
||||
isDisabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faEdit} />}
|
||||
onClick={() => onEditDetails(appConnection)}
|
||||
>
|
||||
Edit Details
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</VariablePermissionCan>
|
||||
<VariablePermissionCan
|
||||
type={isProjectView ? "project" : "org"}
|
||||
I={
|
||||
isProjectView
|
||||
? ProjectPermissionAppConnectionActions.Edit
|
||||
: OrgPermissionAppConnectionActions.Edit
|
||||
}
|
||||
a={
|
||||
isProjectView
|
||||
? subject(ProjectPermissionSub.AppConnections, {
|
||||
connectionId: id
|
||||
})
|
||||
: subject(OrgPermissionSubjects.AppConnections, {
|
||||
connectionId: id
|
||||
})
|
||||
}
|
||||
>
|
||||
{isPlatformManagedCredentials ? "View" : "Edit"} Credentials
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
<OrgPermissionCan
|
||||
I={OrgPermissionAppConnectionActions.Delete}
|
||||
a={OrgPermissionSubjects.AppConnections}
|
||||
>
|
||||
{(isAllowed: boolean) => (
|
||||
<DropdownMenuItem
|
||||
isDisabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faTrash} />}
|
||||
onClick={() => onDelete(appConnection)}
|
||||
{(isAllowed: boolean) => (
|
||||
<DropdownMenuItem
|
||||
isDisabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faAsterisk} />}
|
||||
onClick={() => onEditCredentials(appConnection)}
|
||||
>
|
||||
{isPlatformManagedCredentials ? "View" : "Edit"} Credentials
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</VariablePermissionCan>
|
||||
<VariablePermissionCan
|
||||
type={isProjectView ? "project" : "org"}
|
||||
I={
|
||||
isProjectView
|
||||
? ProjectPermissionAppConnectionActions.Delete
|
||||
: OrgPermissionAppConnectionActions.Delete
|
||||
}
|
||||
a={
|
||||
isProjectView
|
||||
? subject(ProjectPermissionSub.AppConnections, {
|
||||
connectionId: id
|
||||
})
|
||||
: subject(OrgPermissionSubjects.AppConnections, {
|
||||
connectionId: id
|
||||
})
|
||||
}
|
||||
>
|
||||
Delete Connection
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
{(isAllowed: boolean) => (
|
||||
<DropdownMenuItem
|
||||
isDisabled={!isAllowed}
|
||||
icon={<FontAwesomeIcon icon={faTrash} />}
|
||||
onClick={() => onDelete(appConnection)}
|
||||
>
|
||||
Delete Connection
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</VariablePermissionCan>
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</Tooltip>
|
||||
|
||||
+188
-36
@@ -2,16 +2,21 @@ import { useMemo, useState } from "react";
|
||||
import {
|
||||
faArrowDown,
|
||||
faArrowUp,
|
||||
faArrowUpRightFromSquare,
|
||||
faBookOpen,
|
||||
faCheckCircle,
|
||||
faFilter,
|
||||
faMagnifyingGlass,
|
||||
faPlug,
|
||||
faPlus,
|
||||
faSearch
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { VariablePermissionCan } from "@app/components/permissions";
|
||||
import {
|
||||
Button,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
@@ -29,6 +34,9 @@ import {
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { OrgPermissionSubjects, ProjectPermissionSub } from "@app/context";
|
||||
import { OrgPermissionAppConnectionActions } from "@app/context/OrgPermissionContext/types";
|
||||
import { ProjectPermissionAppConnectionActions } from "@app/context/ProjectPermissionContext/types";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import {
|
||||
getUserTablePreference,
|
||||
@@ -39,7 +47,9 @@ import { usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
|
||||
import { TAppConnection, useListAppConnections } from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
|
||||
import { AddAppConnectionModal } from "./AddAppConnectionModal";
|
||||
import { AppConnectionRow } from "./AppConnectionRow";
|
||||
import { DeleteAppConnectionModal } from "./DeleteAppConnectionModal";
|
||||
import { EditAppConnectionCredentialsModal } from "./EditAppConnectionCredentialsModal";
|
||||
@@ -48,22 +58,45 @@ import { EditAppConnectionDetailsModal } from "./EditAppConnectionDetailsModal";
|
||||
enum AppConnectionsOrderBy {
|
||||
App = "app",
|
||||
Name = "name",
|
||||
Method = "method"
|
||||
Method = "method",
|
||||
ManagedBy = "managed-by"
|
||||
}
|
||||
|
||||
type AppConnectionFilters = {
|
||||
apps: AppConnection[];
|
||||
};
|
||||
|
||||
export const AppConnectionsTable = () => {
|
||||
const { isPending, data: appConnections = [] } = useListAppConnections();
|
||||
enum View {
|
||||
All = "all",
|
||||
Scope = "scope"
|
||||
}
|
||||
|
||||
const APP_CONNECTION_VIEW_STORAGE_KEY = "app-connection-view";
|
||||
|
||||
type Props = {
|
||||
projectId?: string;
|
||||
projectType?: ProjectType;
|
||||
};
|
||||
|
||||
export const AppConnectionsTable = ({ projectId, projectType }: Props) => {
|
||||
const isProjectView = Boolean(projectId);
|
||||
const { isPending, data: appConnections = [] } = useListAppConnections(projectId);
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
||||
"addConnection",
|
||||
"deleteConnection",
|
||||
"editCredentials",
|
||||
"editDetails"
|
||||
] as const);
|
||||
|
||||
const [view, setView] = useState<View>(() => {
|
||||
const storedView = localStorage.getItem(APP_CONNECTION_VIEW_STORAGE_KEY) as View | null;
|
||||
|
||||
if (storedView && Object.values(View).includes(storedView)) return storedView;
|
||||
|
||||
return View.Scope;
|
||||
});
|
||||
|
||||
const [filters, setFilters] = useState<AppConnectionFilters>({
|
||||
apps: []
|
||||
});
|
||||
@@ -96,6 +129,10 @@ export const AppConnectionsTable = () => {
|
||||
.filter((appConnection) => {
|
||||
const { app, method, name } = appConnection;
|
||||
|
||||
if (view === View.Scope && !isProjectView && appConnection.projectId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filters.apps.length && !filters.apps.includes(app)) return false;
|
||||
|
||||
const searchValue = search.trim().toLowerCase();
|
||||
@@ -121,6 +158,13 @@ export const AppConnectionsTable = () => {
|
||||
.localeCompare(
|
||||
getAppConnectionMethodDetails(connectionTwo.method).name.toLowerCase()
|
||||
);
|
||||
case AppConnectionsOrderBy.ManagedBy:
|
||||
if (!connectionOne.project) return 1;
|
||||
if (!connectionTwo.project) return -1;
|
||||
|
||||
return connectionOne.project.name
|
||||
.toLowerCase()
|
||||
.localeCompare(connectionTwo.project.name.toLowerCase());
|
||||
case AppConnectionsOrderBy.App:
|
||||
default:
|
||||
return APP_CONNECTION_MAP[connectionOne.app].name
|
||||
@@ -128,7 +172,7 @@ export const AppConnectionsTable = () => {
|
||||
.localeCompare(APP_CONNECTION_MAP[connectionTwo.app].name.toLowerCase());
|
||||
}
|
||||
}),
|
||||
[appConnections, orderDirection, search, orderBy, filters]
|
||||
[appConnections, orderDirection, search, orderBy, filters, view]
|
||||
);
|
||||
|
||||
useResetPageHelper({
|
||||
@@ -165,8 +209,87 @@ export const AppConnectionsTable = () => {
|
||||
handlePopUpOpen("editDetails", appConnection);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<div>
|
||||
<div className="flex items-center gap-1">
|
||||
<p className="text-xl font-semibold text-mineshaft-100">App Connections</p>
|
||||
<a
|
||||
href="https://infisical.com/docs/integrations/app-connections/overview"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<div className="ml-1 mt-[0.12rem] inline-block rounded-md bg-yellow/20 px-1.5 text-sm text-yellow opacity-80 hover:opacity-100">
|
||||
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||
<span>Docs</span>
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowUpRightFromSquare}
|
||||
className="mb-[0.07rem] ml-1.5 text-[10px]"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<p className="text-sm text-bunker-300">
|
||||
Create and configure connections with third-party apps for re-use across your project
|
||||
{isProjectView ? "" : "s"}.
|
||||
</p>
|
||||
</div>
|
||||
<VariablePermissionCan
|
||||
type={isProjectView ? "project" : "org"}
|
||||
I={
|
||||
isProjectView
|
||||
? ProjectPermissionAppConnectionActions.Create
|
||||
: OrgPermissionAppConnectionActions.Create
|
||||
}
|
||||
a={
|
||||
isProjectView
|
||||
? ProjectPermissionSub.AppConnections
|
||||
: OrgPermissionSubjects.AppConnections
|
||||
}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => handlePopUpOpen("addConnection")}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Add Connection
|
||||
</Button>
|
||||
)}
|
||||
</VariablePermissionCan>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
{!isProjectView && (
|
||||
<div className="flex gap-x-0.5 rounded-md border border-mineshaft-600 bg-mineshaft-800 p-1">
|
||||
<Button
|
||||
variant="outline_bg"
|
||||
onClick={() => {
|
||||
setView(View.Scope);
|
||||
localStorage.setItem(APP_CONNECTION_VIEW_STORAGE_KEY, View.Scope);
|
||||
}}
|
||||
size="xs"
|
||||
className={`${
|
||||
view === View.Scope ? "bg-mineshaft-500" : "bg-transparent"
|
||||
} min-w-[5rem] rounded border-none hover:bg-mineshaft-600`}
|
||||
>
|
||||
Organization
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline_bg"
|
||||
onClick={() => {
|
||||
setView(View.All);
|
||||
localStorage.setItem(APP_CONNECTION_VIEW_STORAGE_KEY, View.All);
|
||||
}}
|
||||
size="xs"
|
||||
className={`${
|
||||
view === View.All ? "bg-mineshaft-500" : "bg-transparent"
|
||||
} min-w-[5rem] rounded border-none hover:bg-mineshaft-600`}
|
||||
>
|
||||
All
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<Input
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
@@ -188,38 +311,46 @@ export const AppConnectionsTable = () => {
|
||||
<FontAwesomeIcon icon={faFilter} />
|
||||
</IconButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="thin-scrollbar max-h-[70vh] overflow-y-auto" align="end">
|
||||
<DropdownMenuContent
|
||||
sideOffset={2}
|
||||
className="thin-scrollbar max-h-[70vh] overflow-y-auto"
|
||||
align="end"
|
||||
>
|
||||
<DropdownMenuLabel>Filter by Apps</DropdownMenuLabel>
|
||||
{appConnections.length ? (
|
||||
[...new Set(appConnections.map(({ app }) => app))].map((app) => (
|
||||
<DropdownMenuItem
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setFilters((prev) => ({
|
||||
...prev,
|
||||
apps: prev.apps.includes(app)
|
||||
? prev.apps.filter((a) => a !== app)
|
||||
: [...prev.apps, app]
|
||||
}));
|
||||
}}
|
||||
key={app}
|
||||
icon={
|
||||
filters.apps.includes(app) && (
|
||||
<FontAwesomeIcon className="text-primary" icon={faCheckCircle} />
|
||||
)
|
||||
}
|
||||
iconPos="right"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<img
|
||||
alt={`${APP_CONNECTION_MAP[app].name} integration`}
|
||||
src={`/images/integrations/${APP_CONNECTION_MAP[app].image}`}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
<span>{APP_CONNECTION_MAP[app].name}</span>
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
))
|
||||
[...new Set(appConnections.map(({ app }) => app))]
|
||||
.sort((a, b) => {
|
||||
return a.toLowerCase().localeCompare(b.toLowerCase());
|
||||
})
|
||||
.map((app) => (
|
||||
<DropdownMenuItem
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setFilters((prev) => ({
|
||||
...prev,
|
||||
apps: prev.apps.includes(app)
|
||||
? prev.apps.filter((a) => a !== app)
|
||||
: [...prev.apps, app]
|
||||
}));
|
||||
}}
|
||||
key={app}
|
||||
icon={
|
||||
filters.apps.includes(app) && (
|
||||
<FontAwesomeIcon className="text-primary" icon={faCheckCircle} />
|
||||
)
|
||||
}
|
||||
iconPos="right"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<img
|
||||
alt={`${APP_CONNECTION_MAP[app].name} integration`}
|
||||
src={`/images/integrations/${APP_CONNECTION_MAP[app].image}`}
|
||||
className="h-4 w-4"
|
||||
/>
|
||||
<span>{APP_CONNECTION_MAP[app].name}</span>
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
))
|
||||
) : (
|
||||
<DropdownMenuItem isDisabled>No Connections Configured</DropdownMenuItem>
|
||||
)}
|
||||
@@ -269,7 +400,21 @@ export const AppConnectionsTable = () => {
|
||||
</IconButton>
|
||||
</div>
|
||||
</Th>
|
||||
|
||||
{!isProjectView && (
|
||||
<Th>
|
||||
<div className="flex items-center">
|
||||
Managed By
|
||||
<IconButton
|
||||
variant="plain"
|
||||
className={getClassName(AppConnectionsOrderBy.ManagedBy)}
|
||||
ariaLabel="sort"
|
||||
onClick={() => handleSort(AppConnectionsOrderBy.ManagedBy)}
|
||||
>
|
||||
<FontAwesomeIcon icon={getColSortIcon(AppConnectionsOrderBy.ManagedBy)} />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Th>
|
||||
)}
|
||||
<Th className="w-5" />
|
||||
</Tr>
|
||||
</THead>
|
||||
@@ -284,6 +429,7 @@ export const AppConnectionsTable = () => {
|
||||
onDelete={handleDelete}
|
||||
onEditCredentials={handleEditCredentials}
|
||||
onEditDetails={handleEditDetails}
|
||||
isProjectView={isProjectView}
|
||||
/>
|
||||
))}
|
||||
</TBody>
|
||||
@@ -323,6 +469,12 @@ export const AppConnectionsTable = () => {
|
||||
onOpenChange={(isOpen) => handlePopUpToggle("editDetails", isOpen)}
|
||||
appConnection={popUp.editDetails.data}
|
||||
/>
|
||||
<AddAppConnectionModal
|
||||
isOpen={popUp.addConnection.isOpen}
|
||||
onOpenChange={(isOpen) => handlePopUpToggle("addConnection", isOpen)}
|
||||
projectId={projectId}
|
||||
projectType={projectType}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+127
-111
@@ -12,73 +12,14 @@ import {
|
||||
AzureKeyVaultConnectionMethod,
|
||||
GitHubConnectionMethod,
|
||||
GitLabConnectionMethod,
|
||||
TAzureAppConfigurationConnection,
|
||||
TAzureClientSecretsConnection,
|
||||
TAzureDevOpsConnection,
|
||||
TAzureKeyVaultConnection,
|
||||
TGitHubConnection,
|
||||
TGitHubRadarConnection,
|
||||
TGitLabConnection,
|
||||
TAppConnection,
|
||||
useCreateAppConnection,
|
||||
useUpdateAppConnection
|
||||
} from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { IntegrationsListPageTabs } from "@app/types/integrations";
|
||||
|
||||
type BaseFormData = {
|
||||
returnUrl?: string;
|
||||
connectionId?: string;
|
||||
isUpdate?: boolean;
|
||||
};
|
||||
|
||||
type GithubFormData = BaseFormData &
|
||||
Pick<TGitHubConnection, "name" | "method" | "description" | "gatewayId" | "credentials">;
|
||||
|
||||
type GithubRadarFormData = BaseFormData &
|
||||
Pick<TGitHubRadarConnection, "name" | "method" | "description">;
|
||||
|
||||
type GitLabFormData = BaseFormData &
|
||||
Pick<TGitLabConnection, "name" | "method" | "description" | "credentials">;
|
||||
|
||||
type AzureKeyVaultFormData = BaseFormData &
|
||||
Pick<TAzureKeyVaultConnection, "name" | "method" | "description"> &
|
||||
Pick<TAzureKeyVaultConnection["credentials"], "tenantId">;
|
||||
|
||||
type AzureAppConfigurationFormData = BaseFormData &
|
||||
Pick<TAzureAppConfigurationConnection, "name" | "method" | "description"> &
|
||||
Pick<TAzureAppConfigurationConnection["credentials"], "tenantId">;
|
||||
|
||||
type AzureClientSecretsFormData = BaseFormData &
|
||||
Pick<TAzureClientSecretsConnection, "name" | "method" | "description"> &
|
||||
Pick<TAzureClientSecretsConnection["credentials"], "tenantId">;
|
||||
|
||||
type OAuthCredentials = Extract<
|
||||
TAzureDevOpsConnection,
|
||||
{ method: AzureDevOpsConnectionMethod.OAuth }
|
||||
>["credentials"];
|
||||
type AccessTokenCredentials = Extract<
|
||||
TAzureDevOpsConnection,
|
||||
{ method: AzureDevOpsConnectionMethod.AccessToken }
|
||||
>["credentials"];
|
||||
|
||||
type AzureDevOpsFormData = BaseFormData &
|
||||
Pick<TAzureDevOpsConnection, "name" | "method" | "description"> &
|
||||
(Pick<OAuthCredentials, "tenantId" | "orgName"> | Pick<AccessTokenCredentials, "orgName">);
|
||||
|
||||
type FormDataMap = {
|
||||
[AppConnection.GitHub]: GithubFormData & { app: AppConnection.GitHub };
|
||||
[AppConnection.GitHubRadar]: GithubRadarFormData & { app: AppConnection.GitHubRadar };
|
||||
[AppConnection.GitLab]: GitLabFormData & { app: AppConnection.GitLab };
|
||||
[AppConnection.AzureKeyVault]: AzureKeyVaultFormData & { app: AppConnection.AzureKeyVault };
|
||||
[AppConnection.AzureAppConfiguration]: AzureAppConfigurationFormData & {
|
||||
app: AppConnection.AzureAppConfiguration;
|
||||
};
|
||||
[AppConnection.AzureClientSecrets]: AzureClientSecretsFormData & {
|
||||
app: AppConnection.AzureClientSecrets;
|
||||
};
|
||||
[AppConnection.AzureDevOps]: AzureDevOpsFormData & {
|
||||
app: AppConnection.AzureDevOps;
|
||||
};
|
||||
};
|
||||
import { FormDataMap } from "./OauthCallbackPage.types";
|
||||
|
||||
const formDataStorageFieldMap: Partial<Record<AppConnection, string>> = {
|
||||
[AppConnection.GitHub]: "githubConnectionFormData",
|
||||
@@ -148,11 +89,14 @@ export const OAuthCallbackPage = () => {
|
||||
|
||||
clearState(AppConnection.GitLab);
|
||||
|
||||
const { connectionId, name, description, returnUrl, isUpdate, credentials } = formData;
|
||||
const { connectionId, name, description, returnUrl, isUpdate, projectId, credentials } =
|
||||
formData;
|
||||
|
||||
let connection: TAppConnection;
|
||||
|
||||
try {
|
||||
if (isUpdate && connectionId) {
|
||||
await updateAppConnection.mutateAsync({
|
||||
connection = await updateAppConnection.mutateAsync({
|
||||
app: AppConnection.GitLab,
|
||||
connectionId,
|
||||
credentials: {
|
||||
@@ -161,10 +105,11 @@ export const OAuthCallbackPage = () => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await createAppConnection.mutateAsync({
|
||||
connection = await createAppConnection.mutateAsync({
|
||||
app: AppConnection.GitLab,
|
||||
name,
|
||||
description,
|
||||
projectId,
|
||||
method: GitLabConnectionMethod.OAuth,
|
||||
credentials: {
|
||||
code: code as string,
|
||||
@@ -173,14 +118,12 @@ export const OAuthCallbackPage = () => {
|
||||
});
|
||||
}
|
||||
|
||||
navigate({
|
||||
to: returnUrl ?? "/organization/app-connections"
|
||||
});
|
||||
|
||||
return {
|
||||
connectionId,
|
||||
returnUrl,
|
||||
appConnectionName: formData.app
|
||||
appConnectionName: formData.app,
|
||||
projectId,
|
||||
connection
|
||||
};
|
||||
} catch (err: any) {
|
||||
createNotification({
|
||||
@@ -189,7 +132,10 @@ export const OAuthCallbackPage = () => {
|
||||
type: "error"
|
||||
});
|
||||
navigate({
|
||||
to: returnUrl ?? "/organization/app-connections"
|
||||
to: returnUrl,
|
||||
params: {
|
||||
projectId
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
@@ -201,11 +147,13 @@ export const OAuthCallbackPage = () => {
|
||||
|
||||
clearState(AppConnection.AzureKeyVault);
|
||||
|
||||
const { connectionId, name, description, returnUrl } = formData;
|
||||
const { connectionId, name, description, returnUrl, projectId } = formData;
|
||||
|
||||
let connection: TAppConnection;
|
||||
|
||||
try {
|
||||
if (connectionId) {
|
||||
await updateAppConnection.mutateAsync({
|
||||
connection = await updateAppConnection.mutateAsync({
|
||||
app: AppConnection.AzureKeyVault,
|
||||
connectionId,
|
||||
credentials: {
|
||||
@@ -214,10 +162,11 @@ export const OAuthCallbackPage = () => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await createAppConnection.mutateAsync({
|
||||
connection = await createAppConnection.mutateAsync({
|
||||
app: AppConnection.AzureKeyVault,
|
||||
name,
|
||||
description,
|
||||
projectId,
|
||||
method: AzureKeyVaultConnectionMethod.OAuth,
|
||||
credentials: {
|
||||
tenantId: formData.tenantId,
|
||||
@@ -232,14 +181,20 @@ export const OAuthCallbackPage = () => {
|
||||
type: "error"
|
||||
});
|
||||
navigate({
|
||||
to: returnUrl ?? "/organization/app-connections"
|
||||
to: returnUrl,
|
||||
params: {
|
||||
projectId
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
connectionId,
|
||||
returnUrl,
|
||||
appConnectionName: formData.app
|
||||
appConnectionName: formData.app,
|
||||
projectId,
|
||||
connection
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -249,11 +204,13 @@ export const OAuthCallbackPage = () => {
|
||||
|
||||
clearState(AppConnection.AzureAppConfiguration);
|
||||
|
||||
const { connectionId, name, description, returnUrl } = formData;
|
||||
const { connectionId, name, description, returnUrl, projectId } = formData;
|
||||
|
||||
let connection: TAppConnection;
|
||||
|
||||
try {
|
||||
if (connectionId) {
|
||||
await updateAppConnection.mutateAsync({
|
||||
connection = await updateAppConnection.mutateAsync({
|
||||
app: AppConnection.AzureAppConfiguration,
|
||||
connectionId,
|
||||
credentials: {
|
||||
@@ -262,10 +219,11 @@ export const OAuthCallbackPage = () => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await createAppConnection.mutateAsync({
|
||||
connection = await createAppConnection.mutateAsync({
|
||||
app: AppConnection.AzureAppConfiguration,
|
||||
name,
|
||||
description,
|
||||
projectId,
|
||||
method: AzureAppConfigurationConnectionMethod.OAuth,
|
||||
credentials: {
|
||||
code: code as string,
|
||||
@@ -280,14 +238,20 @@ export const OAuthCallbackPage = () => {
|
||||
type: "error"
|
||||
});
|
||||
navigate({
|
||||
to: returnUrl ?? "/organization/app-connections"
|
||||
to: returnUrl,
|
||||
params: {
|
||||
projectId
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
connectionId,
|
||||
returnUrl,
|
||||
appConnectionName: formData.app
|
||||
appConnectionName: formData.app,
|
||||
projectId,
|
||||
connection
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -297,11 +261,13 @@ export const OAuthCallbackPage = () => {
|
||||
|
||||
clearState(AppConnection.AzureClientSecrets);
|
||||
|
||||
const { connectionId, name, description, returnUrl } = formData;
|
||||
const { connectionId, name, description, returnUrl, projectId } = formData;
|
||||
|
||||
let connection: TAppConnection;
|
||||
|
||||
try {
|
||||
if (connectionId) {
|
||||
await updateAppConnection.mutateAsync({
|
||||
connection = await updateAppConnection.mutateAsync({
|
||||
app: AppConnection.AzureClientSecrets,
|
||||
connectionId,
|
||||
credentials: {
|
||||
@@ -310,11 +276,12 @@ export const OAuthCallbackPage = () => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await createAppConnection.mutateAsync({
|
||||
connection = await createAppConnection.mutateAsync({
|
||||
app: AppConnection.AzureClientSecrets,
|
||||
name,
|
||||
description,
|
||||
method: AzureClientSecretsConnectionMethod.OAuth,
|
||||
projectId,
|
||||
credentials: {
|
||||
code: code as string,
|
||||
tenantId: formData.tenantId
|
||||
@@ -328,14 +295,20 @@ export const OAuthCallbackPage = () => {
|
||||
type: "error"
|
||||
});
|
||||
navigate({
|
||||
to: returnUrl ?? "/organization/app-connections"
|
||||
to: returnUrl,
|
||||
params: {
|
||||
projectId
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
connectionId,
|
||||
returnUrl,
|
||||
appConnectionName: formData.app
|
||||
appConnectionName: formData.app,
|
||||
projectId,
|
||||
connection
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -345,7 +318,9 @@ export const OAuthCallbackPage = () => {
|
||||
|
||||
clearState(AppConnection.AzureDevOps);
|
||||
|
||||
const { connectionId, name, description, returnUrl } = formData;
|
||||
const { connectionId, name, description, returnUrl, projectId } = formData;
|
||||
|
||||
let connection: TAppConnection;
|
||||
|
||||
try {
|
||||
if (!("tenantId" in formData)) {
|
||||
@@ -353,7 +328,7 @@ export const OAuthCallbackPage = () => {
|
||||
}
|
||||
|
||||
if (connectionId) {
|
||||
await updateAppConnection.mutateAsync({
|
||||
connection = await updateAppConnection.mutateAsync({
|
||||
app: AppConnection.AzureDevOps,
|
||||
connectionId,
|
||||
credentials: {
|
||||
@@ -363,11 +338,12 @@ export const OAuthCallbackPage = () => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await createAppConnection.mutateAsync({
|
||||
connection = await createAppConnection.mutateAsync({
|
||||
app: AppConnection.AzureDevOps,
|
||||
name,
|
||||
description,
|
||||
method: AzureDevOpsConnectionMethod.OAuth,
|
||||
projectId,
|
||||
credentials: {
|
||||
code: code as string,
|
||||
tenantId: formData.tenantId as string,
|
||||
@@ -382,14 +358,20 @@ export const OAuthCallbackPage = () => {
|
||||
type: "error"
|
||||
});
|
||||
navigate({
|
||||
to: returnUrl ?? "/organization/app-connections"
|
||||
to: returnUrl,
|
||||
params: {
|
||||
projectId
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
connectionId,
|
||||
returnUrl,
|
||||
appConnectionName: formData.app
|
||||
appConnectionName: formData.app,
|
||||
projectId,
|
||||
connection
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -399,11 +381,14 @@ export const OAuthCallbackPage = () => {
|
||||
|
||||
clearState(AppConnection.GitHub);
|
||||
|
||||
const { connectionId, name, description, returnUrl, gatewayId, credentials } = formData;
|
||||
const { connectionId, name, description, returnUrl, gatewayId, credentials, projectId } =
|
||||
formData;
|
||||
|
||||
let connection: TAppConnection;
|
||||
|
||||
try {
|
||||
if (connectionId) {
|
||||
await updateAppConnection.mutateAsync({
|
||||
connection = await updateAppConnection.mutateAsync({
|
||||
app: AppConnection.GitHub,
|
||||
...(installationId
|
||||
? {
|
||||
@@ -427,10 +412,11 @@ export const OAuthCallbackPage = () => {
|
||||
})
|
||||
});
|
||||
} else {
|
||||
await createAppConnection.mutateAsync({
|
||||
connection = await createAppConnection.mutateAsync({
|
||||
app: AppConnection.GitHub,
|
||||
name,
|
||||
description,
|
||||
projectId,
|
||||
...(installationId
|
||||
? {
|
||||
method: GitHubConnectionMethod.App,
|
||||
@@ -460,14 +446,20 @@ export const OAuthCallbackPage = () => {
|
||||
type: "error"
|
||||
});
|
||||
navigate({
|
||||
to: returnUrl ?? "/organization/app-connections"
|
||||
to: returnUrl,
|
||||
params: {
|
||||
projectId
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
connectionId,
|
||||
returnUrl,
|
||||
appConnectionName: formData.app
|
||||
appConnectionName: formData.app,
|
||||
projectId,
|
||||
connection
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -477,11 +469,13 @@ export const OAuthCallbackPage = () => {
|
||||
|
||||
clearState(AppConnection.GitHubRadar);
|
||||
|
||||
const { connectionId, name, description, returnUrl } = formData;
|
||||
const { connectionId, name, description, returnUrl, projectId } = formData;
|
||||
|
||||
let connection: TAppConnection;
|
||||
|
||||
try {
|
||||
if (connectionId) {
|
||||
await updateAppConnection.mutateAsync({
|
||||
connection = await updateAppConnection.mutateAsync({
|
||||
app: AppConnection.GitHubRadar,
|
||||
connectionId,
|
||||
credentials: {
|
||||
@@ -490,11 +484,12 @@ export const OAuthCallbackPage = () => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await createAppConnection.mutateAsync({
|
||||
connection = await createAppConnection.mutateAsync({
|
||||
app: AppConnection.GitHubRadar,
|
||||
name,
|
||||
description,
|
||||
method: GitHubConnectionMethod.App,
|
||||
projectId,
|
||||
credentials: {
|
||||
code: code as string,
|
||||
installationId: installationId as string
|
||||
@@ -508,14 +503,20 @@ export const OAuthCallbackPage = () => {
|
||||
type: "error"
|
||||
});
|
||||
navigate({
|
||||
to: returnUrl ?? "/organization/app-connections"
|
||||
to: returnUrl,
|
||||
params: {
|
||||
projectId
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
connectionId,
|
||||
returnUrl,
|
||||
appConnectionName: formData.app
|
||||
appConnectionName: formData.app,
|
||||
projectId,
|
||||
connection
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -530,8 +531,13 @@ export const OAuthCallbackPage = () => {
|
||||
if (!isReady) return;
|
||||
|
||||
(async () => {
|
||||
let data: { connectionId?: string; returnUrl?: string; appConnectionName?: string } | null =
|
||||
null;
|
||||
let data: {
|
||||
returnUrl: string;
|
||||
appConnectionName: string;
|
||||
connectionId?: string;
|
||||
projectId?: string;
|
||||
connection: TAppConnection;
|
||||
} | null = null;
|
||||
|
||||
if (appConnection === AppConnection.GitHub) {
|
||||
data = await handleGithub();
|
||||
@@ -554,16 +560,26 @@ export const OAuthCallbackPage = () => {
|
||||
text: `Successfully ${data.connectionId ? "updated" : "added"} ${data.appConnectionName ? APP_CONNECTION_MAP[data.appConnectionName as AppConnection].name : ""} Connection`,
|
||||
type: "success"
|
||||
});
|
||||
} else {
|
||||
createNotification({
|
||||
text: "Failed to add connection",
|
||||
type: "error"
|
||||
|
||||
await navigate({
|
||||
to: data.returnUrl,
|
||||
params: {
|
||||
projectId: data.projectId ?? undefined
|
||||
},
|
||||
// scott: if it's not an app connection page we need to pass connection details as it's an inline creation
|
||||
search: data.returnUrl.includes("app-connections")
|
||||
? undefined
|
||||
: {
|
||||
connectionId: data.connection.id,
|
||||
connectionName: data.connection.name,
|
||||
...(data.returnUrl.includes("integrations")
|
||||
? {
|
||||
selectedTab: IntegrationsListPageTabs.SecretSyncs
|
||||
}
|
||||
: {})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await navigate({
|
||||
to: data?.returnUrl ?? "/organization/app-connections"
|
||||
});
|
||||
})();
|
||||
}, [isReady]);
|
||||
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
import {
|
||||
AzureDevOpsConnectionMethod,
|
||||
TAzureAppConfigurationConnection,
|
||||
TAzureClientSecretsConnection,
|
||||
TAzureDevOpsConnection,
|
||||
TAzureKeyVaultConnection,
|
||||
TGitHubConnection,
|
||||
TGitHubRadarConnection,
|
||||
TGitLabConnection
|
||||
} from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
|
||||
type BaseFormData = {
|
||||
returnUrl: string;
|
||||
connectionId?: string;
|
||||
isUpdate?: boolean;
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export type GithubFormData = BaseFormData &
|
||||
Pick<TGitHubConnection, "name" | "method" | "description" | "gatewayId" | "credentials">;
|
||||
|
||||
export type GithubRadarFormData = BaseFormData &
|
||||
Pick<TGitHubRadarConnection, "name" | "method" | "description">;
|
||||
|
||||
export type GitLabFormData = BaseFormData &
|
||||
Pick<TGitLabConnection, "name" | "method" | "description" | "credentials">;
|
||||
|
||||
export type AzureKeyVaultFormData = BaseFormData &
|
||||
Pick<TAzureKeyVaultConnection, "name" | "method" | "description"> &
|
||||
Pick<TAzureKeyVaultConnection["credentials"], "tenantId">;
|
||||
|
||||
export type AzureAppConfigurationFormData = BaseFormData &
|
||||
Pick<TAzureAppConfigurationConnection, "name" | "method" | "description"> &
|
||||
Pick<TAzureAppConfigurationConnection["credentials"], "tenantId">;
|
||||
|
||||
export type AzureClientSecretsFormData = BaseFormData &
|
||||
Pick<TAzureClientSecretsConnection, "name" | "method" | "description"> &
|
||||
Pick<TAzureClientSecretsConnection["credentials"], "tenantId">;
|
||||
|
||||
type OAuthCredentials = Extract<
|
||||
TAzureDevOpsConnection,
|
||||
{ method: AzureDevOpsConnectionMethod.OAuth }
|
||||
>["credentials"];
|
||||
type AccessTokenCredentials = Extract<
|
||||
TAzureDevOpsConnection,
|
||||
{ method: AzureDevOpsConnectionMethod.AccessToken }
|
||||
>["credentials"];
|
||||
|
||||
export type AzureDevOpsFormData = BaseFormData &
|
||||
Pick<TAzureDevOpsConnection, "name" | "method" | "description"> &
|
||||
(Pick<OAuthCredentials, "tenantId" | "orgName"> | Pick<AccessTokenCredentials, "orgName">);
|
||||
|
||||
export type FormDataMap = {
|
||||
[AppConnection.GitHub]: GithubFormData & { app: AppConnection.GitHub };
|
||||
[AppConnection.GitHubRadar]: GithubRadarFormData & { app: AppConnection.GitHubRadar };
|
||||
[AppConnection.GitLab]: GitLabFormData & { app: AppConnection.GitLab };
|
||||
[AppConnection.AzureKeyVault]: AzureKeyVaultFormData & { app: AppConnection.AzureKeyVault };
|
||||
[AppConnection.AzureAppConfiguration]: AzureAppConfigurationFormData & {
|
||||
app: AppConnection.AzureAppConfiguration;
|
||||
};
|
||||
[AppConnection.AzureClientSecrets]: AzureClientSecretsFormData & {
|
||||
app: AppConnection.AzureClientSecrets;
|
||||
};
|
||||
[AppConnection.AzureDevOps]: AzureDevOpsFormData & {
|
||||
app: AppConnection.AzureDevOps;
|
||||
};
|
||||
};
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
SelectItem
|
||||
} from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import { useGetUserWorkspaces } from "@app/hooks/api";
|
||||
import { useGetUserProjects } from "@app/hooks/api";
|
||||
import {
|
||||
eventToNameMap,
|
||||
secretEvents,
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
} from "@app/hooks/api/auditLogs/constants";
|
||||
import { EventType } from "@app/hooks/api/auditLogs/enums";
|
||||
import { UserAgentType } from "@app/hooks/api/auth/types";
|
||||
import { Workspace } from "@app/hooks/api/workspace/types";
|
||||
import { Project } from "@app/hooks/api/projects/types";
|
||||
|
||||
import { LogFilterItem } from "./LogFilterItem";
|
||||
import { auditLogFilterFormSchema, Presets, TAuditLogFilterFormData } from "./types";
|
||||
@@ -44,7 +44,7 @@ type Props = {
|
||||
presets?: Presets;
|
||||
setFilter: (data: TAuditLogFilterFormData) => void;
|
||||
filter: TAuditLogFilterFormData;
|
||||
project?: Workspace;
|
||||
project?: Project;
|
||||
};
|
||||
|
||||
const getActiveFilterCount = (filter: TAuditLogFilterFormData) => {
|
||||
@@ -72,7 +72,7 @@ const getActiveFilterCount = (filter: TAuditLogFilterFormData) => {
|
||||
};
|
||||
|
||||
export const LogsFilter = ({ presets, setFilter, filter, project }: Props) => {
|
||||
const { data: workspaces = [] } = useGetUserWorkspaces();
|
||||
const { data: workspaces = [] } = useGetUserProjects();
|
||||
const { currentOrg } = useOrganization();
|
||||
|
||||
const workspacesInOrg = workspaces.filter((ws) => ws.orgId === currentOrg?.id);
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
} from "@app/context";
|
||||
import { Timezone } from "@app/helpers/datetime";
|
||||
import { withPermission, withProjectPermission } from "@app/hoc";
|
||||
import { Workspace } from "@app/hooks/api/workspace/types";
|
||||
import { Project } from "@app/hooks/api/projects/types";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
import { LogsDateFilter } from "./LogsDateFilter";
|
||||
@@ -31,7 +31,7 @@ type Props = {
|
||||
refetchInterval?: number;
|
||||
showFilters?: boolean;
|
||||
pageView?: boolean;
|
||||
project?: Workspace;
|
||||
project?: Project;
|
||||
};
|
||||
|
||||
const LogsSectionComponent = ({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { ActorType, EventType, UserAgentType } from "@app/hooks/api/auditLogs/enums";
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
|
||||
export enum AuditLogDateFilterType {
|
||||
Relative = "relative",
|
||||
|
||||
@@ -4,11 +4,11 @@ import {
|
||||
faArrowUpRightFromSquare,
|
||||
faBookOpen,
|
||||
faCopy,
|
||||
faDoorClosed,
|
||||
faEdit,
|
||||
faEllipsisV,
|
||||
faInfoCircle,
|
||||
faMagnifyingGlass,
|
||||
faPlug,
|
||||
faSearch,
|
||||
faTrash
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
@@ -243,7 +243,7 @@ export const GatewayListPage = withPermission(
|
||||
? "No Gateways match search..."
|
||||
: "No Gateways have been configured"
|
||||
}
|
||||
icon={gateways?.length ? faSearch : faPlug}
|
||||
icon={gateways?.length ? faSearch : faDoorClosed}
|
||||
/>
|
||||
)}
|
||||
<DeleteActionModal
|
||||
|
||||
+3
-3
@@ -17,7 +17,7 @@ import {
|
||||
useAddIdentityToWorkspace,
|
||||
useGetIdentityProjectMemberships,
|
||||
useGetProjectRoles,
|
||||
useGetUserWorkspaces,
|
||||
useGetUserProjects,
|
||||
useGetWorkspaceById
|
||||
} from "@app/hooks/api";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
@@ -44,7 +44,7 @@ type Props = {
|
||||
|
||||
const Content = ({ identityId, handlePopUpToggle }: Omit<Props, "popUp">) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { data: workspaces = [] } = useGetUserWorkspaces();
|
||||
const { data: workspaces = [] } = useGetUserProjects();
|
||||
const { mutateAsync: addIdentityToWorkspace } = useAddIdentityToWorkspace();
|
||||
|
||||
const {
|
||||
@@ -77,7 +77,7 @@ const Content = ({ identityId, handlePopUpToggle }: Omit<Props, "popUp">) => {
|
||||
const onFormSubmit = async ({ project: selectedProject, role }: FormData) => {
|
||||
try {
|
||||
await addIdentityToWorkspace({
|
||||
workspaceId: selectedProject.id,
|
||||
projectId: selectedProject.id,
|
||||
identityId,
|
||||
role: role.slug || undefined
|
||||
});
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ import { createNotification } from "@app/components/notifications";
|
||||
import { IconButton, Td, Tooltip, Tr } from "@app/components/v2";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import { formatProjectRoleName } from "@app/helpers/roles";
|
||||
import { useGetUserWorkspaces } from "@app/hooks/api";
|
||||
import { useGetUserProjects } from "@app/hooks/api";
|
||||
import { IdentityMembership } from "@app/hooks/api/identities/types";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -31,7 +31,7 @@ export const IdentityProjectRow = ({
|
||||
membership: { id, createdAt, identity, project, roles },
|
||||
handlePopUpOpen
|
||||
}: Props) => {
|
||||
const { data: workspaces } = useGetUserWorkspaces();
|
||||
const { data: workspaces } = useGetUserProjects();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const isAccessible = useMemo(() => {
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ export const IdentityProjectsSection = ({ identityId }: Props) => {
|
||||
try {
|
||||
await deleteMutateAsync({
|
||||
identityId: id,
|
||||
workspaceId: projectId
|
||||
projectId
|
||||
});
|
||||
|
||||
createNotification({
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
import {
|
||||
faArrowDownAZ,
|
||||
faBorderAll,
|
||||
@@ -16,6 +15,7 @@ import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { OrgPermissionCan } from "@app/components/permissions";
|
||||
import { RequestProjectAccessModal } from "@app/components/projects/RequestProjectAccessModal";
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
@@ -24,12 +24,9 @@ import {
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuTrigger,
|
||||
FormControl,
|
||||
IconButton,
|
||||
Input,
|
||||
Lottie,
|
||||
Modal,
|
||||
ModalContent,
|
||||
Pagination,
|
||||
Skeleton,
|
||||
Tooltip
|
||||
@@ -43,12 +40,8 @@ import {
|
||||
setUserTablePreference
|
||||
} from "@app/helpers/userTablePreferences";
|
||||
import { useDebounce, usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
|
||||
import {
|
||||
useOrgAdminAccessProject,
|
||||
useRequestProjectAccess,
|
||||
useSearchProjects
|
||||
} from "@app/hooks/api";
|
||||
import { ProjectType, Workspace, WorkspaceEnv } from "@app/hooks/api/workspace/types";
|
||||
import { useOrgAdminAccessProject, useSearchProjects } from "@app/hooks/api";
|
||||
import { Project, ProjectEnv, ProjectType } from "@app/hooks/api/projects/types";
|
||||
import {
|
||||
ProjectListToggle,
|
||||
ProjectListView
|
||||
@@ -62,53 +55,6 @@ type Props = {
|
||||
onProjectListViewChange: (value: ProjectListView) => void;
|
||||
};
|
||||
|
||||
type RequestAccessModalProps = {
|
||||
projectId: string;
|
||||
onPopUpToggle: () => void;
|
||||
};
|
||||
|
||||
const RequestAccessModal = ({ projectId, onPopUpToggle }: RequestAccessModalProps) => {
|
||||
const form = useForm<{ note: string }>();
|
||||
|
||||
const requestProjectAccess = useRequestProjectAccess();
|
||||
|
||||
const onFormSubmit = ({ note }: { note: string }) => {
|
||||
if (requestProjectAccess.isPending) return;
|
||||
requestProjectAccess.mutate(
|
||||
{
|
||||
comment: note,
|
||||
projectId
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
createNotification({
|
||||
type: "success",
|
||||
title: "Project Access Request Sent",
|
||||
text: "Project admins will receive an email of your request"
|
||||
});
|
||||
onPopUpToggle();
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={form.handleSubmit(onFormSubmit)}>
|
||||
<FormControl label="Note">
|
||||
<Input {...form.register("note")} />
|
||||
</FormControl>
|
||||
<div className="mt-4 flex items-center">
|
||||
<Button className="mr-4" size="sm" type="submit" isLoading={form.formState.isSubmitting}>
|
||||
Submit Request
|
||||
</Button>
|
||||
<Button colorSchema="secondary" variant="plain" onClick={() => onPopUpToggle()}>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
export const AllProjectView = ({
|
||||
onAddNewProject,
|
||||
onUpgradePlan,
|
||||
@@ -155,7 +101,7 @@ export const AllProjectView = ({
|
||||
const handleAccessProject = async (
|
||||
type: ProjectType,
|
||||
projectId: string,
|
||||
environments: WorkspaceEnv[]
|
||||
environments: ProjectEnv[]
|
||||
) => {
|
||||
try {
|
||||
await orgAdminAccessProject.mutateAsync({
|
||||
@@ -180,7 +126,7 @@ export const AllProjectView = ({
|
||||
offset,
|
||||
totalCount: searchedProjects?.totalCount || 0
|
||||
});
|
||||
const requestedWorkspaceDetails = (popUp.requestAccessConfirmation.data || {}) as Workspace;
|
||||
const requestedWorkspaceDetails = (popUp.requestAccessConfirmation.data || {}) as Project;
|
||||
|
||||
const handleToggleFilterByProjectType = (el: ProjectType) =>
|
||||
setProjectTypeFilter((state) => (state === el ? undefined : el));
|
||||
@@ -278,22 +224,26 @@ export const AllProjectView = ({
|
||||
</IconButton>
|
||||
</div>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Create} an={OrgPermissionSubjects.Workspace}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
isDisabled={!isAllowed}
|
||||
colorSchema="secondary"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => {
|
||||
if (isAddingProjectsAllowed) {
|
||||
onAddNewProject();
|
||||
} else {
|
||||
onUpgradePlan();
|
||||
}
|
||||
}}
|
||||
className="ml-2"
|
||||
>
|
||||
Add New Project
|
||||
</Button>
|
||||
{(isOldProjectPermissionAllowed) => (
|
||||
<OrgPermissionCan I={OrgPermissionActions.Create} an={OrgPermissionSubjects.Project}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
isDisabled={!isAllowed && !isOldProjectPermissionAllowed}
|
||||
colorSchema="secondary"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => {
|
||||
if (isAddingProjectsAllowed) {
|
||||
onAddNewProject();
|
||||
} else {
|
||||
onUpgradePlan();
|
||||
}
|
||||
}}
|
||||
className="ml-2"
|
||||
>
|
||||
Add New Project
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
</div>
|
||||
@@ -419,20 +369,11 @@ export const AllProjectView = ({
|
||||
<div className="text-center font-light">No Projects Found</div>
|
||||
</div>
|
||||
)}
|
||||
<Modal
|
||||
<RequestProjectAccessModal
|
||||
isOpen={popUp.requestAccessConfirmation.isOpen}
|
||||
onOpenChange={(isOpen) => handlePopUpToggle("requestAccessConfirmation", isOpen)}
|
||||
>
|
||||
<ModalContent
|
||||
title="Confirm Access Request"
|
||||
subTitle={`Requesting access to project ${requestedWorkspaceDetails?.name}. You may include an optional note for project admins to review your request.`}
|
||||
>
|
||||
<RequestAccessModal
|
||||
onPopUpToggle={() => handlePopUpToggle("requestAccessConfirmation")}
|
||||
projectId={requestedWorkspaceDetails?.id}
|
||||
/>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
project={requestedWorkspaceDetails}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -39,11 +39,11 @@ import {
|
||||
setUserTablePreference
|
||||
} from "@app/helpers/userTablePreferences";
|
||||
import { usePagination, useResetPageHelper } from "@app/hooks";
|
||||
import { useGetUserWorkspaces } from "@app/hooks/api";
|
||||
import { useGetUserProjects } from "@app/hooks/api";
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
import { Project, ProjectType } from "@app/hooks/api/projects/types";
|
||||
import { useUpdateUserProjectFavorites } from "@app/hooks/api/users/mutation";
|
||||
import { useGetUserProjectFavorites } from "@app/hooks/api/users/queries";
|
||||
import { ProjectType, Workspace } from "@app/hooks/api/workspace/types";
|
||||
import {
|
||||
ProjectListToggle,
|
||||
ProjectListView
|
||||
@@ -79,7 +79,7 @@ export const MyProjectView = ({
|
||||
{}
|
||||
);
|
||||
|
||||
const { data: workspaces = [], isPending: isWorkspaceLoading } = useGetUserWorkspaces();
|
||||
const { data: workspaces = [], isPending: isWorkspaceLoading } = useGetUserProjects();
|
||||
const {
|
||||
setPage,
|
||||
perPage,
|
||||
@@ -136,7 +136,7 @@ export const MyProjectView = ({
|
||||
|
||||
const { workspacesWithFaveProp } = useMemo(() => {
|
||||
const workspacesWithFav = filteredWorkspaces
|
||||
.map((w): Workspace & { isFavorite: boolean } => ({
|
||||
.map((w): Project & { isFavorite: boolean } => ({
|
||||
...w,
|
||||
isFavorite: Boolean(projectFavorites?.includes(w.id))
|
||||
}))
|
||||
@@ -188,7 +188,7 @@ export const MyProjectView = ({
|
||||
}
|
||||
};
|
||||
|
||||
const renderProjectGridItem = (workspace: Workspace, isFavorite: boolean) => (
|
||||
const renderProjectGridItem = (workspace: Project, isFavorite: boolean) => (
|
||||
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
|
||||
<div
|
||||
onClick={() => {
|
||||
@@ -242,7 +242,7 @@ export const MyProjectView = ({
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
const renderProjectListItem = (workspace: Workspace, isFavorite: boolean, index: number) => (
|
||||
const renderProjectListItem = (workspace: Project, isFavorite: boolean, index: number) => (
|
||||
// eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
|
||||
<div
|
||||
onClick={() => {
|
||||
@@ -480,22 +480,26 @@ export const MyProjectView = ({
|
||||
</IconButton>
|
||||
</div>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Create} an={OrgPermissionSubjects.Workspace}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
isDisabled={!isAllowed}
|
||||
colorSchema="secondary"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => {
|
||||
if (isAddingProjectsAllowed) {
|
||||
onAddNewProject();
|
||||
} else {
|
||||
onUpgradePlan();
|
||||
}
|
||||
}}
|
||||
className="ml-2"
|
||||
>
|
||||
Add New Project
|
||||
</Button>
|
||||
{(isOldProjectV1Allowed) => (
|
||||
<OrgPermissionCan I={OrgPermissionActions.Create} an={OrgPermissionSubjects.Project}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
isDisabled={!isAllowed && !isOldProjectV1Allowed}
|
||||
colorSchema="secondary"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => {
|
||||
if (isAddingProjectsAllowed) {
|
||||
onAddNewProject();
|
||||
} else {
|
||||
onUpgradePlan();
|
||||
}
|
||||
}}
|
||||
className="ml-2"
|
||||
>
|
||||
Add New Project
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
</div>
|
||||
|
||||
+6
-3
@@ -122,12 +122,11 @@ export const formSchema = z.object({
|
||||
.refine((val) => val !== "custom", { message: "Cannot use custom as its a keyword" }),
|
||||
permissions: z
|
||||
.object({
|
||||
workspace: z
|
||||
project: z
|
||||
.object({
|
||||
create: z.boolean().optional()
|
||||
})
|
||||
.optional(),
|
||||
|
||||
"audit-logs": auditLogsPermissionSchema,
|
||||
member: generalPermissionSchema,
|
||||
groups: groupPermissionSchema,
|
||||
@@ -162,7 +161,11 @@ export const rolePermission2Form = (permissions: TPermission[] = []) => {
|
||||
// i would have to write a if loop with both conditions same
|
||||
const formVal: Record<string, any> = {};
|
||||
permissions.forEach((permission) => {
|
||||
const { subject, action } = permission;
|
||||
const { action } = permission;
|
||||
let { subject } = permission;
|
||||
if (subject === OrgPermissionSubjects.Workspace) {
|
||||
subject = OrgPermissionSubjects.Project;
|
||||
}
|
||||
if (!formVal?.[subject]) formVal[subject] = {};
|
||||
formVal[subject][action] = true;
|
||||
});
|
||||
|
||||
+4
-4
@@ -28,7 +28,7 @@ export const OrgRoleWorkspaceRow = ({ isEditable, control, setValue }: Props) =>
|
||||
|
||||
const rule = useWatch({
|
||||
control,
|
||||
name: "permissions.workspace"
|
||||
name: "permissions.project"
|
||||
});
|
||||
|
||||
const selectedPermissionCategory = useMemo(() => {
|
||||
@@ -60,7 +60,7 @@ export const OrgRoleWorkspaceRow = ({ isEditable, control, setValue }: Props) =>
|
||||
setIsCustom.off();
|
||||
|
||||
if (val === Permission.NoAccess) {
|
||||
setValue("permissions.workspace", { create: false }, { shouldDirty: true });
|
||||
setValue("permissions.project", { create: false }, { shouldDirty: true });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -95,8 +95,8 @@ export const OrgRoleWorkspaceRow = ({ isEditable, control, setValue }: Props) =>
|
||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||
return (
|
||||
<Controller
|
||||
name={`permissions.workspace.${action}`}
|
||||
key={`permissions.workspace.${action}`}
|
||||
name={`permissions.project.${action}`}
|
||||
key={`permissions.project.${action}`}
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<Checkbox
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ type Props = {
|
||||
title: string;
|
||||
formName: keyof Omit<
|
||||
Exclude<TFormSchema["permissions"], undefined>,
|
||||
| "workspace"
|
||||
| "project"
|
||||
| "organization-admin-console"
|
||||
| "kmip"
|
||||
| "gateway"
|
||||
|
||||
+36
-44
@@ -1,9 +1,8 @@
|
||||
import { faArrowUpRightFromSquare, faBookOpen, faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
|
||||
import { OrgPermissionCan } from "@app/components/permissions";
|
||||
import { Button } from "@app/components/v2";
|
||||
import { OrgPermissionActions, OrgPermissionSubjects, useOrgPermission } from "@app/context";
|
||||
import { useOrgPermission } from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||
|
||||
@@ -15,52 +14,45 @@ export const ExternalMigrationsTab = () => {
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["selectImportPlatform"] as const);
|
||||
|
||||
return (
|
||||
<OrgPermissionCan
|
||||
I={OrgPermissionActions.Create}
|
||||
a={OrgPermissionSubjects.Workspace}
|
||||
renderGuardBanner
|
||||
passThrough={false}
|
||||
>
|
||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-xl font-semibold text-mineshaft-100">Import from external source</p>
|
||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="flex justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-xl font-semibold text-mineshaft-100">Import from external source</p>
|
||||
|
||||
<div>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://infisical.com/docs/documentation/platform/external-migrations/overview"
|
||||
>
|
||||
<div className="ml-2 inline-block rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
|
||||
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||
Docs
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowUpRightFromSquare}
|
||||
className="mb-[0.07rem] ml-1.5 text-xxs"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://infisical.com/docs/documentation/platform/external-migrations/overview"
|
||||
>
|
||||
<div className="ml-2 inline-block rounded-md bg-yellow/20 px-1.5 pb-[0.03rem] pt-[0.04rem] text-sm text-yellow opacity-80 hover:opacity-100">
|
||||
<FontAwesomeIcon icon={faBookOpen} className="mr-1.5" />
|
||||
Docs
|
||||
<FontAwesomeIcon
|
||||
icon={faArrowUpRightFromSquare}
|
||||
className="mb-[0.07rem] ml-1.5 text-xxs"
|
||||
/>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={() => {
|
||||
handlePopUpOpen("selectImportPlatform");
|
||||
}}
|
||||
isDisabled={membership?.role !== ProjectMembershipRole.Admin}
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
>
|
||||
Import
|
||||
</Button>
|
||||
</div>
|
||||
<p className="mb-4 text-gray-400">Import data from another platform to Infisical.</p>
|
||||
|
||||
<SelectImportFromPlatformModal
|
||||
isOpen={popUp.selectImportPlatform.isOpen}
|
||||
onToggle={(state) => handlePopUpToggle("selectImportPlatform", state)}
|
||||
/>
|
||||
<Button
|
||||
onClick={() => {
|
||||
handlePopUpOpen("selectImportPlatform");
|
||||
}}
|
||||
isDisabled={membership?.role !== ProjectMembershipRole.Admin}
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
>
|
||||
Import
|
||||
</Button>
|
||||
</div>
|
||||
</OrgPermissionCan>
|
||||
<p className="mb-4 text-gray-400">Import data from another platform to Infisical.</p>
|
||||
|
||||
<SelectImportFromPlatformModal
|
||||
isOpen={popUp.selectImportPlatform.isOpen}
|
||||
onToggle={(state) => handlePopUpToggle("selectImportPlatform", state)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+1
-1
@@ -7,8 +7,8 @@ import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
|
||||
import { getProjectTitle } from "@app/helpers/project";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
import { TProjectTemplate, useDeleteProjectTemplate } from "@app/hooks/api/projectTemplates";
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
import { ProjectTemplateDetailsModal } from "../../ProjectTemplateDetailsModal";
|
||||
import { ProjectTemplateEnvironmentsForm } from "./ProjectTemplateEnvironmentsForm";
|
||||
|
||||
+1
-1
@@ -15,12 +15,12 @@ import {
|
||||
TextArea
|
||||
} from "@app/components/v2";
|
||||
import { getProjectLottieIcon } from "@app/helpers/project";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
import {
|
||||
TProjectTemplate,
|
||||
useCreateProjectTemplate,
|
||||
useUpdateProjectTemplate
|
||||
} from "@app/hooks/api/projectTemplates";
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
import { slugSchema } from "@app/lib/schemas";
|
||||
|
||||
const formSchema = z.object({
|
||||
|
||||
+3
-3
@@ -9,9 +9,9 @@ import { useOrganization } from "@app/context";
|
||||
import {
|
||||
useAddUserToWsNonE2EE,
|
||||
useGetOrgMembershipProjectMemberships,
|
||||
useGetUserWorkspaces
|
||||
useGetUserProjects
|
||||
} from "@app/hooks/api";
|
||||
import { ProjectVersion } from "@app/hooks/api/workspace/types";
|
||||
import { ProjectVersion } from "@app/hooks/api/projects/types";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
const schema = z
|
||||
@@ -34,7 +34,7 @@ type Props = {
|
||||
const UserAddToProjectModalChild = ({ membershipId, popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const orgId = currentOrg?.id || "";
|
||||
const { data: workspaces = [] } = useGetUserWorkspaces();
|
||||
const { data: workspaces = [] } = useGetUserProjects();
|
||||
|
||||
const { mutateAsync: addUserToWorkspaceNonE2EE } = useAddUserToWsNonE2EE();
|
||||
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ import { createNotification } from "@app/components/notifications";
|
||||
import { IconButton, Td, Tooltip, Tr } from "@app/components/v2";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import { formatProjectRoleName } from "@app/helpers/roles";
|
||||
import { useGetUserWorkspaces } from "@app/hooks/api";
|
||||
import { useGetUserProjects } from "@app/hooks/api";
|
||||
import { TWorkspaceUser } from "@app/hooks/api/types";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
import { OrgAccessControlTabSections } from "@app/types/org";
|
||||
@@ -24,7 +24,7 @@ export const UserProjectRow = ({
|
||||
membership: { id, project, user, roles },
|
||||
handlePopUpOpen
|
||||
}: Props) => {
|
||||
const { data: workspaces = [] } = useGetUserWorkspaces();
|
||||
const { data: workspaces = [] } = useGetUserProjects();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const isAccessible = useMemo(() => {
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ export const UserProjectsSection = ({ membershipId }: Props) => {
|
||||
|
||||
const handleRemoveUser = async (projectId: string, username: string) => {
|
||||
try {
|
||||
await removeUserFromWorkspace({ workspaceId: projectId, usernames: [username], orgId });
|
||||
await removeUserFromWorkspace({ projectId, usernames: [username], orgId });
|
||||
createNotification({
|
||||
text: "Successfully removed user from project",
|
||||
type: "success"
|
||||
|
||||
@@ -3,9 +3,9 @@ import { useTranslation } from "react-i18next";
|
||||
import { useNavigate, useSearch } from "@tanstack/react-router";
|
||||
|
||||
import { PageHeader, Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
import { ProjectAccessControlTabs } from "@app/types/project";
|
||||
|
||||
import {
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
|
||||
const Page = () => {
|
||||
const navigate = useNavigate();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const selectedTab = useSearch({
|
||||
strict: false,
|
||||
select: (el) => el.selectedTab
|
||||
@@ -26,15 +26,15 @@ const Page = () => {
|
||||
|
||||
const updateSelectedTab = (tab: string) => {
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/access-management` as const,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/access-management` as const,
|
||||
search: (prev) => ({ ...prev, selectedTab: tab }),
|
||||
params: {
|
||||
projectId: currentWorkspace.id
|
||||
projectId: currentProject.id
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const isSecretManager = currentWorkspace.type === ProjectType.SecretManager;
|
||||
const isSecretManager = currentProject.type === ProjectType.SecretManager;
|
||||
|
||||
return (
|
||||
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
||||
|
||||
+5
-5
@@ -6,7 +6,7 @@ import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
import { Button, FilterableSelect, FormControl, Modal, ModalContent } from "@app/components/v2";
|
||||
import { useOrganization, useWorkspace } from "@app/context";
|
||||
import { useOrganization, useProject } from "@app/context";
|
||||
import {
|
||||
useAddGroupToWorkspace,
|
||||
useGetOrganizationGroups,
|
||||
@@ -31,14 +31,14 @@ type Props = {
|
||||
|
||||
const Content = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const orgId = currentOrg?.id || "";
|
||||
|
||||
const { data: groups } = useGetOrganizationGroups(orgId);
|
||||
const { data: groupMemberships } = useListWorkspaceGroups(currentWorkspace?.id || "");
|
||||
const { data: groupMemberships } = useListWorkspaceGroups(currentProject?.id || "");
|
||||
|
||||
const { data: roles } = useGetProjectRoles(currentWorkspace?.id || "");
|
||||
const { data: roles } = useGetProjectRoles(currentProject?.id || "");
|
||||
|
||||
const { mutateAsync: addGroupToWorkspaceMutateAsync } = useAddGroupToWorkspace();
|
||||
|
||||
@@ -64,7 +64,7 @@ const Content = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const onFormSubmit = async ({ group, role }: FormData) => {
|
||||
try {
|
||||
await addGroupToWorkspaceMutateAsync({
|
||||
projectId: currentWorkspace?.id || "",
|
||||
projectId: currentProject?.id || "",
|
||||
groupId: group.id,
|
||||
role: role.slug || undefined
|
||||
});
|
||||
|
||||
+6
-6
@@ -24,13 +24,13 @@ import {
|
||||
Tag,
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { formatProjectRoleName } from "@app/helpers/roles";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useGetProjectRoles, useUpdateGroupWorkspaceRole } from "@app/hooks/api";
|
||||
import { TGroupMembership } from "@app/hooks/api/groups/types";
|
||||
import { ProjectUserMembershipTemporaryMode } from "@app/hooks/api/projects/types";
|
||||
import { TProjectRole } from "@app/hooks/api/roles/types";
|
||||
import { ProjectUserMembershipTemporaryMode } from "@app/hooks/api/workspace/types";
|
||||
import { groupBy } from "@app/lib/fn/array";
|
||||
|
||||
const temporaryRoleFormSchema = z.object({
|
||||
@@ -213,7 +213,7 @@ type FormProps = {
|
||||
};
|
||||
|
||||
const GroupRolesForm = ({ projectRoles, roles, groupId, onClose }: FormProps) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const [searchRoles, setSearchRoles] = useState("");
|
||||
|
||||
@@ -255,7 +255,7 @@ const GroupRolesForm = ({ projectRoles, roles, groupId, onClose }: FormProps) =>
|
||||
|
||||
try {
|
||||
await updateGroupWorkspaceRole.mutateAsync({
|
||||
projectId: currentWorkspace?.id || "",
|
||||
projectId: currentProject?.id || "",
|
||||
groupId,
|
||||
roles: selectedRoles
|
||||
});
|
||||
@@ -373,11 +373,11 @@ export const GroupRoles = ({
|
||||
className,
|
||||
popperContentProps
|
||||
}: TMemberRolesProp) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { popUp, handlePopUpToggle } = usePopUp(["editRole"] as const);
|
||||
|
||||
const { data: projectRoles, isPending: isRolesLoading } = useGetProjectRoles(
|
||||
currentWorkspace?.id ?? ""
|
||||
currentProject?.id ?? ""
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
+4
-4
@@ -8,8 +8,8 @@ import { Button, DeleteActionModal } from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
useSubscription,
|
||||
useWorkspace
|
||||
useProject,
|
||||
useSubscription
|
||||
} from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useDeleteGroupFromWorkspace } from "@app/hooks/api";
|
||||
@@ -19,7 +19,7 @@ import { GroupTable } from "./GroupsTable";
|
||||
|
||||
export const GroupsSection = () => {
|
||||
const { subscription } = useSubscription();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { mutateAsync: deleteMutateAsync } = useDeleteGroupFromWorkspace();
|
||||
|
||||
@@ -44,7 +44,7 @@ export const GroupsSection = () => {
|
||||
try {
|
||||
await deleteMutateAsync({
|
||||
groupId,
|
||||
projectId: currentWorkspace?.id || ""
|
||||
projectId: currentProject?.id || ""
|
||||
});
|
||||
|
||||
createNotification({
|
||||
|
||||
+7
-7
@@ -32,7 +32,7 @@ import {
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import {
|
||||
getUserTablePreference,
|
||||
@@ -61,7 +61,7 @@ enum GroupsOrderBy {
|
||||
}
|
||||
|
||||
export const GroupTable = ({ handlePopUpOpen }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const {
|
||||
@@ -85,7 +85,7 @@ export const GroupTable = ({ handlePopUpOpen }: Props) => {
|
||||
};
|
||||
|
||||
const { data: groupMemberships = [], isPending } = useListWorkspaceGroups(
|
||||
currentWorkspace?.id || ""
|
||||
currentProject?.id || ""
|
||||
);
|
||||
|
||||
const filteredGroupMemberships = useMemo(() => {
|
||||
@@ -159,9 +159,9 @@ export const GroupTable = ({ handlePopUpOpen }: Props) => {
|
||||
onKeyDown={(evt) => {
|
||||
if (evt.key === "Enter") {
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/groups/$groupId` as const,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/groups/$groupId` as const,
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
groupId: id
|
||||
}
|
||||
});
|
||||
@@ -169,9 +169,9 @@ export const GroupTable = ({ handlePopUpOpen }: Props) => {
|
||||
}}
|
||||
onClick={() =>
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/groups/$groupId` as const,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/groups/$groupId` as const,
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
groupId: id
|
||||
}
|
||||
})
|
||||
|
||||
+9
-11
@@ -45,7 +45,7 @@ import {
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import { formatProjectRoleName } from "@app/helpers/roles";
|
||||
import {
|
||||
@@ -57,7 +57,7 @@ import { withProjectPermission } from "@app/hoc";
|
||||
import { usePagination, useResetPageHelper } from "@app/hooks";
|
||||
import { useDeleteIdentityFromWorkspace, useGetWorkspaceIdentityMemberships } from "@app/hooks/api";
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
import { ProjectIdentityOrderBy } from "@app/hooks/api/workspace/types";
|
||||
import { ProjectIdentityOrderBy } from "@app/hooks/api/projects/types";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
import { IdentityModal } from "./components/IdentityModal";
|
||||
@@ -66,7 +66,7 @@ const MAX_ROLES_TO_BE_SHOWN_IN_TABLE = 2;
|
||||
|
||||
export const IdentityTab = withProjectPermission(
|
||||
() => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject, projectId } = useProject();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const {
|
||||
@@ -92,11 +92,9 @@ export const IdentityTab = withProjectPermission(
|
||||
setUserTablePreference("projectIdentityTable", PreferenceKey.PerPage, newPerPage);
|
||||
};
|
||||
|
||||
const workspaceId = currentWorkspace?.id ?? "";
|
||||
|
||||
const { data, isPending, isFetching } = useGetWorkspaceIdentityMemberships(
|
||||
{
|
||||
workspaceId: currentWorkspace?.id || "",
|
||||
projectId,
|
||||
offset,
|
||||
limit,
|
||||
orderDirection,
|
||||
@@ -126,7 +124,7 @@ export const IdentityTab = withProjectPermission(
|
||||
try {
|
||||
await deleteMutateAsync({
|
||||
identityId,
|
||||
workspaceId
|
||||
projectId
|
||||
});
|
||||
|
||||
createNotification({
|
||||
@@ -261,9 +259,9 @@ export const IdentityTab = withProjectPermission(
|
||||
onKeyDown={(evt) => {
|
||||
if (evt.key === "Enter") {
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/identities/$identityId` as const,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/identities/$identityId` as const,
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
identityId: id
|
||||
}
|
||||
});
|
||||
@@ -271,9 +269,9 @@ export const IdentityTab = withProjectPermission(
|
||||
}}
|
||||
onClick={() =>
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/identities/$identityId` as const,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/identities/$identityId` as const,
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
identityId: id
|
||||
}
|
||||
})
|
||||
|
||||
+5
-6
@@ -14,7 +14,7 @@ import {
|
||||
ModalContent,
|
||||
Spinner
|
||||
} from "@app/components/v2";
|
||||
import { useOrganization, useWorkspace } from "@app/context";
|
||||
import { useOrganization, useProject } from "@app/context";
|
||||
import {
|
||||
useAddIdentityToWorkspace,
|
||||
useGetIdentityMembershipOrgs,
|
||||
@@ -37,10 +37,9 @@ type Props = {
|
||||
|
||||
const Content = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { projectId } = useProject();
|
||||
|
||||
const organizationId = currentOrg?.id || "";
|
||||
const workspaceId = currentWorkspace?.id || "";
|
||||
|
||||
const { data: identityMembershipOrgsData, isPending: isMembershipsLoading } =
|
||||
useGetIdentityMembershipOrgs({
|
||||
@@ -49,12 +48,12 @@ const Content = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
});
|
||||
const identityMembershipOrgs = identityMembershipOrgsData?.identityMemberships;
|
||||
const { data: identityMembershipsData } = useGetWorkspaceIdentityMemberships({
|
||||
workspaceId,
|
||||
projectId,
|
||||
limit: 20000 // TODO: this is temp to preserve functionality for larger projects, will optimize in PR referenced above
|
||||
});
|
||||
const identityMemberships = identityMembershipsData?.identityMemberships;
|
||||
|
||||
const { data: roles, isPending: isRolesLoading } = useGetProjectRoles(workspaceId);
|
||||
const { data: roles, isPending: isRolesLoading } = useGetProjectRoles(projectId);
|
||||
|
||||
const { mutateAsync: addIdentityToWorkspaceMutateAsync } = useAddIdentityToWorkspace();
|
||||
|
||||
@@ -80,7 +79,7 @@ const Content = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const onFormSubmit = async ({ identity, role }: FormData) => {
|
||||
try {
|
||||
await addIdentityToWorkspaceMutateAsync({
|
||||
workspaceId,
|
||||
projectId,
|
||||
identityId: identity.id,
|
||||
role: role.slug || undefined
|
||||
});
|
||||
|
||||
+10
-10
@@ -22,7 +22,7 @@ import {
|
||||
OrgPermissionSubjects,
|
||||
useOrganization,
|
||||
useOrgPermission,
|
||||
useWorkspace
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import {
|
||||
useAddUsersToOrg,
|
||||
@@ -30,8 +30,8 @@ import {
|
||||
useGetProjectRoles,
|
||||
useGetWorkspaceUsers
|
||||
} from "@app/hooks/api";
|
||||
import { ProjectVersion } from "@app/hooks/api/projects/types";
|
||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||
import { ProjectVersion } from "@app/hooks/api/workspace/types";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
const addMemberFormSchema = z.object({
|
||||
@@ -57,7 +57,7 @@ type Props = {
|
||||
export const AddMemberModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const navigate = useNavigate({ from: "" });
|
||||
const { permission } = useOrgPermission();
|
||||
const requesterEmail = useSearch({
|
||||
@@ -66,12 +66,12 @@ export const AddMemberModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
});
|
||||
|
||||
const orgId = currentOrg?.id || "";
|
||||
const workspaceId = currentWorkspace?.id || "";
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
const { data: members } = useGetWorkspaceUsers(workspaceId);
|
||||
const { data: members } = useGetWorkspaceUsers(projectId);
|
||||
const { data: orgUsers } = useGetOrgUsers(orgId);
|
||||
|
||||
const { data: roles } = useGetProjectRoles(currentWorkspace?.id || "");
|
||||
const { data: roles } = useGetProjectRoles(currentProject?.id || "");
|
||||
|
||||
const {
|
||||
control,
|
||||
@@ -94,7 +94,7 @@ export const AddMemberModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
}, [requesterEmail]);
|
||||
|
||||
const onAddMembers = async ({ orgMemberships, projectRoleSlugs }: TAddMemberForm) => {
|
||||
if (!currentWorkspace) return;
|
||||
if (!currentProject) return;
|
||||
if (!currentOrg?.id) return;
|
||||
|
||||
const existingMembers = orgMemberships.filter((membership) => !membership.isNewInvitee);
|
||||
@@ -109,7 +109,7 @@ export const AddMemberModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
if (!selectedMembers) return;
|
||||
|
||||
try {
|
||||
if (currentWorkspace.version === ProjectVersion.V1) {
|
||||
if (currentProject.version === ProjectVersion.V1) {
|
||||
createNotification({
|
||||
type: "error",
|
||||
text: "Please upgrade your project to invite new members to the project."
|
||||
@@ -146,8 +146,8 @@ export const AddMemberModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
organizationRoleSlug: ProjectMembershipRole.Member, // only applies to new invites
|
||||
projects: [
|
||||
{
|
||||
slug: currentWorkspace.slug,
|
||||
id: currentWorkspace.id,
|
||||
slug: currentProject.slug,
|
||||
id: currentProject.id,
|
||||
projectRoleSlug: projectRoleSlugs.map((role) => role.slug)
|
||||
}
|
||||
]
|
||||
|
||||
+6
-7
@@ -29,14 +29,14 @@ import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionMemberActions,
|
||||
ProjectPermissionSub,
|
||||
useProject,
|
||||
useProjectPermission,
|
||||
useSubscription,
|
||||
useWorkspace
|
||||
useSubscription
|
||||
} from "@app/context";
|
||||
import { useGetProjectRoles, useUpdateUserWorkspaceRole } from "@app/hooks/api";
|
||||
import { ProjectUserMembershipTemporaryMode } from "@app/hooks/api/projects/types";
|
||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||
import { TWorkspaceUser } from "@app/hooks/api/types";
|
||||
import { ProjectUserMembershipTemporaryMode } from "@app/hooks/api/workspace/types";
|
||||
|
||||
const roleFormSchema = z.object({
|
||||
roles: z
|
||||
@@ -64,9 +64,8 @@ type Props = {
|
||||
};
|
||||
export const MemberRbacSection = ({ projectMember, onOpenUpgradeModal }: Props) => {
|
||||
const { subscription } = useSubscription();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const workspaceId = currentWorkspace?.id || "";
|
||||
const { data: projectRoles, isPending: isRolesLoading } = useGetProjectRoles(workspaceId);
|
||||
const { projectId } = useProject();
|
||||
const { data: projectRoles, isPending: isRolesLoading } = useGetProjectRoles(projectId);
|
||||
const { permission } = useProjectPermission();
|
||||
const isMemberEditDisabled = permission.cannot(
|
||||
ProjectPermissionMemberActions.Edit,
|
||||
@@ -130,7 +129,7 @@ export const MemberRbacSection = ({ projectMember, onOpenUpgradeModal }: Props)
|
||||
|
||||
try {
|
||||
await updateMembershipRole.mutateAsync({
|
||||
workspaceId,
|
||||
projectId,
|
||||
membershipId: projectMember.id,
|
||||
roles: sanitizedRoles
|
||||
});
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
|
||||
import { Alert, AlertDescription } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import { TWorkspaceUser } from "@app/hooks/api/types";
|
||||
|
||||
@@ -12,7 +12,7 @@ type Props = {
|
||||
onOpenUpgradeModal: (title: string) => void;
|
||||
};
|
||||
export const MemberRoleForm = ({ projectMember, onOpenUpgradeModal }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
return (
|
||||
<div>
|
||||
<MemberRbacSection projectMember={projectMember} onOpenUpgradeModal={onOpenUpgradeModal} />
|
||||
@@ -22,9 +22,9 @@ export const MemberRoleForm = ({ projectMember, onOpenUpgradeModal }: Props) =>
|
||||
>
|
||||
<AlertDescription>
|
||||
<Link
|
||||
to={`${getProjectBaseURL(currentWorkspace.type)}/members/$membershipId` as const}
|
||||
to={`${getProjectBaseURL(currentProject.type)}/members/$membershipId` as const}
|
||||
params={{
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
membershipId: projectMember.id
|
||||
}}
|
||||
>
|
||||
|
||||
+7
-7
@@ -43,8 +43,8 @@ import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionMemberActions,
|
||||
ProjectPermissionSub,
|
||||
useProjectPermission,
|
||||
useWorkspace
|
||||
useProject,
|
||||
useProjectPermission
|
||||
} from "@app/context";
|
||||
import { removeTrailingSlash } from "@app/helpers/string";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
@@ -89,7 +89,7 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
secretPath?: string;
|
||||
onClose?: () => void;
|
||||
}) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { popUp, handlePopUpOpen, handlePopUpToggle, handlePopUpClose } = usePopUp([
|
||||
"deletePrivilege",
|
||||
@@ -129,7 +129,7 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
temporaryAccess: privilege
|
||||
}
|
||||
: {
|
||||
environmentSlug: currentWorkspace.environments?.[0]?.slug,
|
||||
environmentSlug: currentProject.environments?.[0]?.slug,
|
||||
secretPath: initialSecretPath,
|
||||
read: selectedActions.includes(ProjectPermissionActions.Read),
|
||||
edit: selectedActions.includes(ProjectPermissionActions.Edit),
|
||||
@@ -202,7 +202,7 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
// This is used for requesting access additional privileges, not directly creating a privilege!
|
||||
const handleRequestAccess = async (data: TSecretPermissionForm) => {
|
||||
if (!policies) return;
|
||||
if (!currentWorkspace) {
|
||||
if (!currentProject) {
|
||||
createNotification({
|
||||
type: "error",
|
||||
text: "No workspace found.",
|
||||
@@ -253,7 +253,7 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
...(data.temporaryAccess.isTemporary && {
|
||||
temporaryRange: data.temporaryAccess.temporaryRange
|
||||
}),
|
||||
projectSlug: currentWorkspace.slug,
|
||||
projectSlug: currentProject.slug,
|
||||
isTemporary: data.temporaryAccess.isTemporary,
|
||||
permissions: actions
|
||||
.filter(({ allowed }) => allowed)
|
||||
@@ -307,7 +307,7 @@ export const SpecificPrivilegeSecretForm = ({
|
||||
position="popper"
|
||||
dropdownContainerClassName="max-w-none"
|
||||
>
|
||||
{currentWorkspace?.environments?.map(({ slug, id, name }) => (
|
||||
{currentProject?.environments?.map(({ slug, id, name }) => (
|
||||
<SelectItem value={slug} key={id}>
|
||||
{name}
|
||||
</SelectItem>
|
||||
|
||||
+4
-4
@@ -9,7 +9,7 @@ import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
useOrganization,
|
||||
useWorkspace
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useDeleteUserFromWorkspace } from "@app/hooks/api";
|
||||
@@ -19,7 +19,7 @@ import { MembersTable } from "./MembersTable";
|
||||
|
||||
export const MembersSection = () => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { mutateAsync: removeUserFromWorkspace } = useDeleteUserFromWorkspace();
|
||||
|
||||
@@ -32,11 +32,11 @@ export const MembersSection = () => {
|
||||
const handleRemoveUser = async () => {
|
||||
const username = (popUp?.removeMember?.data as { username: string })?.username;
|
||||
if (!currentOrg?.id) return;
|
||||
if (!currentWorkspace?.id) return;
|
||||
if (!currentProject?.id) return;
|
||||
|
||||
try {
|
||||
await removeUserFromWorkspace({
|
||||
workspaceId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
usernames: [username],
|
||||
orgId: currentOrg.id
|
||||
});
|
||||
|
||||
+9
-14
@@ -44,12 +44,7 @@ import {
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
useUser,
|
||||
useWorkspace
|
||||
} from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject, useUser } from "@app/context";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import { formatProjectRoleName } from "@app/helpers/roles";
|
||||
import {
|
||||
@@ -81,7 +76,7 @@ type Filter = {
|
||||
};
|
||||
|
||||
export const MembersTable = ({ handlePopUpOpen }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { user } = useUser();
|
||||
const navigate = useNavigate();
|
||||
const [filter, setFilter] = useState<Filter>({
|
||||
@@ -90,8 +85,8 @@ export const MembersTable = ({ handlePopUpOpen }: Props) => {
|
||||
const filterRoles = useMemo(() => filter.roles, [filter.roles]);
|
||||
|
||||
const userId = user?.id || "";
|
||||
const workspaceId = currentWorkspace?.id || "";
|
||||
const { data: projectRoles } = useGetProjectRoles(workspaceId);
|
||||
const projectId = currentProject?.id || "";
|
||||
const { data: projectRoles } = useGetProjectRoles(projectId);
|
||||
|
||||
const {
|
||||
search,
|
||||
@@ -116,7 +111,7 @@ export const MembersTable = ({ handlePopUpOpen }: Props) => {
|
||||
};
|
||||
|
||||
const { data: members = [], isPending: isMembersLoading } = useGetWorkspaceUsers(
|
||||
workspaceId,
|
||||
projectId,
|
||||
undefined,
|
||||
filterRoles
|
||||
);
|
||||
@@ -312,9 +307,9 @@ export const MembersTable = ({ handlePopUpOpen }: Props) => {
|
||||
onKeyDown={(evt) => {
|
||||
if (evt.key === "Enter") {
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/members/$membershipId`,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/members/$membershipId`,
|
||||
params: {
|
||||
projectId: workspaceId,
|
||||
projectId,
|
||||
membershipId
|
||||
}
|
||||
});
|
||||
@@ -322,9 +317,9 @@ export const MembersTable = ({ handlePopUpOpen }: Props) => {
|
||||
}}
|
||||
onClick={() =>
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/members/$membershipId`,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/members/$membershipId`,
|
||||
params: {
|
||||
projectId: workspaceId,
|
||||
projectId,
|
||||
membershipId
|
||||
}
|
||||
})
|
||||
|
||||
+7
-7
@@ -39,7 +39,7 @@ import {
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import { isCustomProjectRole } from "@app/helpers/roles";
|
||||
import {
|
||||
@@ -67,8 +67,8 @@ export const ProjectRoleList = () => {
|
||||
"deleteRole",
|
||||
"duplicateRole"
|
||||
] as const);
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
const { data: roles, isPending: isRolesLoading } = useGetProjectRoles(projectId);
|
||||
|
||||
@@ -250,9 +250,9 @@ export const ProjectRoleList = () => {
|
||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||
onClick={() =>
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/roles/$roleSlug`,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/roles/$roleSlug`,
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
roleSlug: slug
|
||||
}
|
||||
})
|
||||
@@ -292,9 +292,9 @@ export const ProjectRoleList = () => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/roles/$roleSlug`,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/roles/$roleSlug`,
|
||||
params: {
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
roleSlug: slug
|
||||
}
|
||||
});
|
||||
|
||||
+10
-10
@@ -22,7 +22,7 @@ import {
|
||||
Select,
|
||||
SelectItem
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { useToggle } from "@app/hooks";
|
||||
import { useCreateServiceToken } from "@app/hooks/api";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
@@ -70,7 +70,7 @@ type Props = {
|
||||
const ServiceTokenForm = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
@@ -81,7 +81,7 @@ const ServiceTokenForm = () => {
|
||||
scopes: [
|
||||
{
|
||||
secretPath: "/",
|
||||
environment: currentWorkspace?.environments?.[0]?.slug
|
||||
environment: currentProject?.environments?.[0]?.slug
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -111,7 +111,7 @@ const ServiceTokenForm = () => {
|
||||
|
||||
const onFormSubmit = async ({ name, scopes, expiresIn, permissions }: FormData) => {
|
||||
try {
|
||||
if (!currentWorkspace?.id) return;
|
||||
if (!currentProject?.id) return;
|
||||
|
||||
const randomBytes = crypto.randomBytes(16).toString("hex");
|
||||
|
||||
@@ -122,7 +122,7 @@ const ServiceTokenForm = () => {
|
||||
scopes,
|
||||
expiresIn: Number(expiresIn),
|
||||
name,
|
||||
workspaceId: currentWorkspace.id,
|
||||
workspaceId: currentProject.id,
|
||||
randomBytes,
|
||||
permissions: Object.entries(permissions)
|
||||
.filter(([, permissionsValue]) => permissionsValue)
|
||||
@@ -172,7 +172,7 @@ const ServiceTokenForm = () => {
|
||||
<Controller
|
||||
control={control}
|
||||
name={`scopes.${index}.environment`}
|
||||
defaultValue={currentWorkspace?.environments?.[0]?.slug}
|
||||
defaultValue={currentProject?.environments?.[0]?.slug}
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
className="mb-0"
|
||||
@@ -186,7 +186,7 @@ const ServiceTokenForm = () => {
|
||||
onValueChange={(e) => onChange(e)}
|
||||
className="w-full"
|
||||
>
|
||||
{currentWorkspace?.environments.map(({ name, slug }) => (
|
||||
{currentProject?.environments.map(({ name, slug }) => (
|
||||
<SelectItem value={slug} key={slug}>
|
||||
{name}
|
||||
</SelectItem>
|
||||
@@ -225,7 +225,7 @@ const ServiceTokenForm = () => {
|
||||
variant="outline_bg"
|
||||
onClick={() =>
|
||||
append({
|
||||
environment: currentWorkspace?.environments?.[0]?.slug || "",
|
||||
environment: currentProject?.environments?.[0]?.slug || "",
|
||||
secretPath: ""
|
||||
})
|
||||
}
|
||||
@@ -334,7 +334,7 @@ const ServiceTokenForm = () => {
|
||||
export const AddServiceTokenModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@@ -346,7 +346,7 @@ export const AddServiceTokenModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
<ModalContent
|
||||
title={
|
||||
t("section.token.add-dialog.title", {
|
||||
target: currentWorkspace?.name
|
||||
target: currentProject?.name
|
||||
}) as string
|
||||
}
|
||||
subTitle={t("section.token.add-dialog.description") as string}
|
||||
|
||||
+3
-3
@@ -33,7 +33,7 @@ import {
|
||||
Tooltip,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import {
|
||||
getUserTablePreference,
|
||||
PreferenceKey,
|
||||
@@ -63,9 +63,9 @@ enum TokensOrderBy {
|
||||
}
|
||||
|
||||
export const ServiceTokenTable = ({ handlePopUpOpen }: Props) => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const { data, isPending } = useGetUserWsServiceTokens({
|
||||
workspaceID: currentWorkspace?.id || ""
|
||||
workspaceID: currentProject?.id || ""
|
||||
});
|
||||
|
||||
const {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Helmet } from "react-helmet";
|
||||
|
||||
import { PageHeader } from "@app/components/v2";
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
ProjectPermissionAppConnectionActions,
|
||||
ProjectPermissionSub
|
||||
} from "@app/context/ProjectPermissionContext/types";
|
||||
import { withProjectPermission } from "@app/hoc";
|
||||
import { AppConnectionsTable } from "@app/pages/organization/AppConnections/AppConnectionsPage/components";
|
||||
|
||||
export const AppConnectionsPage = withProjectPermission(
|
||||
() => {
|
||||
const { currentProject } = useProject();
|
||||
|
||||
return (
|
||||
<div className="bg-bunker-800">
|
||||
<Helmet>
|
||||
<title>Infisical | App Connections</title>
|
||||
<link rel="icon" href="/infisical.ico" />
|
||||
<meta property="og:image" content="/images/message.png" />
|
||||
</Helmet>
|
||||
<div className="flex w-full justify-center bg-bunker-800 text-white">
|
||||
<div className="w-full max-w-7xl">
|
||||
<PageHeader
|
||||
className="w-full"
|
||||
title="App Connections"
|
||||
description="Manage project App Connections"
|
||||
/>
|
||||
|
||||
<AppConnectionsTable projectId={currentProject.id} projectType={currentProject.type} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
{
|
||||
action: ProjectPermissionAppConnectionActions.Read,
|
||||
subject: ProjectPermissionSub.AppConnections
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,19 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
import { AppConnectionsPage } from "./AppConnectionsPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/app-connections"
|
||||
)({
|
||||
component: AppConnectionsPage,
|
||||
beforeLoad: ({ context }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
...context.breadcrumbs,
|
||||
{
|
||||
label: "App Connections"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
import { AppConnectionsPage } from "./AppConnectionsPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/app-connections"
|
||||
)({
|
||||
component: AppConnectionsPage,
|
||||
beforeLoad: ({ context }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
...context.breadcrumbs,
|
||||
{
|
||||
label: "App Connections"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
import { AppConnectionsPage } from "./AppConnectionsPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-scanning/$projectId/_secret-scanning-layout/app-connections"
|
||||
)({
|
||||
component: AppConnectionsPage,
|
||||
beforeLoad: ({ context }) => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
...context.breadcrumbs,
|
||||
{
|
||||
label: "App Connections"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Helmet } from "react-helmet";
|
||||
|
||||
import { PageHeader } from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { LogsSection } from "@app/pages/organization/AuditLogsPage/components";
|
||||
|
||||
export const AuditLogsPage = () => {
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
return (
|
||||
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
||||
@@ -19,7 +19,7 @@ export const AuditLogsPage = () => {
|
||||
title="Audit logs"
|
||||
description="Audit logs for security and compliance teams to monitor information access."
|
||||
/>
|
||||
<LogsSection pageView project={currentWorkspace} />
|
||||
<LogsSection pageView project={currentProject} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,8 +4,8 @@ import { useParams } from "@tanstack/react-router";
|
||||
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { EmptyState, PageHeader, Spinner } from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { useGetWorkspaceGroupMembershipDetails } from "@app/hooks/api/workspace/queries";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { useGetWorkspaceGroupMembershipDetails } from "@app/hooks/api/projects/queries";
|
||||
|
||||
import { GroupDetailsSection } from "./components/GroupDetailsSection";
|
||||
import { GroupMembersSection } from "./components/GroupMembersSection";
|
||||
@@ -16,10 +16,10 @@ const Page = () => {
|
||||
select: (el) => el.groupId as string
|
||||
});
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { data: groupMembership, isPending } = useGetWorkspaceGroupMembershipDetails(
|
||||
currentWorkspace.id,
|
||||
currentProject.id,
|
||||
groupId
|
||||
);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
IconButton
|
||||
} from "@app/components/v2";
|
||||
import { CopyButton } from "@app/components/v2/CopyButton";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { getProjectBaseURL } from "@app/helpers/project";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useDeleteGroupFromWorkspace } from "@app/hooks/api";
|
||||
@@ -31,14 +31,14 @@ export const GroupDetailsSection = ({ groupMembership }: Props) => {
|
||||
] as const);
|
||||
|
||||
const { mutateAsync: deleteMutateAsync } = useDeleteGroupFromWorkspace();
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onRemoveGroupSubmit = async () => {
|
||||
try {
|
||||
await deleteMutateAsync({
|
||||
groupId: groupMembership.group.id,
|
||||
projectId: currentWorkspace.id
|
||||
projectId: currentProject.id
|
||||
});
|
||||
|
||||
createNotification({
|
||||
@@ -47,9 +47,9 @@ export const GroupDetailsSection = ({ groupMembership }: Props) => {
|
||||
});
|
||||
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/access-management`,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/access-management`,
|
||||
params: {
|
||||
projectId: currentWorkspace.id
|
||||
projectId: currentProject.id
|
||||
},
|
||||
search: {
|
||||
selectedTab: "groups"
|
||||
|
||||
+6
-6
@@ -23,7 +23,7 @@ import {
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { useWorkspace } from "@app/context";
|
||||
import { useProject } from "@app/context";
|
||||
import { getProjectHomePage } from "@app/helpers/project";
|
||||
import {
|
||||
getUserTablePreference,
|
||||
@@ -69,12 +69,12 @@ export const GroupMembersTable = ({ groupMembership }: Props) => {
|
||||
setUserTablePreference("projectGroupMembersTable", PreferenceKey.PerPage, newPerPage);
|
||||
};
|
||||
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { data: groupMemberships, isPending } = useListProjectGroupUsers({
|
||||
id: groupMembership.group.id,
|
||||
groupSlug: groupMembership.group.slug,
|
||||
projectId: currentWorkspace.id,
|
||||
projectId: currentProject.id,
|
||||
offset,
|
||||
limit: perPage,
|
||||
search,
|
||||
@@ -127,7 +127,7 @@ export const GroupMembersTable = ({ groupMembership }: Props) => {
|
||||
{
|
||||
actorId: userId,
|
||||
actorType: ActorType.USER,
|
||||
projectId: currentWorkspace.id
|
||||
projectId: currentProject.id
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
@@ -136,8 +136,8 @@ export const GroupMembersTable = ({ groupMembership }: Props) => {
|
||||
text: "User privilege assumption has started"
|
||||
});
|
||||
|
||||
const url = getProjectHomePage(currentWorkspace.type, currentWorkspace.environments);
|
||||
window.location.href = url.replace("$projectId", currentWorkspace.id);
|
||||
const url = getProjectHomePage(currentProject.type, currentProject.environments);
|
||||
window.location.href = url.replace("$projectId", currentProject.id);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionIdentityActions,
|
||||
ProjectPermissionSub,
|
||||
useWorkspace
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { getProjectBaseURL, getProjectHomePage } from "@app/helpers/project";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
@@ -38,12 +38,10 @@ const Page = () => {
|
||||
strict: false,
|
||||
select: (el) => el.identityId as string
|
||||
});
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
|
||||
const workspaceId = currentWorkspace?.id || "";
|
||||
const { currentProject, projectId } = useProject();
|
||||
|
||||
const { data: identityMembershipDetails, isPending: isMembershipDetailsLoading } =
|
||||
useGetWorkspaceIdentityMembershipDetails(workspaceId, identityId);
|
||||
useGetWorkspaceIdentityMembershipDetails(projectId, identityId);
|
||||
|
||||
const { mutateAsync: deleteMutateAsync, isPending: isDeletingIdentity } =
|
||||
useDeleteIdentityFromWorkspace();
|
||||
@@ -59,7 +57,7 @@ const Page = () => {
|
||||
{
|
||||
actorId: identityId,
|
||||
actorType: ActorType.IDENTITY,
|
||||
projectId: workspaceId
|
||||
projectId
|
||||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
@@ -67,8 +65,8 @@ const Page = () => {
|
||||
type: "success",
|
||||
text: "Identity privilege assumption has started"
|
||||
});
|
||||
const url = getProjectHomePage(currentWorkspace.type, currentWorkspace.environments);
|
||||
window.location.href = url.replace("$projectId", currentWorkspace.id);
|
||||
const url = getProjectHomePage(currentProject.type, currentProject.environments);
|
||||
window.location.href = url.replace("$projectId", currentProject.id);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -78,7 +76,7 @@ const Page = () => {
|
||||
try {
|
||||
await deleteMutateAsync({
|
||||
identityId,
|
||||
workspaceId
|
||||
projectId
|
||||
});
|
||||
createNotification({
|
||||
text: "Successfully removed identity from project",
|
||||
@@ -86,9 +84,9 @@ const Page = () => {
|
||||
});
|
||||
handlePopUpClose("deleteIdentity");
|
||||
navigate({
|
||||
to: `${getProjectBaseURL(currentWorkspace.type)}/access-management` as const,
|
||||
to: `${getProjectBaseURL(currentProject.type)}/access-management` as const,
|
||||
params: {
|
||||
projectId: workspaceId
|
||||
projectId
|
||||
},
|
||||
search: {
|
||||
selectedTab: "identities"
|
||||
|
||||
+5
-5
@@ -24,8 +24,8 @@ import {
|
||||
import {
|
||||
ProjectPermissionIdentityActions,
|
||||
ProjectPermissionSub,
|
||||
useProjectPermission,
|
||||
useWorkspace
|
||||
useProject,
|
||||
useProjectPermission
|
||||
} from "@app/context";
|
||||
import {
|
||||
useCreateIdentityProjectAdditionalPrivilege,
|
||||
@@ -78,8 +78,8 @@ export const IdentityProjectAdditionalPrivilegeModifySection = ({
|
||||
isDisabled
|
||||
}: Props) => {
|
||||
const isCreate = !privilegeId;
|
||||
const { currentWorkspace } = useWorkspace();
|
||||
const projectId = currentWorkspace?.id || "";
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
const { data: privilegeDetails, isPending } = useGetIdentityProjectPrivilegeDetails({
|
||||
identityId,
|
||||
projectId,
|
||||
@@ -225,7 +225,7 @@ export const IdentityProjectAdditionalPrivilegeModifySection = ({
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<AddPoliciesButton isDisabled={isDisabled} projectType={currentWorkspace.type} />
|
||||
<AddPoliciesButton isDisabled={isDisabled} projectType={currentProject.type} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user