mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 21:26:40 +00:00
Merge pull request #4687 from Infisical/ENG-3955
feat(gateways): gateway and relay deployment CLI command interactive helper
This commit is contained in:
@@ -62,7 +62,11 @@ export const ROUTE_PATHS = Object.freeze({
|
|||||||
"/organization/app-connections/$appConnection/oauth/callback",
|
"/organization/app-connections/$appConnection/oauth/callback",
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections/$appConnection/oauth/callback"
|
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections/$appConnection/oauth/callback"
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
|
NetworkingPage: setRoute(
|
||||||
|
"/organization/networking",
|
||||||
|
"/_authenticate/_inject-org-details/_org-layout/organization/networking"
|
||||||
|
)
|
||||||
},
|
},
|
||||||
SecretManager: {
|
SecretManager: {
|
||||||
ApprovalPage: setRoute(
|
ApprovalPage: setRoute(
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export * from "./pkiSubscriber";
|
|||||||
export * from "./projects";
|
export * from "./projects";
|
||||||
export * from "./projectUserAdditionalPrivilege";
|
export * from "./projectUserAdditionalPrivilege";
|
||||||
export * from "./rateLimit";
|
export * from "./rateLimit";
|
||||||
|
export * from "./relays";
|
||||||
export * from "./roles";
|
export * from "./roles";
|
||||||
export * from "./scim";
|
export * from "./scim";
|
||||||
export * from "./secretApproval";
|
export * from "./secretApproval";
|
||||||
|
|||||||
+18
-2
@@ -8,6 +8,7 @@ import {
|
|||||||
faEllipsisV,
|
faEllipsisV,
|
||||||
faInfoCircle,
|
faInfoCircle,
|
||||||
faMagnifyingGlass,
|
faMagnifyingGlass,
|
||||||
|
faPlus,
|
||||||
faSearch,
|
faSearch,
|
||||||
faTrash
|
faTrash
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
@@ -17,6 +18,7 @@ import { useQuery } from "@tanstack/react-query";
|
|||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
import { OrgPermissionCan } from "@app/components/permissions";
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
DeleteActionModal,
|
DeleteActionModal,
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@@ -47,6 +49,7 @@ import { gatewaysQueryKeys, useDeleteGatewayById } from "@app/hooks/api/gateways
|
|||||||
import { useDeleteGatewayV2ById } from "@app/hooks/api/gateways-v2";
|
import { useDeleteGatewayV2ById } from "@app/hooks/api/gateways-v2";
|
||||||
|
|
||||||
import { EditGatewayDetailsModal } from "./components/EditGatewayDetailsModal";
|
import { EditGatewayDetailsModal } from "./components/EditGatewayDetailsModal";
|
||||||
|
import { GatewayDeployModal } from "./components/GatewayDeployModal";
|
||||||
|
|
||||||
const GatewayHealthStatus = ({ heartbeat }: { heartbeat?: string }) => {
|
const GatewayHealthStatus = ({ heartbeat }: { heartbeat?: string }) => {
|
||||||
const heartbeatDate = heartbeat ? new Date(heartbeat) : null;
|
const heartbeatDate = heartbeat ? new Date(heartbeat) : null;
|
||||||
@@ -73,6 +76,7 @@ export const GatewayTab = withPermission(
|
|||||||
const { data: gateways, isPending: isGatewaysLoading } = useQuery(gatewaysQueryKeys.list());
|
const { data: gateways, isPending: isGatewaysLoading } = useQuery(gatewaysQueryKeys.list());
|
||||||
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
||||||
|
"deployGateway",
|
||||||
"deleteGateway",
|
"deleteGateway",
|
||||||
"editDetails"
|
"editDetails"
|
||||||
] as const);
|
] as const);
|
||||||
@@ -101,8 +105,8 @@ export const GatewayTab = withPermission(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div className="mb-2 flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex grow items-center gap-2">
|
||||||
<h3 className="text-lg font-medium text-mineshaft-100">Gateways</h3>
|
<h3 className="text-lg font-medium text-mineshaft-100">Gateways</h3>
|
||||||
<a
|
<a
|
||||||
href="https://infisical.com/docs/documentation/platform/gateways/overview"
|
href="https://infisical.com/docs/documentation/platform/gateways/overview"
|
||||||
@@ -118,6 +122,14 @@ export const GatewayTab = withPermission(
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
<div className="flex grow" />
|
||||||
|
<Button
|
||||||
|
variant="outline_bg"
|
||||||
|
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||||
|
onClick={() => handlePopUpOpen("deployGateway")}
|
||||||
|
>
|
||||||
|
Deploy Gateway
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="mb-4 text-sm text-mineshaft-400">
|
<p className="mb-4 text-sm text-mineshaft-400">
|
||||||
@@ -257,6 +269,10 @@ export const GatewayTab = withPermission(
|
|||||||
deleteKey="confirm"
|
deleteKey="confirm"
|
||||||
onDeleteApproved={() => handleDeleteGateway()}
|
onDeleteApproved={() => handleDeleteGateway()}
|
||||||
/>
|
/>
|
||||||
|
<GatewayDeployModal
|
||||||
|
isOpen={popUp.deployGateway.isOpen}
|
||||||
|
onOpenChange={(isOpen) => handlePopUpToggle("deployGateway", isOpen)}
|
||||||
|
/>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+387
@@ -0,0 +1,387 @@
|
|||||||
|
import { useMemo, useState } from "react";
|
||||||
|
import { SingleValue } from "react-select";
|
||||||
|
import { faCopy, faQuestionCircle, faUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { useNavigate } from "@tanstack/react-router";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { createNotification } from "@app/components/notifications";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
FilterableSelect,
|
||||||
|
FormLabel,
|
||||||
|
IconButton,
|
||||||
|
Input,
|
||||||
|
ModalClose,
|
||||||
|
Tooltip
|
||||||
|
} from "@app/components/v2";
|
||||||
|
import { ROUTE_PATHS } from "@app/const/routes";
|
||||||
|
import {
|
||||||
|
OrgPermissionIdentityActions,
|
||||||
|
OrgPermissionSubjects,
|
||||||
|
useOrganization,
|
||||||
|
useOrgPermission
|
||||||
|
} from "@app/context";
|
||||||
|
import {
|
||||||
|
useAddIdentityTokenAuth,
|
||||||
|
useCreateTokenIdentityTokenAuth,
|
||||||
|
useGetIdentityMembershipOrgs,
|
||||||
|
useGetIdentityTokenAuth,
|
||||||
|
useGetRelays
|
||||||
|
} from "@app/hooks/api";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
|
import { RelayOption } from "./RelayOption";
|
||||||
|
|
||||||
|
const baseFormSchema = z.object({
|
||||||
|
name: slugSchema({ field: "name" }),
|
||||||
|
instanceDomain: z.string().url("Must be a valid URL").or(z.literal("")),
|
||||||
|
relay: z
|
||||||
|
.object(
|
||||||
|
{
|
||||||
|
id: z.string(),
|
||||||
|
name: z.string()
|
||||||
|
},
|
||||||
|
{ required_error: "Relay is required" }
|
||||||
|
)
|
||||||
|
.nullable()
|
||||||
|
.refine((val) => val !== null, { message: "Relay is required" })
|
||||||
|
});
|
||||||
|
|
||||||
|
const formSchemaWithIdentity = baseFormSchema.extend({
|
||||||
|
identity: z
|
||||||
|
.object(
|
||||||
|
{
|
||||||
|
id: z.string(),
|
||||||
|
name: z.string()
|
||||||
|
},
|
||||||
|
{ required_error: "Identity is required" }
|
||||||
|
)
|
||||||
|
.nullable()
|
||||||
|
.refine((val) => val !== null, { message: "Identity is required" })
|
||||||
|
});
|
||||||
|
|
||||||
|
const formSchemaWithToken = baseFormSchema.extend({
|
||||||
|
identityToken: z.string().min(1, "Token is required")
|
||||||
|
});
|
||||||
|
|
||||||
|
export const GatewayCliDeploymentMethod = () => {
|
||||||
|
const { protocol, hostname, port } = window.location;
|
||||||
|
const portSuffix = port && port !== "80" ? `:${port}` : "";
|
||||||
|
const siteURL = `${protocol}//${hostname}${portSuffix}`;
|
||||||
|
|
||||||
|
const navigate = useNavigate({
|
||||||
|
from: ROUTE_PATHS.Organization.NetworkingPage.path
|
||||||
|
});
|
||||||
|
|
||||||
|
const [autogenerateToken, setAutogenerateToken] = useState(true);
|
||||||
|
const [step, setStep] = useState<"form" | "command">("form");
|
||||||
|
const [name, setName] = useState("");
|
||||||
|
const [instanceDomain, setInstanceDomain] = useState(siteURL);
|
||||||
|
const [relay, setRelay] = useState<null | {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}>(null);
|
||||||
|
const [identity, setIdentity] = useState<null | {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}>(null);
|
||||||
|
const [identityToken, setIdentityToken] = useState("");
|
||||||
|
const [formErrors, setFormErrors] = useState<z.ZodIssue[]>([]);
|
||||||
|
|
||||||
|
const errors = useMemo(() => {
|
||||||
|
const errorMap: Record<string, string | undefined> = {};
|
||||||
|
formErrors.forEach((issue) => {
|
||||||
|
if (issue.path.length > 0) {
|
||||||
|
errorMap[String(issue.path[0])] = issue.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return errorMap;
|
||||||
|
}, [formErrors]);
|
||||||
|
|
||||||
|
const { data: relays, isPending: isRelaysLoading } = useGetRelays();
|
||||||
|
|
||||||
|
const { currentOrg } = useOrganization();
|
||||||
|
const organizationId = currentOrg?.id || "";
|
||||||
|
|
||||||
|
const { permission } = useOrgPermission();
|
||||||
|
const canCreateToken = permission.can(
|
||||||
|
OrgPermissionIdentityActions.CreateToken,
|
||||||
|
OrgPermissionSubjects.Identity
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: identityMembershipOrgsData, isPending: isIdentitiesLoading } =
|
||||||
|
useGetIdentityMembershipOrgs({
|
||||||
|
organizationId,
|
||||||
|
limit: 20000
|
||||||
|
});
|
||||||
|
const identityMembershipOrgs = identityMembershipOrgsData?.identityMemberships || [];
|
||||||
|
|
||||||
|
const { mutateAsync: createToken, isPending: isCreatingToken } =
|
||||||
|
useCreateTokenIdentityTokenAuth();
|
||||||
|
const { mutateAsync: addIdentityTokenAuth, isPending: isAddingTokenAuth } =
|
||||||
|
useAddIdentityTokenAuth();
|
||||||
|
const { refetch } = useGetIdentityTokenAuth(identity?.id ?? "");
|
||||||
|
|
||||||
|
const handleGenerateCommand = async () => {
|
||||||
|
setFormErrors([]);
|
||||||
|
|
||||||
|
if (canCreateToken && autogenerateToken) {
|
||||||
|
const validation = formSchemaWithIdentity.safeParse({
|
||||||
|
name,
|
||||||
|
relay,
|
||||||
|
identity,
|
||||||
|
instanceDomain
|
||||||
|
});
|
||||||
|
if (!validation.success) {
|
||||||
|
setFormErrors(validation.error.issues);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const validatedIdentity = validation.data.identity;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data: identityTokenAuth } = await refetch();
|
||||||
|
if (!identityTokenAuth) {
|
||||||
|
await addIdentityTokenAuth({
|
||||||
|
identityId: validatedIdentity.id,
|
||||||
|
organizationId,
|
||||||
|
accessTokenTTL: 2592000,
|
||||||
|
accessTokenMaxTTL: 2592000,
|
||||||
|
accessTokenNumUsesLimit: 0,
|
||||||
|
accessTokenTrustedIps: [{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]
|
||||||
|
});
|
||||||
|
createNotification({
|
||||||
|
text: "Token authentication has been automatically enabled for the selected identity. By default, it is configured to allow all IP addresses with a default token TTL of 30 days. You can manage these settings in Access Control.",
|
||||||
|
type: "warning"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = await createToken({
|
||||||
|
identityId: validatedIdentity.id,
|
||||||
|
name: `gateway token for ${name} (autogenerated)`
|
||||||
|
});
|
||||||
|
setIdentityToken(token.accessToken);
|
||||||
|
createNotification({
|
||||||
|
text: "Automatically generated a token for the selected identity.",
|
||||||
|
type: "info"
|
||||||
|
});
|
||||||
|
setStep("command");
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
createNotification({
|
||||||
|
text: "Failed to generate token for the selected identity",
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
setIdentityToken("");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const validation = formSchemaWithToken.safeParse({
|
||||||
|
name,
|
||||||
|
relay,
|
||||||
|
identityToken,
|
||||||
|
instanceDomain
|
||||||
|
});
|
||||||
|
if (!validation.success) {
|
||||||
|
setFormErrors(validation.error.issues);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setStep("command");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const command = useMemo(() => {
|
||||||
|
const domainFlag = instanceDomain ? ` --domain=${instanceDomain}` : "";
|
||||||
|
return `infisical gateway start --name=${name} --relay=${
|
||||||
|
relay?.name || ""
|
||||||
|
}${domainFlag} --token=${identityToken}`;
|
||||||
|
}, [name, relay, identityToken, instanceDomain]);
|
||||||
|
|
||||||
|
if (step === "command") {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormLabel label="CLI Command" />
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Input value={command} isDisabled />
|
||||||
|
<IconButton
|
||||||
|
ariaLabel="copy"
|
||||||
|
variant="outline_bg"
|
||||||
|
colorSchema="secondary"
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(command);
|
||||||
|
createNotification({
|
||||||
|
text: "Command copied to clipboard",
|
||||||
|
type: "info"
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className="w-10"
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faCopy} />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
href="https://infisical.com/docs/cli/overview"
|
||||||
|
target="_blank"
|
||||||
|
className="mt-2 flex h-4 w-fit items-center gap-2 border-b border-mineshaft-400 text-sm text-mineshaft-400 transition-colors duration-100 hover:border-yellow-400 hover:text-yellow-400"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<span>Install the Infisical CLI</span>
|
||||||
|
<FontAwesomeIcon icon={faUpRightFromSquare} className="size-3" />
|
||||||
|
</a>
|
||||||
|
<div className="mt-6 flex items-center">
|
||||||
|
<ModalClose asChild>
|
||||||
|
<Button className="mr-4" size="sm" colorSchema="secondary">
|
||||||
|
Done
|
||||||
|
</Button>
|
||||||
|
</ModalClose>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormLabel label="Name" tooltipText="The name for your gateway." />
|
||||||
|
<Input
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
placeholder="Enter gateway name..."
|
||||||
|
isError={Boolean(errors.name)}
|
||||||
|
/>
|
||||||
|
{errors.name && <p className="mt-1 text-sm text-red">{errors.name}</p>}
|
||||||
|
|
||||||
|
<FormLabel label="Relay" tooltipText="The relay to use with your gateway." className="mt-4" />
|
||||||
|
<FilterableSelect
|
||||||
|
value={relay}
|
||||||
|
onChange={(newValue) => {
|
||||||
|
if ((newValue as SingleValue<{ id: string }>)?.id === "_create") {
|
||||||
|
navigate({
|
||||||
|
search: (prev) => ({ ...prev, selectedTab: "relays", action: "deploy-relay" })
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setRelay(newValue as SingleValue<{ id: string; name: string }>);
|
||||||
|
}}
|
||||||
|
isLoading={isRelaysLoading}
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
id: "_create",
|
||||||
|
name: "Deploy New Relay"
|
||||||
|
},
|
||||||
|
...(relays || [])
|
||||||
|
]}
|
||||||
|
placeholder="Select relay..."
|
||||||
|
getOptionLabel={(option) => option.name}
|
||||||
|
getOptionValue={(option) => option.id}
|
||||||
|
components={{ Option: RelayOption }}
|
||||||
|
/>
|
||||||
|
{errors.relay && <p className="mt-1 text-sm text-red">{errors.relay}</p>}
|
||||||
|
|
||||||
|
<FormLabel
|
||||||
|
label="Infisical Instance Host Address"
|
||||||
|
tooltipText="The host address of the infisical instance that's accessible by the gateway."
|
||||||
|
className="mt-4"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
value={instanceDomain}
|
||||||
|
onChange={(e) => setInstanceDomain(e.target.value)}
|
||||||
|
placeholder="https://app.infisical.com"
|
||||||
|
isError={Boolean(errors.instanceDomain)}
|
||||||
|
/>
|
||||||
|
{errors.instanceDomain && <p className="mt-1 text-sm text-red">{errors.instanceDomain}</p>}
|
||||||
|
|
||||||
|
{canCreateToken && autogenerateToken ? (
|
||||||
|
<>
|
||||||
|
<FormLabel
|
||||||
|
label="Identity"
|
||||||
|
tooltipText="The identity that your gateway will use for authentication."
|
||||||
|
className="mt-4"
|
||||||
|
/>
|
||||||
|
<FilterableSelect
|
||||||
|
value={identity}
|
||||||
|
onChange={(e) =>
|
||||||
|
setIdentity(
|
||||||
|
e as SingleValue<{
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
isLoading={isIdentitiesLoading}
|
||||||
|
placeholder="Select identity..."
|
||||||
|
options={identityMembershipOrgs.map((membership) => membership.identity)}
|
||||||
|
getOptionValue={(option) => option.id}
|
||||||
|
getOptionLabel={(option) => option.name}
|
||||||
|
/>
|
||||||
|
{errors.identity && <p className="mt-1 text-sm text-red">{errors.identity}</p>}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<FormLabel
|
||||||
|
label="Identity Token"
|
||||||
|
tooltipText="The identity token that your relay will use for authentication."
|
||||||
|
className="mt-4"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
value={identityToken}
|
||||||
|
onChange={(e) => setIdentityToken(e.target.value)}
|
||||||
|
placeholder="Enter identity token..."
|
||||||
|
isError={Boolean(errors.identityToken)}
|
||||||
|
/>
|
||||||
|
{errors.identityToken && <p className="mt-1 text-sm text-red">{errors.identityToken}</p>}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{canCreateToken && (
|
||||||
|
<div className="mt-2">
|
||||||
|
<Checkbox
|
||||||
|
isChecked={autogenerateToken}
|
||||||
|
onCheckedChange={(e) => {
|
||||||
|
setAutogenerateToken(Boolean(e));
|
||||||
|
}}
|
||||||
|
id="autogenerate-token"
|
||||||
|
className="mr-2"
|
||||||
|
>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<span>Automatically enable token auth and generate a token for identity</span>
|
||||||
|
<Tooltip
|
||||||
|
className="max-w-md"
|
||||||
|
content={
|
||||||
|
<>
|
||||||
|
Token authentication will be automatically enabled for the selected identity if
|
||||||
|
it isn't already configured. By default, it will be configured to allow all
|
||||||
|
IP addresses with a token TTL of 30 days. You can manage these settings in
|
||||||
|
Access Control.
|
||||||
|
<br />
|
||||||
|
<br />A token will automatically be generated to be used with the CLI command.
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faQuestionCircle} size="sm" className="mt-0.5 ml-1" />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mt-6 flex items-center">
|
||||||
|
<Button
|
||||||
|
className="mr-4"
|
||||||
|
size="sm"
|
||||||
|
colorSchema="secondary"
|
||||||
|
onClick={handleGenerateCommand}
|
||||||
|
isLoading={isCreatingToken || isAddingTokenAuth}
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</Button>
|
||||||
|
<ModalClose asChild>
|
||||||
|
<Button colorSchema="secondary" variant="plain">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ModalClose>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
import { Modal, ModalContent } from "@app/components/v2";
|
||||||
|
import { GatewayDeploymentMethodSelect } from "@app/pages/organization/NetworkingPage/components/GatewayTab/components/GatewayDeploymentMethodSelect";
|
||||||
|
|
||||||
|
import { GatewayCliDeploymentMethod } from "./GatewayCliDeploymentMethod";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isOpen: boolean;
|
||||||
|
onOpenChange: (isOpen: boolean) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GatewayDeploymentInfoMap = {
|
||||||
|
cli: { name: "CLI", image: "SSH.png", component: GatewayCliDeploymentMethod }
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type GatewayDeploymentMethod = keyof typeof GatewayDeploymentInfoMap;
|
||||||
|
|
||||||
|
const Content = () => {
|
||||||
|
const [selectedMethod, setSelectedMethod] = useState<null | GatewayDeploymentMethod>(null);
|
||||||
|
|
||||||
|
if (selectedMethod) {
|
||||||
|
const ComponentToRender = GatewayDeploymentInfoMap[selectedMethod]?.component;
|
||||||
|
if (ComponentToRender) {
|
||||||
|
return <ComponentToRender />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <GatewayDeploymentMethodSelect onSelect={setSelectedMethod} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GatewayDeployModal = ({ isOpen, onOpenChange }: Props) => {
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||||
|
<ModalContent
|
||||||
|
className="max-w-2xl"
|
||||||
|
title="Deploy Gateway"
|
||||||
|
subTitle="Select a deployment method to use for the gateway."
|
||||||
|
bodyClassName="overflow-visible"
|
||||||
|
>
|
||||||
|
<Content />
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
GatewayDeploymentInfoMap,
|
||||||
|
GatewayDeploymentMethod
|
||||||
|
} from "@app/pages/organization/NetworkingPage/components/GatewayTab/components/GatewayDeployModal";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onSelect: (method: GatewayDeploymentMethod) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GatewayDeploymentMethodSelect = ({ onSelect }: Props) => {
|
||||||
|
const deploymentOptions = useMemo(
|
||||||
|
() =>
|
||||||
|
(Object.keys(GatewayDeploymentInfoMap) as GatewayDeploymentMethod[]).map((method) => ({
|
||||||
|
method,
|
||||||
|
name: GatewayDeploymentInfoMap[method].name,
|
||||||
|
image: GatewayDeploymentInfoMap[method].image
|
||||||
|
})),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleResourceSelect = (method: GatewayDeploymentMethod) => {
|
||||||
|
onSelect(method);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid h-fit grid-cols-4 content-start gap-2">
|
||||||
|
{deploymentOptions.map((option) => {
|
||||||
|
const { image, name, method } = option;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={method}
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleResourceSelect(method)}
|
||||||
|
className="group relative flex h-28 cursor-pointer flex-col items-center justify-center rounded-md border border-mineshaft-600 bg-mineshaft-700 p-4 duration-200 hover:bg-mineshaft-600"
|
||||||
|
>
|
||||||
|
<div className="relative">
|
||||||
|
<img
|
||||||
|
src={`/images/integrations/${image}`}
|
||||||
|
className="mt-auto w-12"
|
||||||
|
alt={`${name} logo`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mt-auto max-w-xs text-center text-xs font-medium text-gray-300 duration-200 group-hover:text-gray-200">
|
||||||
|
{name}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
import { components, OptionProps } from "react-select";
|
||||||
|
import { faCheckCircle } from "@fortawesome/free-regular-svg-icons";
|
||||||
|
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
|
export const RelayOption = ({
|
||||||
|
isSelected,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: OptionProps<{ id: string; name: string }>) => {
|
||||||
|
const isCreateOption = props.data.id === "_create";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<components.Option isSelected={isSelected} {...props}>
|
||||||
|
<div className="flex flex-row items-center justify-between">
|
||||||
|
{isCreateOption ? (
|
||||||
|
<div className="flex items-center gap-x-1 text-mineshaft-400">
|
||||||
|
<FontAwesomeIcon icon={faPlus} size="sm" />
|
||||||
|
<span className="mr-auto">Deploy New Relay</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<p className="truncate">{children}</p>
|
||||||
|
{isSelected && (
|
||||||
|
<FontAwesomeIcon className="ml-2 text-primary" icon={faCheckCircle} size="sm" />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</components.Option>
|
||||||
|
);
|
||||||
|
};
|
||||||
+15
-6
@@ -1,15 +1,20 @@
|
|||||||
import { useState } from "react";
|
import { useNavigate, useSearch } from "@tanstack/react-router";
|
||||||
import { useSearch } from "@tanstack/react-router";
|
|
||||||
|
|
||||||
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
||||||
|
import { ROUTE_PATHS } from "@app/const/routes";
|
||||||
import { useOrganization } from "@app/context";
|
import { useOrganization } from "@app/context";
|
||||||
|
|
||||||
import { GatewayTab } from "../GatewayTab/GatewayTab";
|
import { GatewayTab } from "../GatewayTab/GatewayTab";
|
||||||
import { RelayTab } from "../RelayTab/RelayTab";
|
import { RelayTab } from "../RelayTab/RelayTab";
|
||||||
|
|
||||||
export const NetworkingTabGroup = () => {
|
export const NetworkingTabGroup = () => {
|
||||||
const search = useSearch({
|
const navigate = useNavigate({
|
||||||
from: "/_authenticate/_inject-org-details/_org-layout/organization/networking/"
|
from: ROUTE_PATHS.Organization.NetworkingPage.path
|
||||||
|
});
|
||||||
|
const selectedTab = useSearch({
|
||||||
|
from: ROUTE_PATHS.Organization.NetworkingPage.id,
|
||||||
|
select: (el) => el.selectedTab,
|
||||||
|
structuralSharing: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
@@ -17,12 +22,16 @@ export const NetworkingTabGroup = () => {
|
|||||||
{ name: "Relays", key: "relays", component: RelayTab }
|
{ name: "Relays", key: "relays", component: RelayTab }
|
||||||
];
|
];
|
||||||
|
|
||||||
const [selectedTab, setSelectedTab] = useState(search.selectedTab || tabs[0].key);
|
const handleTabChange = (tab: string) => {
|
||||||
|
navigate({
|
||||||
|
search: { selectedTab: tab }
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const { isSubOrganization } = useOrganization();
|
const { isSubOrganization } = useOrganization();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tabs orientation="vertical" value={selectedTab} onValueChange={setSelectedTab}>
|
<Tabs orientation="vertical" value={selectedTab} onValueChange={handleTabChange}>
|
||||||
<TabList>
|
<TabList>
|
||||||
{tabs.map((tab) => (
|
{tabs.map((tab) => (
|
||||||
<Tab variant={isSubOrganization ? "namespace" : "org"} value={tab.key} key={tab.key}>
|
<Tab variant={isSubOrganization ? "namespace" : "org"} value={tab.key} key={tab.key}>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
faArrowUpRightFromSquare,
|
faArrowUpRightFromSquare,
|
||||||
faBookOpen,
|
faBookOpen,
|
||||||
@@ -7,15 +7,18 @@ import {
|
|||||||
faEllipsisV,
|
faEllipsisV,
|
||||||
faInfoCircle,
|
faInfoCircle,
|
||||||
faMagnifyingGlass,
|
faMagnifyingGlass,
|
||||||
|
faPlus,
|
||||||
faSearch,
|
faSearch,
|
||||||
faTrash
|
faTrash
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { useNavigate, useSearch } from "@tanstack/react-router";
|
||||||
import { formatRelative } from "date-fns";
|
import { formatRelative } from "date-fns";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
import { OrgPermissionCan } from "@app/components/permissions";
|
||||||
import {
|
import {
|
||||||
|
Button,
|
||||||
DeleteActionModal,
|
DeleteActionModal,
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@@ -34,6 +37,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
Tr
|
Tr
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
|
import { ROUTE_PATHS } from "@app/const/routes";
|
||||||
import {
|
import {
|
||||||
OrgPermissionSubjects,
|
OrgPermissionSubjects,
|
||||||
OrgRelayPermissionActions
|
OrgRelayPermissionActions
|
||||||
@@ -42,6 +46,8 @@ import { withPermission } from "@app/hoc";
|
|||||||
import { usePopUp } from "@app/hooks";
|
import { usePopUp } from "@app/hooks";
|
||||||
import { useDeleteRelayById, useGetRelays } from "@app/hooks/api/relays";
|
import { useDeleteRelayById, useGetRelays } from "@app/hooks/api/relays";
|
||||||
|
|
||||||
|
import { RelayDeployModal } from "./components/RelayDeployModal";
|
||||||
|
|
||||||
const RelayHealthStatus = ({ heartbeat }: { heartbeat?: string }) => {
|
const RelayHealthStatus = ({ heartbeat }: { heartbeat?: string }) => {
|
||||||
const heartbeatDate = heartbeat ? new Date(heartbeat) : null;
|
const heartbeatDate = heartbeat ? new Date(heartbeat) : null;
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
@@ -66,7 +72,29 @@ export const RelayTab = withPermission(
|
|||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const { data: relays, isPending: isRelaysLoading } = useGetRelays();
|
const { data: relays, isPending: isRelaysLoading } = useGetRelays();
|
||||||
|
|
||||||
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["deleteRelay"] as const);
|
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp([
|
||||||
|
"deleteRelay",
|
||||||
|
"deployRelay"
|
||||||
|
] as const);
|
||||||
|
|
||||||
|
const action = useSearch({
|
||||||
|
from: ROUTE_PATHS.Organization.NetworkingPage.id,
|
||||||
|
select: (s) => s.action
|
||||||
|
});
|
||||||
|
|
||||||
|
const navigate = useNavigate({
|
||||||
|
from: ROUTE_PATHS.Organization.NetworkingPage.path
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (action === "deploy-relay") {
|
||||||
|
handlePopUpOpen("deployRelay");
|
||||||
|
navigate({
|
||||||
|
search: (prev) => ({ ...prev, action: undefined }),
|
||||||
|
replace: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [action, handlePopUpOpen, navigate]);
|
||||||
|
|
||||||
const deleteRelayById = useDeleteRelayById();
|
const deleteRelayById = useDeleteRelayById();
|
||||||
|
|
||||||
@@ -87,8 +115,8 @@ export const RelayTab = withPermission(
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||||
<div className="mb-4 flex items-center justify-between">
|
<div className="mb-2 flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex grow items-center gap-2">
|
||||||
<h3 className="text-lg font-medium text-mineshaft-100">Relays</h3>
|
<h3 className="text-lg font-medium text-mineshaft-100">Relays</h3>
|
||||||
<a
|
<a
|
||||||
href="https://infisical.com/docs/documentation/platform/gateways/relay-deployment"
|
href="https://infisical.com/docs/documentation/platform/gateways/relay-deployment"
|
||||||
@@ -104,6 +132,14 @@ export const RelayTab = withPermission(
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
<div className="flex grow" />
|
||||||
|
<Button
|
||||||
|
variant="outline_bg"
|
||||||
|
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||||
|
onClick={() => handlePopUpOpen("deployRelay")}
|
||||||
|
>
|
||||||
|
Deploy Relay
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p className="mb-4 text-sm text-mineshaft-400">
|
<p className="mb-4 text-sm text-mineshaft-400">
|
||||||
@@ -222,6 +258,10 @@ export const RelayTab = withPermission(
|
|||||||
deleteKey="confirm"
|
deleteKey="confirm"
|
||||||
onDeleteApproved={() => handleDeleteRelay()}
|
onDeleteApproved={() => handleDeleteRelay()}
|
||||||
/>
|
/>
|
||||||
|
<RelayDeployModal
|
||||||
|
isOpen={popUp.deployRelay.isOpen}
|
||||||
|
onOpenChange={(isOpen) => handlePopUpToggle("deployRelay", isOpen)}
|
||||||
|
/>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+352
@@ -0,0 +1,352 @@
|
|||||||
|
import { useMemo, useState } from "react";
|
||||||
|
import { SingleValue } from "react-select";
|
||||||
|
import { faCopy, faQuestionCircle, faUpRightFromSquare } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { createNotification } from "@app/components/notifications";
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
FilterableSelect,
|
||||||
|
FormLabel,
|
||||||
|
IconButton,
|
||||||
|
Input,
|
||||||
|
ModalClose,
|
||||||
|
Tooltip
|
||||||
|
} from "@app/components/v2";
|
||||||
|
import {
|
||||||
|
OrgPermissionIdentityActions,
|
||||||
|
OrgPermissionSubjects,
|
||||||
|
useOrganization,
|
||||||
|
useOrgPermission
|
||||||
|
} from "@app/context";
|
||||||
|
import {
|
||||||
|
useAddIdentityTokenAuth,
|
||||||
|
useCreateTokenIdentityTokenAuth,
|
||||||
|
useGetIdentityMembershipOrgs,
|
||||||
|
useGetIdentityTokenAuth
|
||||||
|
} from "@app/hooks/api";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
|
const baseFormSchema = z.object({
|
||||||
|
name: slugSchema({ field: "name" }),
|
||||||
|
host: z.string().min(1, "Host is required"),
|
||||||
|
instanceDomain: z.string().url("Must be a valid URL").or(z.literal(""))
|
||||||
|
});
|
||||||
|
|
||||||
|
const formSchemaWithIdentity = baseFormSchema.extend({
|
||||||
|
identity: z
|
||||||
|
.object(
|
||||||
|
{
|
||||||
|
id: z.string(),
|
||||||
|
name: z.string()
|
||||||
|
},
|
||||||
|
{ required_error: "Identity is required" }
|
||||||
|
)
|
||||||
|
.nullable()
|
||||||
|
.refine((val) => val !== null, { message: "Identity is required" })
|
||||||
|
});
|
||||||
|
|
||||||
|
const formSchemaWithToken = baseFormSchema.extend({
|
||||||
|
identityToken: z.string().min(1, "Token is required")
|
||||||
|
});
|
||||||
|
|
||||||
|
export const RelayCliDeploymentMethod = () => {
|
||||||
|
const { protocol, hostname, port } = window.location;
|
||||||
|
const portSuffix = port && port !== "80" ? `:${port}` : "";
|
||||||
|
const siteURL = `${protocol}//${hostname}${portSuffix}`;
|
||||||
|
|
||||||
|
const [autogenerateToken, setAutogenerateToken] = useState(true);
|
||||||
|
const [step, setStep] = useState<"form" | "command">("form");
|
||||||
|
const [name, setName] = useState("");
|
||||||
|
const [host, setHost] = useState("");
|
||||||
|
|
||||||
|
const [instanceDomain, setInstanceDomain] = useState(siteURL);
|
||||||
|
const [identity, setIdentity] = useState<null | {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}>(null);
|
||||||
|
const [identityToken, setIdentityToken] = useState("");
|
||||||
|
const [formErrors, setFormErrors] = useState<z.ZodIssue[]>([]);
|
||||||
|
|
||||||
|
const errors = useMemo(() => {
|
||||||
|
const errorMap: Record<string, string | undefined> = {};
|
||||||
|
formErrors.forEach((issue) => {
|
||||||
|
if (issue.path.length > 0) {
|
||||||
|
errorMap[String(issue.path[0])] = issue.message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return errorMap;
|
||||||
|
}, [formErrors]);
|
||||||
|
|
||||||
|
const { currentOrg } = useOrganization();
|
||||||
|
const organizationId = currentOrg?.id || "";
|
||||||
|
|
||||||
|
const { permission } = useOrgPermission();
|
||||||
|
const canCreateToken = permission.can(
|
||||||
|
OrgPermissionIdentityActions.CreateToken,
|
||||||
|
OrgPermissionSubjects.Identity
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: identityMembershipOrgsData, isPending: isIdentitiesLoading } =
|
||||||
|
useGetIdentityMembershipOrgs({
|
||||||
|
organizationId,
|
||||||
|
limit: 20000
|
||||||
|
});
|
||||||
|
const identityMembershipOrgs = identityMembershipOrgsData?.identityMemberships || [];
|
||||||
|
|
||||||
|
const { mutateAsync: createToken, isPending: isCreatingToken } =
|
||||||
|
useCreateTokenIdentityTokenAuth();
|
||||||
|
const { mutateAsync: addIdentityTokenAuth, isPending: isAddingTokenAuth } =
|
||||||
|
useAddIdentityTokenAuth();
|
||||||
|
const { refetch } = useGetIdentityTokenAuth(identity?.id ?? "");
|
||||||
|
|
||||||
|
const handleGenerateCommand = async () => {
|
||||||
|
setFormErrors([]);
|
||||||
|
|
||||||
|
if (canCreateToken && autogenerateToken) {
|
||||||
|
const validation = formSchemaWithIdentity.safeParse({ name, host, instanceDomain, identity });
|
||||||
|
if (!validation.success) {
|
||||||
|
setFormErrors(validation.error.issues);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const validatedIdentity = validation.data.identity;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data: identityTokenAuth } = await refetch();
|
||||||
|
if (!identityTokenAuth) {
|
||||||
|
await addIdentityTokenAuth({
|
||||||
|
identityId: validatedIdentity.id,
|
||||||
|
organizationId,
|
||||||
|
accessTokenTTL: 2592000,
|
||||||
|
accessTokenMaxTTL: 2592000,
|
||||||
|
accessTokenNumUsesLimit: 0,
|
||||||
|
accessTokenTrustedIps: [{ ipAddress: "0.0.0.0/0" }, { ipAddress: "::/0" }]
|
||||||
|
});
|
||||||
|
createNotification({
|
||||||
|
text: "Token authentication has been automatically enabled for the selected identity. By default, it is configured to allow all IP addresses with a default token TTL of 30 days. You can manage these settings in Access Control.",
|
||||||
|
type: "warning"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = await createToken({
|
||||||
|
identityId: validatedIdentity.id,
|
||||||
|
name: `relay token for ${name} (autogenerated)`
|
||||||
|
});
|
||||||
|
setIdentityToken(token.accessToken);
|
||||||
|
createNotification({
|
||||||
|
text: "Automatically generated a token for the selected identity.",
|
||||||
|
type: "info"
|
||||||
|
});
|
||||||
|
setStep("command");
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
createNotification({
|
||||||
|
text: "Failed to generate token for the selected identity",
|
||||||
|
type: "error"
|
||||||
|
});
|
||||||
|
setIdentityToken("");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const validation = formSchemaWithToken.safeParse({
|
||||||
|
name,
|
||||||
|
host,
|
||||||
|
instanceDomain,
|
||||||
|
identityToken
|
||||||
|
});
|
||||||
|
if (!validation.success) {
|
||||||
|
setFormErrors(validation.error.issues);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setStep("command");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleIdentityChange = (
|
||||||
|
selectedIdentity: SingleValue<{
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}>
|
||||||
|
) => {
|
||||||
|
setIdentity(selectedIdentity);
|
||||||
|
};
|
||||||
|
|
||||||
|
const command = useMemo(() => {
|
||||||
|
const domainFlag = instanceDomain ? ` --domain=${instanceDomain}` : "";
|
||||||
|
return `infisical relay start --name=${name}${domainFlag} --host=${host} --token=${identityToken}`;
|
||||||
|
}, [name, instanceDomain, host, identityToken]);
|
||||||
|
|
||||||
|
if (step === "command") {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormLabel label="CLI Command" />
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<Input value={command} isDisabled />
|
||||||
|
<IconButton
|
||||||
|
ariaLabel="copy"
|
||||||
|
variant="outline_bg"
|
||||||
|
colorSchema="secondary"
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(command);
|
||||||
|
createNotification({
|
||||||
|
text: "Command copied to clipboard",
|
||||||
|
type: "info"
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className="w-10"
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faCopy} />
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
href="https://infisical.com/docs/cli/overview"
|
||||||
|
target="_blank"
|
||||||
|
className="mt-2 flex h-4 w-fit items-center gap-2 border-b border-mineshaft-400 text-sm text-mineshaft-400 transition-colors duration-100 hover:border-yellow-400 hover:text-yellow-400"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<span>Install the Infisical CLI</span>
|
||||||
|
<FontAwesomeIcon icon={faUpRightFromSquare} className="size-3" />
|
||||||
|
</a>
|
||||||
|
<div className="mt-6 flex items-center">
|
||||||
|
<ModalClose asChild>
|
||||||
|
<Button className="mr-4" size="sm" colorSchema="secondary">
|
||||||
|
Done
|
||||||
|
</Button>
|
||||||
|
</ModalClose>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FormLabel label="Name" tooltipText="The name for your relay." />
|
||||||
|
<Input
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
placeholder="Enter relay name..."
|
||||||
|
isError={Boolean(errors.name)}
|
||||||
|
/>
|
||||||
|
{errors.name && <p className="mt-1 text-sm text-red">{errors.name}</p>}
|
||||||
|
|
||||||
|
<FormLabel
|
||||||
|
label="Host"
|
||||||
|
tooltipText="The public IP address of the system you're deploying the relay to."
|
||||||
|
className="mt-4"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
value={host}
|
||||||
|
onChange={(e) => setHost(e.target.value)}
|
||||||
|
placeholder="0.0.0.0"
|
||||||
|
isError={Boolean(errors.host)}
|
||||||
|
/>
|
||||||
|
{errors.host && <p className="mt-1 text-sm text-red">{errors.host}</p>}
|
||||||
|
|
||||||
|
<FormLabel
|
||||||
|
label="Infisical Instance Host Address"
|
||||||
|
tooltipText="The host address of the infisical instance that's accessible by the relay."
|
||||||
|
className="mt-4"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
value={instanceDomain}
|
||||||
|
onChange={(e) => setInstanceDomain(e.target.value)}
|
||||||
|
placeholder="https://app.infisical.com"
|
||||||
|
isError={Boolean(errors.instanceDomain)}
|
||||||
|
/>
|
||||||
|
{errors.instanceDomain && <p className="mt-1 text-sm text-red">{errors.instanceDomain}</p>}
|
||||||
|
|
||||||
|
{canCreateToken && autogenerateToken ? (
|
||||||
|
<>
|
||||||
|
<FormLabel
|
||||||
|
label="Identity"
|
||||||
|
tooltipText="The identity that your relay will use for authentication."
|
||||||
|
className="mt-4"
|
||||||
|
/>
|
||||||
|
<FilterableSelect
|
||||||
|
value={identity}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleIdentityChange(
|
||||||
|
e as SingleValue<{
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
isLoading={isIdentitiesLoading}
|
||||||
|
placeholder="Select identity..."
|
||||||
|
options={identityMembershipOrgs.map((membership) => membership.identity)}
|
||||||
|
getOptionValue={(option) => option.id}
|
||||||
|
getOptionLabel={(option) => option.name}
|
||||||
|
/>
|
||||||
|
{errors.identity && <p className="mt-1 text-sm text-red">{errors.identity}</p>}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<FormLabel
|
||||||
|
label="Identity Token"
|
||||||
|
tooltipText="The identity token that your relay will use for authentication."
|
||||||
|
className="mt-4"
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
value={identityToken}
|
||||||
|
onChange={(e) => setIdentityToken(e.target.value)}
|
||||||
|
placeholder="Enter identity token..."
|
||||||
|
isError={Boolean(errors.identityToken)}
|
||||||
|
/>
|
||||||
|
{errors.identityToken && <p className="mt-1 text-sm text-red">{errors.identityToken}</p>}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{canCreateToken && (
|
||||||
|
<div className="mt-2">
|
||||||
|
<Checkbox
|
||||||
|
isChecked={autogenerateToken}
|
||||||
|
onCheckedChange={(e) => {
|
||||||
|
setAutogenerateToken(Boolean(e));
|
||||||
|
}}
|
||||||
|
id="autogenerate-token"
|
||||||
|
className="mr-2"
|
||||||
|
>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<span>Automatically enable token auth and generate a token for identity</span>
|
||||||
|
<Tooltip
|
||||||
|
className="max-w-md"
|
||||||
|
content={
|
||||||
|
<>
|
||||||
|
Token authentication will be automatically enabled for the selected identity if
|
||||||
|
it isn't already configured. By default, it will be configured to allow all
|
||||||
|
IP addresses with a token TTL of 30 days. You can manage these settings in
|
||||||
|
Access Control.
|
||||||
|
<br />
|
||||||
|
<br />A token will automatically be generated to be used with the CLI command.
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faQuestionCircle} size="sm" className="mt-0.5 ml-1" />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="mt-6 flex items-center">
|
||||||
|
<Button
|
||||||
|
className="mr-4"
|
||||||
|
size="sm"
|
||||||
|
colorSchema="secondary"
|
||||||
|
onClick={handleGenerateCommand}
|
||||||
|
isLoading={isCreatingToken || isAddingTokenAuth}
|
||||||
|
>
|
||||||
|
Continue
|
||||||
|
</Button>
|
||||||
|
<ModalClose asChild>
|
||||||
|
<Button colorSchema="secondary" variant="plain">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</ModalClose>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
import { Modal, ModalContent } from "@app/components/v2";
|
||||||
|
import { RelayDeploymentMethodSelect } from "@app/pages/organization/NetworkingPage/components/RelayTab/components/RelayDeploymentMethodSelect";
|
||||||
|
|
||||||
|
import { RelayCliDeploymentMethod } from "./RelayCliDeploymentMethod";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
isOpen: boolean;
|
||||||
|
onOpenChange: (isOpen: boolean) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RelayDeploymentInfoMap = {
|
||||||
|
cli: { name: "CLI", image: "SSH.png", component: RelayCliDeploymentMethod }
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type RelayDeploymentMethod = keyof typeof RelayDeploymentInfoMap;
|
||||||
|
|
||||||
|
const Content = () => {
|
||||||
|
const [selectedMethod, setSelectedMethod] = useState<null | RelayDeploymentMethod>(null);
|
||||||
|
|
||||||
|
if (selectedMethod) {
|
||||||
|
const ComponentToRender = RelayDeploymentInfoMap[selectedMethod]?.component;
|
||||||
|
if (ComponentToRender) {
|
||||||
|
return <ComponentToRender />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <RelayDeploymentMethodSelect onSelect={setSelectedMethod} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RelayDeployModal = ({ isOpen, onOpenChange }: Props) => {
|
||||||
|
return (
|
||||||
|
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
|
||||||
|
<ModalContent
|
||||||
|
className="max-w-2xl"
|
||||||
|
title="Deploy Relay"
|
||||||
|
subTitle="Select a deployment method to use for the relay."
|
||||||
|
bodyClassName="overflow-visible"
|
||||||
|
>
|
||||||
|
<Content />
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
RelayDeploymentInfoMap,
|
||||||
|
RelayDeploymentMethod
|
||||||
|
} from "@app/pages/organization/NetworkingPage/components/RelayTab/components/RelayDeployModal";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onSelect: (method: RelayDeploymentMethod) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RelayDeploymentMethodSelect = ({ onSelect }: Props) => {
|
||||||
|
const deploymentOptions = useMemo(
|
||||||
|
() =>
|
||||||
|
(Object.keys(RelayDeploymentInfoMap) as RelayDeploymentMethod[]).map((method) => ({
|
||||||
|
method,
|
||||||
|
name: RelayDeploymentInfoMap[method].name,
|
||||||
|
image: RelayDeploymentInfoMap[method].image
|
||||||
|
})),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleResourceSelect = (method: RelayDeploymentMethod) => {
|
||||||
|
onSelect(method);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="grid h-fit grid-cols-4 content-start gap-2">
|
||||||
|
{deploymentOptions.map((option) => {
|
||||||
|
const { image, name, method } = option;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={method}
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleResourceSelect(method)}
|
||||||
|
className="group relative flex h-28 cursor-pointer flex-col items-center justify-center rounded-md border border-mineshaft-600 bg-mineshaft-700 p-4 duration-200 hover:bg-mineshaft-600"
|
||||||
|
>
|
||||||
|
<div className="relative">
|
||||||
|
<img
|
||||||
|
src={`/images/integrations/${image}`}
|
||||||
|
className="mt-auto w-12"
|
||||||
|
alt={`${name} logo`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mt-auto max-w-xs text-center text-xs font-medium text-gray-300 duration-200 group-hover:text-gray-200">
|
||||||
|
{name}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -5,16 +5,17 @@ import { z } from "zod";
|
|||||||
import { NetworkingPage } from "./NetworkingPage";
|
import { NetworkingPage } from "./NetworkingPage";
|
||||||
|
|
||||||
const NetworkingPageQueryParams = z.object({
|
const NetworkingPageQueryParams = z.object({
|
||||||
selectedTab: z.string().catch("")
|
selectedTab: z.string().catch("gateways"),
|
||||||
|
action: z.string().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Route = createFileRoute(
|
export const Route = createFileRoute(
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/networking/"
|
"/_authenticate/_inject-org-details/_org-layout/organization/networking"
|
||||||
)({
|
)({
|
||||||
component: NetworkingPage,
|
component: NetworkingPage,
|
||||||
validateSearch: zodValidator(NetworkingPageQueryParams),
|
validateSearch: zodValidator(NetworkingPageQueryParams),
|
||||||
search: {
|
search: {
|
||||||
middlewares: [stripSearchParams({ selectedTab: "" })]
|
middlewares: [stripSearchParams({ selectedTab: "gateways" })]
|
||||||
},
|
},
|
||||||
context: () => ({
|
context: () => ({
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import { Route as adminCachingPageRouteImport } from './pages/admin/CachingPage/
|
|||||||
import { Route as adminAuthenticationPageRouteImport } from './pages/admin/AuthenticationPage/route'
|
import { Route as adminAuthenticationPageRouteImport } from './pages/admin/AuthenticationPage/route'
|
||||||
import { Route as adminAccessManagementPageRouteImport } from './pages/admin/AccessManagementPage/route'
|
import { Route as adminAccessManagementPageRouteImport } from './pages/admin/AccessManagementPage/route'
|
||||||
import { Route as organizationProjectsPageRouteImport } from './pages/organization/ProjectsPage/route'
|
import { Route as organizationProjectsPageRouteImport } from './pages/organization/ProjectsPage/route'
|
||||||
|
import { Route as organizationNetworkingPageRouteImport } from './pages/organization/NetworkingPage/route'
|
||||||
import { Route as organizationBillingPageRouteImport } from './pages/organization/BillingPage/route'
|
import { Route as organizationBillingPageRouteImport } from './pages/organization/BillingPage/route'
|
||||||
import { Route as organizationAuditLogsPageRouteImport } from './pages/organization/AuditLogsPage/route'
|
import { Route as organizationAuditLogsPageRouteImport } from './pages/organization/AuditLogsPage/route'
|
||||||
import { Route as organizationAccessManagementPageRouteImport } from './pages/organization/AccessManagementPage/route'
|
import { Route as organizationAccessManagementPageRouteImport } from './pages/organization/AccessManagementPage/route'
|
||||||
@@ -62,7 +63,6 @@ import { Route as organizationIdentityDetailsByIDPageRouteImport } from './pages
|
|||||||
import { Route as organizationGroupDetailsByIDPageRouteImport } from './pages/organization/GroupDetailsByIDPage/route'
|
import { Route as organizationGroupDetailsByIDPageRouteImport } from './pages/organization/GroupDetailsByIDPage/route'
|
||||||
import { Route as organizationSettingsPageRouteImport } from './pages/organization/SettingsPage/route'
|
import { Route as organizationSettingsPageRouteImport } from './pages/organization/SettingsPage/route'
|
||||||
import { Route as organizationSecretSharingPageRouteImport } from './pages/organization/SecretSharingPage/route'
|
import { Route as organizationSecretSharingPageRouteImport } from './pages/organization/SecretSharingPage/route'
|
||||||
import { Route as organizationNetworkingPageRouteImport } from './pages/organization/NetworkingPage/route'
|
|
||||||
import { Route as organizationAppConnectionsAppConnectionsPageRouteImport } from './pages/organization/AppConnections/AppConnectionsPage/route'
|
import { Route as organizationAppConnectionsAppConnectionsPageRouteImport } from './pages/organization/AppConnections/AppConnectionsPage/route'
|
||||||
import { Route as sshLayoutImport } from './pages/ssh/layout'
|
import { Route as sshLayoutImport } from './pages/ssh/layout'
|
||||||
import { Route as secretScanningLayoutImport } from './pages/secret-scanning/layout'
|
import { Route as secretScanningLayoutImport } from './pages/secret-scanning/layout'
|
||||||
@@ -270,10 +270,6 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingImport =
|
|||||||
createFileRoute(
|
createFileRoute(
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing',
|
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing',
|
||||||
)()
|
)()
|
||||||
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingImport =
|
|
||||||
createFileRoute(
|
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/networking',
|
|
||||||
)()
|
|
||||||
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport =
|
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport =
|
||||||
createFileRoute(
|
createFileRoute(
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/app-connections',
|
'/_authenticate/_inject-org-details/_org-layout/organization/app-connections',
|
||||||
@@ -594,14 +590,6 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute =
|
|||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute =
|
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingImport.update({
|
|
||||||
id: '/networking',
|
|
||||||
path: '/networking',
|
|
||||||
getParentRoute: () =>
|
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute =
|
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute =
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport.update({
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport.update({
|
||||||
id: '/app-connections',
|
id: '/app-connections',
|
||||||
@@ -658,6 +646,14 @@ const organizationProjectsPageRouteRoute =
|
|||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
|
const organizationNetworkingPageRouteRoute =
|
||||||
|
organizationNetworkingPageRouteImport.update({
|
||||||
|
id: '/networking',
|
||||||
|
path: '/networking',
|
||||||
|
getParentRoute: () =>
|
||||||
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
const organizationBillingPageRouteRoute =
|
const organizationBillingPageRouteRoute =
|
||||||
organizationBillingPageRouteImport.update({
|
organizationBillingPageRouteImport.update({
|
||||||
id: '/billing',
|
id: '/billing',
|
||||||
@@ -799,14 +795,6 @@ const organizationSecretSharingPageRouteRoute =
|
|||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute,
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
const organizationNetworkingPageRouteRoute =
|
|
||||||
organizationNetworkingPageRouteImport.update({
|
|
||||||
id: '/',
|
|
||||||
path: '/',
|
|
||||||
getParentRoute: () =>
|
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute,
|
|
||||||
} as any)
|
|
||||||
|
|
||||||
const organizationAppConnectionsAppConnectionsPageRouteRoute =
|
const organizationAppConnectionsAppConnectionsPageRouteRoute =
|
||||||
organizationAppConnectionsAppConnectionsPageRouteImport.update({
|
organizationAppConnectionsAppConnectionsPageRouteImport.update({
|
||||||
id: '/',
|
id: '/',
|
||||||
@@ -2476,6 +2464,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof organizationBillingPageRouteImport
|
preLoaderRoute: typeof organizationBillingPageRouteImport
|
||||||
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
|
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
|
||||||
}
|
}
|
||||||
|
'/_authenticate/_inject-org-details/_org-layout/organization/networking': {
|
||||||
|
id: '/_authenticate/_inject-org-details/_org-layout/organization/networking'
|
||||||
|
path: '/networking'
|
||||||
|
fullPath: '/organization/networking'
|
||||||
|
preLoaderRoute: typeof organizationNetworkingPageRouteImport
|
||||||
|
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
|
||||||
|
}
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/projects': {
|
'/_authenticate/_inject-org-details/_org-layout/organization/projects': {
|
||||||
id: '/_authenticate/_inject-org-details/_org-layout/organization/projects'
|
id: '/_authenticate/_inject-org-details/_org-layout/organization/projects'
|
||||||
path: '/projects'
|
path: '/projects'
|
||||||
@@ -2532,13 +2527,6 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport
|
preLoaderRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport
|
||||||
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
|
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
|
||||||
}
|
}
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/networking': {
|
|
||||||
id: '/_authenticate/_inject-org-details/_org-layout/organization/networking'
|
|
||||||
path: '/networking'
|
|
||||||
fullPath: '/organization/networking'
|
|
||||||
preLoaderRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingImport
|
|
||||||
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationImport
|
|
||||||
}
|
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing': {
|
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing': {
|
||||||
id: '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing'
|
id: '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing'
|
||||||
path: '/secret-sharing'
|
path: '/secret-sharing'
|
||||||
@@ -2567,13 +2555,6 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof organizationAppConnectionsAppConnectionsPageRouteImport
|
preLoaderRoute: typeof organizationAppConnectionsAppConnectionsPageRouteImport
|
||||||
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport
|
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsImport
|
||||||
}
|
}
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/networking/': {
|
|
||||||
id: '/_authenticate/_inject-org-details/_org-layout/organization/networking/'
|
|
||||||
path: '/'
|
|
||||||
fullPath: '/organization/networking/'
|
|
||||||
preLoaderRoute: typeof organizationNetworkingPageRouteImport
|
|
||||||
parentRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingImport
|
|
||||||
}
|
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/': {
|
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/': {
|
||||||
id: '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/'
|
id: '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/'
|
||||||
path: '/'
|
path: '/'
|
||||||
@@ -4001,20 +3982,6 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithCh
|
|||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteChildren,
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteChildren,
|
||||||
)
|
)
|
||||||
|
|
||||||
interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteChildren {
|
|
||||||
organizationNetworkingPageRouteRoute: typeof organizationNetworkingPageRouteRoute
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteChildren: AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteChildren =
|
|
||||||
{
|
|
||||||
organizationNetworkingPageRouteRoute: organizationNetworkingPageRouteRoute,
|
|
||||||
}
|
|
||||||
|
|
||||||
const AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren =
|
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute._addFileChildren(
|
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteChildren,
|
|
||||||
)
|
|
||||||
|
|
||||||
interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteChildren {
|
interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteChildren {
|
||||||
organizationSecretSharingPageRouteRoute: typeof organizationSecretSharingPageRouteRoute
|
organizationSecretSharingPageRouteRoute: typeof organizationSecretSharingPageRouteRoute
|
||||||
}
|
}
|
||||||
@@ -4051,9 +4018,9 @@ interface AuthenticateInjectOrgDetailsOrgLayoutOrganizationRouteChildren {
|
|||||||
organizationAccessManagementPageRouteRoute: typeof organizationAccessManagementPageRouteRoute
|
organizationAccessManagementPageRouteRoute: typeof organizationAccessManagementPageRouteRoute
|
||||||
organizationAuditLogsPageRouteRoute: typeof organizationAuditLogsPageRouteRoute
|
organizationAuditLogsPageRouteRoute: typeof organizationAuditLogsPageRouteRoute
|
||||||
organizationBillingPageRouteRoute: typeof organizationBillingPageRouteRoute
|
organizationBillingPageRouteRoute: typeof organizationBillingPageRouteRoute
|
||||||
|
organizationNetworkingPageRouteRoute: typeof organizationNetworkingPageRouteRoute
|
||||||
organizationProjectsPageRouteRoute: typeof organizationProjectsPageRouteRoute
|
organizationProjectsPageRouteRoute: typeof organizationProjectsPageRouteRoute
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren
|
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRouteWithChildren
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRoute: typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRouteWithChildren
|
||||||
organizationGroupDetailsByIDPageRouteRoute: typeof organizationGroupDetailsByIDPageRouteRoute
|
organizationGroupDetailsByIDPageRouteRoute: typeof organizationGroupDetailsByIDPageRouteRoute
|
||||||
@@ -4068,11 +4035,10 @@ const AuthenticateInjectOrgDetailsOrgLayoutOrganizationRouteChildren: Authentica
|
|||||||
organizationAccessManagementPageRouteRoute,
|
organizationAccessManagementPageRouteRoute,
|
||||||
organizationAuditLogsPageRouteRoute: organizationAuditLogsPageRouteRoute,
|
organizationAuditLogsPageRouteRoute: organizationAuditLogsPageRouteRoute,
|
||||||
organizationBillingPageRouteRoute: organizationBillingPageRouteRoute,
|
organizationBillingPageRouteRoute: organizationBillingPageRouteRoute,
|
||||||
|
organizationNetworkingPageRouteRoute: organizationNetworkingPageRouteRoute,
|
||||||
organizationProjectsPageRouteRoute: organizationProjectsPageRouteRoute,
|
organizationProjectsPageRouteRoute: organizationProjectsPageRouteRoute,
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute:
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRoute:
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren,
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren,
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRoute:
|
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren,
|
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute:
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRoute:
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren,
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren,
|
||||||
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRoute:
|
AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRoute:
|
||||||
@@ -5055,6 +5021,7 @@ export interface FileRoutesByFullPath {
|
|||||||
'/organization/access-management': typeof organizationAccessManagementPageRouteRoute
|
'/organization/access-management': typeof organizationAccessManagementPageRouteRoute
|
||||||
'/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute
|
'/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute
|
||||||
'/organization/billing': typeof organizationBillingPageRouteRoute
|
'/organization/billing': typeof organizationBillingPageRouteRoute
|
||||||
|
'/organization/networking': typeof organizationNetworkingPageRouteRoute
|
||||||
'/organization/projects': typeof organizationProjectsPageRouteRoute
|
'/organization/projects': typeof organizationProjectsPageRouteRoute
|
||||||
'/admin/access-management': typeof adminAccessManagementPageRouteRoute
|
'/admin/access-management': typeof adminAccessManagementPageRouteRoute
|
||||||
'/admin/authentication': typeof adminAuthenticationPageRouteRoute
|
'/admin/authentication': typeof adminAuthenticationPageRouteRoute
|
||||||
@@ -5063,12 +5030,10 @@ export interface FileRoutesByFullPath {
|
|||||||
'/admin/environment': typeof adminEnvironmentPageRouteRoute
|
'/admin/environment': typeof adminEnvironmentPageRouteRoute
|
||||||
'/admin/integrations': typeof adminIntegrationsPageRouteRoute
|
'/admin/integrations': typeof adminIntegrationsPageRouteRoute
|
||||||
'/organization/app-connections': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
|
'/organization/app-connections': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
|
||||||
'/organization/networking': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren
|
|
||||||
'/organization/secret-sharing': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
|
'/organization/secret-sharing': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
|
||||||
'/organization/settings': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRouteWithChildren
|
'/organization/settings': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRouteWithChildren
|
||||||
'/secret-manager/$projectId': typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdRouteWithChildren
|
'/secret-manager/$projectId': typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdRouteWithChildren
|
||||||
'/organization/app-connections/': typeof organizationAppConnectionsAppConnectionsPageRouteRoute
|
'/organization/app-connections/': typeof organizationAppConnectionsAppConnectionsPageRouteRoute
|
||||||
'/organization/networking/': typeof organizationNetworkingPageRouteRoute
|
|
||||||
'/organization/secret-sharing/': typeof organizationSecretSharingPageRouteRoute
|
'/organization/secret-sharing/': typeof organizationSecretSharingPageRouteRoute
|
||||||
'/organization/settings/': typeof organizationSettingsPageRouteRoute
|
'/organization/settings/': typeof organizationSettingsPageRouteRoute
|
||||||
'/organization/groups/$groupId': typeof organizationGroupDetailsByIDPageRouteRoute
|
'/organization/groups/$groupId': typeof organizationGroupDetailsByIDPageRouteRoute
|
||||||
@@ -5292,6 +5257,7 @@ export interface FileRoutesByTo {
|
|||||||
'/organization/access-management': typeof organizationAccessManagementPageRouteRoute
|
'/organization/access-management': typeof organizationAccessManagementPageRouteRoute
|
||||||
'/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute
|
'/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute
|
||||||
'/organization/billing': typeof organizationBillingPageRouteRoute
|
'/organization/billing': typeof organizationBillingPageRouteRoute
|
||||||
|
'/organization/networking': typeof organizationNetworkingPageRouteRoute
|
||||||
'/organization/projects': typeof organizationProjectsPageRouteRoute
|
'/organization/projects': typeof organizationProjectsPageRouteRoute
|
||||||
'/admin/access-management': typeof adminAccessManagementPageRouteRoute
|
'/admin/access-management': typeof adminAccessManagementPageRouteRoute
|
||||||
'/admin/authentication': typeof adminAuthenticationPageRouteRoute
|
'/admin/authentication': typeof adminAuthenticationPageRouteRoute
|
||||||
@@ -5301,7 +5267,6 @@ export interface FileRoutesByTo {
|
|||||||
'/admin/integrations': typeof adminIntegrationsPageRouteRoute
|
'/admin/integrations': typeof adminIntegrationsPageRouteRoute
|
||||||
'/secret-manager/$projectId': typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdRouteWithChildren
|
'/secret-manager/$projectId': typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdRouteWithChildren
|
||||||
'/organization/app-connections': typeof organizationAppConnectionsAppConnectionsPageRouteRoute
|
'/organization/app-connections': typeof organizationAppConnectionsAppConnectionsPageRouteRoute
|
||||||
'/organization/networking': typeof organizationNetworkingPageRouteRoute
|
|
||||||
'/organization/secret-sharing': typeof organizationSecretSharingPageRouteRoute
|
'/organization/secret-sharing': typeof organizationSecretSharingPageRouteRoute
|
||||||
'/organization/settings': typeof organizationSettingsPageRouteRoute
|
'/organization/settings': typeof organizationSettingsPageRouteRoute
|
||||||
'/organization/groups/$groupId': typeof organizationGroupDetailsByIDPageRouteRoute
|
'/organization/groups/$groupId': typeof organizationGroupDetailsByIDPageRouteRoute
|
||||||
@@ -5527,6 +5492,7 @@ export interface FileRoutesById {
|
|||||||
'/_authenticate/_inject-org-details/_org-layout/organization/access-management': typeof organizationAccessManagementPageRouteRoute
|
'/_authenticate/_inject-org-details/_org-layout/organization/access-management': typeof organizationAccessManagementPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute
|
'/_authenticate/_inject-org-details/_org-layout/organization/audit-logs': typeof organizationAuditLogsPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/billing': typeof organizationBillingPageRouteRoute
|
'/_authenticate/_inject-org-details/_org-layout/organization/billing': typeof organizationBillingPageRouteRoute
|
||||||
|
'/_authenticate/_inject-org-details/_org-layout/organization/networking': typeof organizationNetworkingPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/projects': typeof organizationProjectsPageRouteRoute
|
'/_authenticate/_inject-org-details/_org-layout/organization/projects': typeof organizationProjectsPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/admin/_admin-layout/access-management': typeof adminAccessManagementPageRouteRoute
|
'/_authenticate/_inject-org-details/admin/_admin-layout/access-management': typeof adminAccessManagementPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/admin/_admin-layout/authentication': typeof adminAuthenticationPageRouteRoute
|
'/_authenticate/_inject-org-details/admin/_admin-layout/authentication': typeof adminAuthenticationPageRouteRoute
|
||||||
@@ -5535,12 +5501,10 @@ export interface FileRoutesById {
|
|||||||
'/_authenticate/_inject-org-details/admin/_admin-layout/environment': typeof adminEnvironmentPageRouteRoute
|
'/_authenticate/_inject-org-details/admin/_admin-layout/environment': typeof adminEnvironmentPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/admin/_admin-layout/integrations': typeof adminIntegrationsPageRouteRoute
|
'/_authenticate/_inject-org-details/admin/_admin-layout/integrations': typeof adminIntegrationsPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/app-connections': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
|
'/_authenticate/_inject-org-details/_org-layout/organization/app-connections': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationAppConnectionsRouteWithChildren
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/networking': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationNetworkingRouteWithChildren
|
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
|
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSecretSharingRouteWithChildren
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/settings': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRouteWithChildren
|
'/_authenticate/_inject-org-details/_org-layout/organization/settings': typeof AuthenticateInjectOrgDetailsOrgLayoutOrganizationSettingsRouteWithChildren
|
||||||
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId': typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdRouteWithChildren
|
'/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId': typeof AuthenticateInjectOrgDetailsOrgLayoutSecretManagerProjectIdRouteWithChildren
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/app-connections/': typeof organizationAppConnectionsAppConnectionsPageRouteRoute
|
'/_authenticate/_inject-org-details/_org-layout/organization/app-connections/': typeof organizationAppConnectionsAppConnectionsPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/networking/': typeof organizationNetworkingPageRouteRoute
|
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/': typeof organizationSecretSharingPageRouteRoute
|
'/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/': typeof organizationSecretSharingPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/settings/': typeof organizationSettingsPageRouteRoute
|
'/_authenticate/_inject-org-details/_org-layout/organization/settings/': typeof organizationSettingsPageRouteRoute
|
||||||
'/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId': typeof organizationGroupDetailsByIDPageRouteRoute
|
'/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId': typeof organizationGroupDetailsByIDPageRouteRoute
|
||||||
@@ -5776,6 +5740,7 @@ export interface FileRouteTypes {
|
|||||||
| '/organization/access-management'
|
| '/organization/access-management'
|
||||||
| '/organization/audit-logs'
|
| '/organization/audit-logs'
|
||||||
| '/organization/billing'
|
| '/organization/billing'
|
||||||
|
| '/organization/networking'
|
||||||
| '/organization/projects'
|
| '/organization/projects'
|
||||||
| '/admin/access-management'
|
| '/admin/access-management'
|
||||||
| '/admin/authentication'
|
| '/admin/authentication'
|
||||||
@@ -5784,12 +5749,10 @@ export interface FileRouteTypes {
|
|||||||
| '/admin/environment'
|
| '/admin/environment'
|
||||||
| '/admin/integrations'
|
| '/admin/integrations'
|
||||||
| '/organization/app-connections'
|
| '/organization/app-connections'
|
||||||
| '/organization/networking'
|
|
||||||
| '/organization/secret-sharing'
|
| '/organization/secret-sharing'
|
||||||
| '/organization/settings'
|
| '/organization/settings'
|
||||||
| '/secret-manager/$projectId'
|
| '/secret-manager/$projectId'
|
||||||
| '/organization/app-connections/'
|
| '/organization/app-connections/'
|
||||||
| '/organization/networking/'
|
|
||||||
| '/organization/secret-sharing/'
|
| '/organization/secret-sharing/'
|
||||||
| '/organization/settings/'
|
| '/organization/settings/'
|
||||||
| '/organization/groups/$groupId'
|
| '/organization/groups/$groupId'
|
||||||
@@ -6012,6 +5975,7 @@ export interface FileRouteTypes {
|
|||||||
| '/organization/access-management'
|
| '/organization/access-management'
|
||||||
| '/organization/audit-logs'
|
| '/organization/audit-logs'
|
||||||
| '/organization/billing'
|
| '/organization/billing'
|
||||||
|
| '/organization/networking'
|
||||||
| '/organization/projects'
|
| '/organization/projects'
|
||||||
| '/admin/access-management'
|
| '/admin/access-management'
|
||||||
| '/admin/authentication'
|
| '/admin/authentication'
|
||||||
@@ -6021,7 +5985,6 @@ export interface FileRouteTypes {
|
|||||||
| '/admin/integrations'
|
| '/admin/integrations'
|
||||||
| '/secret-manager/$projectId'
|
| '/secret-manager/$projectId'
|
||||||
| '/organization/app-connections'
|
| '/organization/app-connections'
|
||||||
| '/organization/networking'
|
|
||||||
| '/organization/secret-sharing'
|
| '/organization/secret-sharing'
|
||||||
| '/organization/settings'
|
| '/organization/settings'
|
||||||
| '/organization/groups/$groupId'
|
| '/organization/groups/$groupId'
|
||||||
@@ -6245,6 +6208,7 @@ export interface FileRouteTypes {
|
|||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/access-management'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/access-management'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/audit-logs'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/audit-logs'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/billing'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/billing'
|
||||||
|
| '/_authenticate/_inject-org-details/_org-layout/organization/networking'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/projects'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/projects'
|
||||||
| '/_authenticate/_inject-org-details/admin/_admin-layout/access-management'
|
| '/_authenticate/_inject-org-details/admin/_admin-layout/access-management'
|
||||||
| '/_authenticate/_inject-org-details/admin/_admin-layout/authentication'
|
| '/_authenticate/_inject-org-details/admin/_admin-layout/authentication'
|
||||||
@@ -6253,12 +6217,10 @@ export interface FileRouteTypes {
|
|||||||
| '/_authenticate/_inject-org-details/admin/_admin-layout/environment'
|
| '/_authenticate/_inject-org-details/admin/_admin-layout/environment'
|
||||||
| '/_authenticate/_inject-org-details/admin/_admin-layout/integrations'
|
| '/_authenticate/_inject-org-details/admin/_admin-layout/integrations'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/app-connections'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/app-connections'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/networking'
|
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/settings'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/settings'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId'
|
| '/_authenticate/_inject-org-details/_org-layout/secret-manager/$projectId'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/app-connections/'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/app-connections/'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/networking/'
|
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/settings/'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/settings/'
|
||||||
| '/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId'
|
| '/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId'
|
||||||
@@ -6701,9 +6663,9 @@ export const routeTree = rootRoute
|
|||||||
"/_authenticate/_inject-org-details/_org-layout/organization/access-management",
|
"/_authenticate/_inject-org-details/_org-layout/organization/access-management",
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/audit-logs",
|
"/_authenticate/_inject-org-details/_org-layout/organization/audit-logs",
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/billing",
|
"/_authenticate/_inject-org-details/_org-layout/organization/billing",
|
||||||
|
"/_authenticate/_inject-org-details/_org-layout/organization/networking",
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/projects",
|
"/_authenticate/_inject-org-details/_org-layout/organization/projects",
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections",
|
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections",
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/networking",
|
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing",
|
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing",
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/settings",
|
"/_authenticate/_inject-org-details/_org-layout/organization/settings",
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId",
|
"/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId",
|
||||||
@@ -6742,6 +6704,10 @@ export const routeTree = rootRoute
|
|||||||
"filePath": "organization/BillingPage/route.tsx",
|
"filePath": "organization/BillingPage/route.tsx",
|
||||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organization"
|
"parent": "/_authenticate/_inject-org-details/_org-layout/organization"
|
||||||
},
|
},
|
||||||
|
"/_authenticate/_inject-org-details/_org-layout/organization/networking": {
|
||||||
|
"filePath": "organization/NetworkingPage/route.tsx",
|
||||||
|
"parent": "/_authenticate/_inject-org-details/_org-layout/organization"
|
||||||
|
},
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/projects": {
|
"/_authenticate/_inject-org-details/_org-layout/organization/projects": {
|
||||||
"filePath": "organization/ProjectsPage/route.tsx",
|
"filePath": "organization/ProjectsPage/route.tsx",
|
||||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organization"
|
"parent": "/_authenticate/_inject-org-details/_org-layout/organization"
|
||||||
@@ -6778,13 +6744,6 @@ export const routeTree = rootRoute
|
|||||||
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections/$appConnection/oauth/callback"
|
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections/$appConnection/oauth/callback"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/networking": {
|
|
||||||
"filePath": "",
|
|
||||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organization",
|
|
||||||
"children": [
|
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/networking/"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing": {
|
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing": {
|
||||||
"filePath": "",
|
"filePath": "",
|
||||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organization",
|
"parent": "/_authenticate/_inject-org-details/_org-layout/organization",
|
||||||
@@ -6811,10 +6770,6 @@ export const routeTree = rootRoute
|
|||||||
"filePath": "organization/AppConnections/AppConnectionsPage/route.tsx",
|
"filePath": "organization/AppConnections/AppConnectionsPage/route.tsx",
|
||||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organization/app-connections"
|
"parent": "/_authenticate/_inject-org-details/_org-layout/organization/app-connections"
|
||||||
},
|
},
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/networking/": {
|
|
||||||
"filePath": "organization/NetworkingPage/route.tsx",
|
|
||||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organization/networking"
|
|
||||||
},
|
|
||||||
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/": {
|
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/": {
|
||||||
"filePath": "organization/SecretSharingPage/route.tsx",
|
"filePath": "organization/SecretSharingPage/route.tsx",
|
||||||
"parent": "/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing"
|
"parent": "/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing"
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const organizationRoutes = route("/organization", [
|
|||||||
"organization/AppConnections/OauthCallbackPage/route.tsx"
|
"organization/AppConnections/OauthCallbackPage/route.tsx"
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
route("/networking", [index("organization/NetworkingPage/route.tsx")])
|
route("/networking", "organization/NetworkingPage/route.tsx")
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const secretManagerRoutes = route("/projects/secret-management/$projectId", [
|
const secretManagerRoutes = route("/projects/secret-management/$projectId", [
|
||||||
|
|||||||
Reference in New Issue
Block a user