mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 04:27:38 +00:00
Merge branch 'main' into feature/mongodb-secret-rotation
This commit is contained in:
+7
-7
@@ -8,15 +8,15 @@
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="
|
||||
default-src 'self';
|
||||
connect-src 'self' https://*.posthog.com http://127.0.0.1:* https://cdn.jsdelivr.net/npm/@lottiefiles/[email protected]/dist/dotlottie-player.wasm;
|
||||
script-src 'self' https://*.posthog.com https://js.stripe.com https://api.stripe.com https://widget.intercom.io https://js.intercomcdn.com https://hcaptcha.com https://*.hcaptcha.com 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net/npm/@lottiefiles/[email protected]/dist/dotlottie-player.wasm;
|
||||
style-src 'self' 'unsafe-inline' https://hcaptcha.com https://*.hcaptcha.com;
|
||||
connect-src 'self' https://d1zwf0dwl0k2ky.cloudfront.net https://*.posthog.com http://127.0.0.1:* https://cdn.jsdelivr.net/npm/@lottiefiles/[email protected]/dist/dotlottie-player.wasm;
|
||||
script-src 'self' https://d1zwf0dwl0k2ky.cloudfront.net https://*.posthog.com https://js.stripe.com https://api.stripe.com https://widget.intercom.io https://js.intercomcdn.com https://hcaptcha.com https://*.hcaptcha.com 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net/npm/@lottiefiles/[email protected]/dist/dotlottie-player.wasm;
|
||||
style-src 'self' https://d1zwf0dwl0k2ky.cloudfront.net 'unsafe-inline' https://hcaptcha.com https://*.hcaptcha.com;
|
||||
child-src https://api.stripe.com;
|
||||
frame-src https://js.stripe.com/ https://api.stripe.com https://www.youtube.com/ https://hcaptcha.com https://*.hcaptcha.com;
|
||||
connect-src 'self' wss://nexus-websocket-a.intercom.io https://api-iam.intercom.io https://api.heroku.com/ https://id.heroku.com/oauth/authorize https://id.heroku.com/oauth/token https://checkout.stripe.com https://app.posthog.com https://api.stripe.com https://api.pwnedpasswords.com http://127.0.0.1:* https://hcaptcha.com https://*.hcaptcha.com;
|
||||
img-src 'self' https://static.intercomassets.com https://js.intercomcdn.com https://downloads.intercomcdn.com https://*.stripe.com https://i.ytimg.com/ data:;
|
||||
media-src https://js.intercomcdn.com;
|
||||
font-src 'self' https://fonts.intercomcdn.com/ https://fonts.gstatic.com;
|
||||
connect-src 'self' https://d1zwf0dwl0k2ky.cloudfront.net wss://nexus-websocket-a.intercom.io https://api-iam.intercom.io https://api.heroku.com/ https://id.heroku.com/oauth/authorize https://id.heroku.com/oauth/token https://checkout.stripe.com https://app.posthog.com https://api.stripe.com https://api.pwnedpasswords.com http://127.0.0.1:* https://hcaptcha.com https://*.hcaptcha.com;
|
||||
img-src 'self' https://d1zwf0dwl0k2ky.cloudfront.net https://static.intercomassets.com https://js.intercomcdn.com https://downloads.intercomcdn.com https://*.stripe.com https://i.ytimg.com/ data:;
|
||||
media-src https://d1zwf0dwl0k2ky.cloudfront.net https://js.intercomcdn.com;
|
||||
font-src 'self' https://d1zwf0dwl0k2ky.cloudfront.net https://fonts.intercomcdn.com/ https://fonts.gstatic.com;
|
||||
"
|
||||
/>
|
||||
<title>Infisical</title>
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 120 60" width="120" height="60" style="enable-background:new 0 0 120 60;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#808285;}
|
||||
.st1{fill:url(#SVGID_1_);}
|
||||
.st2{fill:#005B99;}
|
||||
.st3{enable-background:new ;}
|
||||
.st4{fill:#77787B;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M34.1,42.6h9.4v-3.2C41.5,41.2,38.2,42.3,34.1,42.6L34.1,42.6z"/>
|
||||
<path class="st0" d="M17.3,40.1v2.5h11.9c-2.4-0.2-5-0.6-7.6-1.2C20.1,41,18.7,40.6,17.3,40.1L17.3,40.1z"/>
|
||||
|
||||
<radialGradient id="SVGID_1_" cx="-183.5882" cy="811.1324" r="47.498" gradientTransform="matrix(1 0 0 1 241.0864 -776.3726)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" style="stop-color:#0095DA"/>
|
||||
<stop offset="0.21" style="stop-color:#0095DA"/>
|
||||
<stop offset="0.33" style="stop-color:#00ACE4"/>
|
||||
<stop offset="0.9045" style="stop-color:#005093"/>
|
||||
<stop offset="0.9335" style="stop-color:#005396"/>
|
||||
<stop offset="0.954" style="stop-color:#005C9F"/>
|
||||
<stop offset="0.9718" style="stop-color:#006BAE"/>
|
||||
<stop offset="0.988" style="stop-color:#0080C4"/>
|
||||
<stop offset="1" style="stop-color:#0095DA"/>
|
||||
</radialGradient>
|
||||
<path class="st1" d="M43.5,18.5H29.2C23,17.1,15.4,17.1,10,18.2c2.4-0.3,5.1-0.3,7.8,0.1c0.7,0.1,1.3,0.2,2,0.3l0,0
|
||||
c2.9,0.5,5.7,1.2,8.1,2.2l0,0c0.3,0.1,0.5,0.2,0.8,0.3h0c0.1,0,0.2,0.1,0.3,0.1h0c0.1,0,0.2,0.1,0.3,0.1h0c0.1,0,0.2,0.1,0.2,0.1
|
||||
l0,0c0.1,0,0.1,0.1,0.2,0.1l0,0c0.1,0,0.1,0.1,0.2,0.1l0,0c0.1,0,0.2,0.1,0.2,0.1l0,0l0,0h0c0.1,0,0.1,0.1,0.2,0.1l0,0
|
||||
c0.1,0,0.1,0.1,0.2,0.1l0,0c0.1,0,0.1,0.1,0.2,0.1l0,0c0.1,0,0.1,0.1,0.2,0.1l0,0c0.1,0,0.1,0.1,0.2,0.1l0,0c0.1,0,0.1,0.1,0.2,0.1
|
||||
l0.1,0c0.1,0,0.1,0.1,0.2,0.1l0.1,0c0.1,0,0.1,0.1,0.2,0.1l0.1,0c0.1,0,0.1,0.1,0.2,0.1l0.1,0c0.1,0,0.1,0.1,0.1,0.1l0.1,0.1
|
||||
c0.1,0,0.1,0.1,0.1,0.1l0.1,0.1c0.1,0,0.1,0.1,0.1,0.1l0.1,0.1c0,0,0.1,0.1,0.1,0.1c3.2,2.2,5.1,4.9,5.1,7.6c0,3.1-2.6,5.7-6.8,7.2
|
||||
c2.9-1.5,4.6-3.6,4.6-6.1c0-3.1-2.7-6.3-7-8.7c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1-0.1-0.2-0.1
|
||||
c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1-0.1-0.2-0.1l-0.2-0.1c-0.1,0-0.2-0.1-0.2-0.1
|
||||
l-0.1-0.1c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1-0.1-0.2-0.1c-0.1,0-0.1-0.1-0.2-0.1
|
||||
L26,22c-0.1,0-0.2-0.1-0.3-0.1h0l-0.2-0.1l0,0c-0.1,0-0.2-0.1-0.3-0.1l-0.1,0c-0.1-0.1-0.2-0.1-0.4-0.1h0c-0.1,0-0.2-0.1-0.3-0.1h0
|
||||
c-0.1-0.1-0.3-0.1-0.5-0.2l-0.1,0c-0.1-0.1-0.3-0.1-0.5-0.1h0c-0.3-0.1-0.5-0.2-0.8-0.3l0,0c-0.3-0.1-0.6-0.2-0.8-0.3l0,0
|
||||
c-0.2-0.1-0.3-0.1-0.5-0.1l0,0c-0.7-0.2-1.5-0.4-2.3-0.5l0,0c-0.6-0.1-1.2-0.2-1.8-0.3v19.2c0.2,0.1,0.4,0.1,0.6,0.1
|
||||
C30.3,42,41,39.4,41.8,33.2c0.4-3.3-2-6.9-6.1-10c3.3,1.9,6,4.1,7.8,6.4c1,1.4,1.7,2.7,2,4.1c-0.1-1.9-0.9-4.8-2-6.9L43.5,18.5
|
||||
L43.5,18.5z"/>
|
||||
<g>
|
||||
<path class="st2" d="M67.5,26.9c0,1-0.2,2-0.7,2.9c-0.4,0.9-1,1.7-1.8,2.3c-0.8,0.7-1.7,1.2-2.8,1.6c-1.1,0.4-2.2,0.6-3.5,0.6H49
|
||||
v-9h4.5v5.3h5.2c0.6,0,1.2-0.1,1.7-0.3c0.5-0.2,1-0.4,1.4-0.7c0.4-0.3,0.7-0.7,0.9-1.1c0.2-0.4,0.3-0.9,0.3-1.4
|
||||
c0-0.5-0.1-1-0.3-1.4c-0.2-0.4-0.5-0.8-0.9-1.1c-0.4-0.3-0.8-0.6-1.4-0.7c-0.5-0.2-1.1-0.3-1.7-0.3H49l2.9-3.8h6.8
|
||||
c1.3,0,2.4,0.2,3.5,0.5c1.1,0.3,2,0.8,2.8,1.5s1.4,1.4,1.8,2.3C67.2,24.9,67.5,25.8,67.5,26.9z"/>
|
||||
<g>
|
||||
<path class="st2" d="M82.8,21.4v6.8l-8.9-8c-0.4-0.3-0.7-0.5-1-0.6c-0.3-0.1-0.6-0.1-0.8-0.1c-0.3,0-0.6,0.1-0.9,0.1
|
||||
c-0.3,0.1-0.6,0.3-0.8,0.5c-0.2,0.2-0.4,0.5-0.5,0.8c-0.1,0.3-0.2,0.8-0.2,1.2v12h4.1v-8.5l8.9,8c0.3,0.3,0.7,0.5,0.9,0.6
|
||||
c0.3,0.1,0.6,0.1,0.8,0.1c0.3,0,0.6-0.1,0.9-0.1c0.3-0.1,0.6-0.3,0.8-0.5c0.2-0.2,0.4-0.5,0.5-0.8c0.1-0.3,0.2-0.8,0.2-1.2V19.9
|
||||
L82.8,21.4z"/>
|
||||
</g>
|
||||
<path class="st2" d="M103,25.5c1.8,0,3.1,0.3,4,1c0.9,0.7,1.4,1.6,1.4,3c0,0.7-0.1,1.4-0.3,2c-0.2,0.6-0.6,1.1-1.1,1.5
|
||||
c-0.5,0.4-1.2,0.7-1.9,0.9c-0.8,0.2-1.7,0.3-2.8,0.3H88.7l2.9-3.7h11c0.5,0,0.9-0.1,1.2-0.3c0.3-0.2,0.4-0.4,0.4-0.8
|
||||
s-0.1-0.7-0.4-0.8c-0.3-0.2-0.6-0.2-1.2-0.2h-7.9c-0.9,0-1.8-0.1-2.4-0.3c-0.7-0.2-1.2-0.5-1.7-0.8c-0.5-0.4-0.8-0.8-1-1.3
|
||||
c-0.2-0.5-0.3-1.1-0.3-1.7c0-0.7,0.1-1.3,0.4-1.9c0.2-0.6,0.6-1,1.1-1.4c0.5-0.4,1.1-0.7,1.9-0.9c0.8-0.2,1.7-0.3,2.8-0.3h12.6
|
||||
l-2.9,3.8H95.1c-0.5,0-0.9,0.1-1.2,0.2c-0.3,0.1-0.4,0.4-0.4,0.8c0,0.4,0.1,0.6,0.4,0.8c0.3,0.1,0.6,0.2,1.2,0.2L103,25.5
|
||||
L103,25.5z"/>
|
||||
</g>
|
||||
<g class="st3">
|
||||
<path class="st4" d="M57.5,36.6v5h-1.4v-2.7v-0.7l0.1-0.4v-0.4h-0.1l-0.2,0.3l-0.2,0.3l-0.4,0.7l-1.7,2.8h-1.3l-1.7-2.8l-0.4-0.7
|
||||
l-0.2-0.3l-0.2-0.3h-0.1l0,0.4v0.4l0.1,0.7v2.7h-1.5v-5h2.4l1.4,2.3l0.4,0.7l0.2,0.3l0.2,0.3H53l0.2-0.3l0.2-0.3l0.4-0.7l1.4-2.3
|
||||
L57.5,36.6L57.5,36.6z"/>
|
||||
<path class="st4" d="M63.6,40.6h-3.3l-0.5,0.9h-1.6l2.6-5H63l2.6,5H64L63.6,40.6z M63.2,39.9l-1.3-2.6l-1.3,2.6H63.2z"/>
|
||||
<path class="st4" d="M66.2,41.6v-5H70c1,0,1.8,0.2,2.2,0.5s0.7,0.8,0.7,1.6c0,0.7,0,1.2-0.1,1.5c0,0.3-0.2,0.6-0.5,0.9
|
||||
c-0.3,0.3-1,0.5-2.3,0.5H66.2L66.2,41.6z M67.7,40.7h2.1c0.7,0,1.2-0.1,1.4-0.3s0.3-0.7,0.3-1.4c0-0.7-0.1-1.2-0.3-1.4
|
||||
s-0.6-0.3-1.3-0.3h-2.2L67.7,40.7L67.7,40.7z"/>
|
||||
<path class="st4" d="M75.3,37.4v1.3h3.6v0.7h-3.6v1.4h3.8v0.8h-5.3v-5h5.3v0.8L75.3,37.4L75.3,37.4z"/>
|
||||
<path class="st4" d="M84.4,37.4v1.3H88v0.7h-3.6v1.4h3.8v0.8H83v-5h5.3v0.8L84.4,37.4L84.4,37.4z"/>
|
||||
<path class="st4" d="M94,40.6h-3.3l-0.5,0.9h-1.6l2.6-5h2.2l2.6,5h-1.5L94,40.6z M93.7,39.9l-1.3-2.6L91,39.9H93.7z"/>
|
||||
<path class="st4" d="M102.4,38.1H101v-0.1c0-0.3-0.1-0.4-0.3-0.5c-0.2-0.1-0.6-0.1-1.2-0.1c-0.7,0-1.2,0-1.4,0.1
|
||||
c-0.2,0.1-0.3,0.3-0.3,0.5c0,0.3,0.1,0.5,0.3,0.6s0.8,0.1,1.7,0.1c1.1,0,1.9,0.1,2.2,0.3c0.3,0.2,0.5,0.5,0.5,1.1
|
||||
c0,0.7-0.2,1.1-0.6,1.3s-1.2,0.3-2.5,0.3c-1.3,0-2.2-0.1-2.5-0.3c-0.4-0.2-0.6-0.6-0.6-1.2V40h1.4v0.1c0,0.3,0.1,0.5,0.3,0.6
|
||||
c0.2,0.1,0.7,0.1,1.5,0.1c0.7,0,1.1,0,1.2-0.1s0.3-0.3,0.3-0.6c0-0.3-0.1-0.4-0.2-0.5c-0.1-0.1-0.4-0.1-0.9-0.1l-0.8,0
|
||||
c-1.2,0-2-0.1-2.3-0.3c-0.4-0.2-0.5-0.6-0.5-1.1c0-0.6,0.2-1,0.6-1.2c0.4-0.2,1.2-0.3,2.5-0.3c1.1,0,1.9,0.1,2.3,0.3
|
||||
c0.4,0.2,0.6,0.5,0.6,1L102.4,38.1L102.4,38.1z"/>
|
||||
<path class="st4" d="M110,36.6l-2.9,3.1v1.9h-1.5v-1.9l-2.8-3.1h1.7l1.2,1.3l0.3,0.4l0.2,0.2l0.2,0.2l0.2-0.2l0.2-0.2l0.3-0.4
|
||||
l1.2-1.3H110z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
@@ -289,7 +289,7 @@
|
||||
}
|
||||
},
|
||||
"project": {
|
||||
"title": "Settings",
|
||||
"title": "Project Settings",
|
||||
"description": "These settings only apply to the currently selected Project.",
|
||||
"danger-zone": "Danger Zone",
|
||||
"delete-project": "Delete Project",
|
||||
|
||||
@@ -20,9 +20,14 @@ export default function TeamInviteStep(): JSX.Element {
|
||||
const { mutateAsync } = useAddUsersToOrg();
|
||||
const { handlePopUpToggle, popUp, handlePopUpOpen } = usePopUp(["setUpEmail"] as const);
|
||||
|
||||
const orgId = String(localStorage.getItem("orgData.id"));
|
||||
|
||||
// Redirect user to the getting started page
|
||||
const redirectToHome = async () => {
|
||||
navigate({ to: "/organization/projects" as const });
|
||||
navigate({
|
||||
to: orgId ? ("/organizations/$orgId/projects" as const) : "/",
|
||||
params: { orgId }
|
||||
});
|
||||
};
|
||||
|
||||
const inviteUsers = async ({ emails: inviteEmails }: { emails: string }) => {
|
||||
@@ -32,7 +37,7 @@ export default function TeamInviteStep(): JSX.Element {
|
||||
.map(async (email) => {
|
||||
mutateAsync({
|
||||
inviteeEmails: [email],
|
||||
organizationId: String(localStorage.getItem("orgData.id")),
|
||||
organizationId: orgId,
|
||||
organizationRoleSlug: "member"
|
||||
});
|
||||
});
|
||||
|
||||
@@ -70,7 +70,8 @@ export default function NavHeader({
|
||||
{currentOrg?.name?.charAt(0)}
|
||||
</div>
|
||||
<Link
|
||||
to="/organization/projects"
|
||||
to="/organizations/$orgId/projects"
|
||||
params={{ orgId: currentOrg.id }}
|
||||
className="truncate pl-0.5 text-sm font-medium text-primary/80 hover:text-primary"
|
||||
>
|
||||
{currentOrg?.name}
|
||||
@@ -90,8 +91,8 @@ export default function NavHeader({
|
||||
<FontAwesomeIcon icon={faAngleRight} className="mr-3 ml-3 text-sm text-gray-400" />
|
||||
{pageName === "Secrets" ? (
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/overview"
|
||||
params={{ projectId: currentProject.id }}
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/overview"
|
||||
params={{ orgId: currentOrg?.id || "", projectId: currentProject.id }}
|
||||
className="text-sm font-medium text-primary/80 hover:text-primary"
|
||||
>
|
||||
{pageName}
|
||||
@@ -126,8 +127,8 @@ export default function NavHeader({
|
||||
<div className="flex items-center space-x-3">
|
||||
<FontAwesomeIcon icon={faAngleRight} className="mr-1.5 ml-3 text-xs text-gray-400" />
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/secrets/$envSlug"
|
||||
params={{ projectId: currentProject.id, envSlug: routerEnvSlug }}
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/secrets/$envSlug"
|
||||
params={{ orgId: currentOrg.id, projectId: currentProject.id, envSlug: routerEnvSlug }}
|
||||
className="text-sm font-medium text-primary/80 hover:text-primary"
|
||||
>
|
||||
{userAvailableEnvs?.find(({ slug }) => slug === currentEnv)?.name}
|
||||
@@ -188,8 +189,9 @@ export default function NavHeader({
|
||||
</div>
|
||||
) : (
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/secrets/$envSlug"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/secrets/$envSlug"
|
||||
params={{
|
||||
orgId: currentOrg?.id || "",
|
||||
projectId: currentProject.id,
|
||||
envSlug: routerEnvSlug || ""
|
||||
}}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { useOrganization } from "@app/context";
|
||||
import { useTimedReset } from "@app/hooks";
|
||||
|
||||
import { createNotification } from "../notifications";
|
||||
@@ -23,6 +24,7 @@ export const SecretDashboardPathBreadcrumb = ({
|
||||
projectId,
|
||||
disableCopy
|
||||
}: Props) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const [, isCopying, setIsCopying] = useTimedReset({
|
||||
initialState: false
|
||||
});
|
||||
@@ -69,8 +71,9 @@ export const SecretDashboardPathBreadcrumb = ({
|
||||
</div>
|
||||
) : (
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/secrets/$envSlug"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/secrets/$envSlug"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId,
|
||||
envSlug: environmentSlug
|
||||
}}
|
||||
|
||||
@@ -57,7 +57,8 @@ export const CreateOrgModal: FC<CreateOrgModalProps> = ({ isOpen, onClose }) =>
|
||||
});
|
||||
|
||||
navigate({
|
||||
to: "/organization/projects"
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId: organization.id }
|
||||
});
|
||||
|
||||
localStorage.setItem("orgData.id", organization.id);
|
||||
|
||||
@@ -87,17 +87,24 @@ const shouldShowConditionalAccess = (
|
||||
folderPath: string,
|
||||
conditionalFields: string[]
|
||||
): boolean => {
|
||||
return actionRuleMap.some((rule) => {
|
||||
// Find all rules that apply to this environment/path
|
||||
const applicableRules = actionRuleMap.filter((rule) => {
|
||||
const ruleConditions = rule[action]?.conditions;
|
||||
if (!ruleConditions) return false;
|
||||
|
||||
// Check if any of the conditional fields are present
|
||||
const hasConditionalField = conditionalFields.some((field) => ruleConditions[field]);
|
||||
if (!hasConditionalField) return false;
|
||||
|
||||
// Check if base conditions (environment and secretPath) apply
|
||||
return doBaseConditionsApply(ruleConditions, environment, folderPath);
|
||||
});
|
||||
|
||||
// If no rules apply, don't show conditional
|
||||
if (applicableRules.length === 0) return false;
|
||||
|
||||
// Check if ALL applicable rules have conditional fields and if at least one rule applies without conditional fields, show full access
|
||||
const allRulesHaveConditionalFields = applicableRules.every((rule) => {
|
||||
const ruleConditions = rule[action]?.conditions;
|
||||
if (!ruleConditions) return false;
|
||||
return conditionalFields.some((field) => ruleConditions[field]);
|
||||
});
|
||||
|
||||
return allRulesHaveConditionalFields;
|
||||
};
|
||||
|
||||
const determineAccessLevel = (
|
||||
|
||||
@@ -157,7 +157,7 @@ const NewProjectForm = ({ onOpenChange }: NewProjectFormProps) => {
|
||||
onOpenChange(false);
|
||||
navigate({
|
||||
to: getProjectHomePage(project.type, project.environments),
|
||||
params: { projectId: project.id }
|
||||
params: { projectId: project.id, orgId: currentOrg.id }
|
||||
});
|
||||
};
|
||||
const onSubmit = handleSubmit((data) => {
|
||||
|
||||
@@ -3,14 +3,7 @@ import { ReactNode } from "@tanstack/react-router";
|
||||
import { LucideIcon } from "lucide-react";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import {
|
||||
Badge,
|
||||
InstanceIcon,
|
||||
OrgIcon,
|
||||
ProjectIcon,
|
||||
SubOrgIcon,
|
||||
TBadgeProps
|
||||
} from "@app/components/v3";
|
||||
import { InstanceIcon, OrgIcon, ProjectIcon, SubOrgIcon } from "@app/components/v3";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
|
||||
type Props = {
|
||||
@@ -21,41 +14,40 @@ type Props = {
|
||||
scope: "org" | "namespace" | "instance" | ProjectType | null;
|
||||
};
|
||||
|
||||
const SCOPE_NAME: Record<NonNullable<Props["scope"]>, { label: string; icon: LucideIcon }> = {
|
||||
org: { label: "Organization", icon: OrgIcon },
|
||||
[ProjectType.SecretManager]: { label: "Project", icon: ProjectIcon },
|
||||
[ProjectType.CertificateManager]: { label: "Project", icon: ProjectIcon },
|
||||
[ProjectType.SSH]: { label: "Project", icon: ProjectIcon },
|
||||
[ProjectType.KMS]: { label: "Project", icon: ProjectIcon },
|
||||
[ProjectType.PAM]: { label: "Project", icon: ProjectIcon },
|
||||
[ProjectType.SecretScanning]: { label: "Project", icon: ProjectIcon },
|
||||
namespace: { label: "Sub-Organization", icon: SubOrgIcon },
|
||||
instance: { label: "Server", icon: InstanceIcon }
|
||||
};
|
||||
|
||||
const SCOPE_VARIANT: Record<NonNullable<Props["scope"]>, TBadgeProps["variant"]> = {
|
||||
org: "org",
|
||||
[ProjectType.SecretManager]: "project",
|
||||
[ProjectType.CertificateManager]: "project",
|
||||
[ProjectType.SSH]: "project",
|
||||
[ProjectType.KMS]: "project",
|
||||
[ProjectType.PAM]: "project",
|
||||
[ProjectType.SecretScanning]: "project",
|
||||
namespace: "sub-org",
|
||||
instance: "neutral"
|
||||
const SCOPE_BADGE: Record<NonNullable<Props["scope"]>, { icon: LucideIcon; className: string }> = {
|
||||
org: { className: "text-org", icon: OrgIcon },
|
||||
[ProjectType.SecretManager]: { className: "text-project", icon: ProjectIcon },
|
||||
[ProjectType.CertificateManager]: { className: "text-project", icon: ProjectIcon },
|
||||
[ProjectType.SSH]: { className: "text-project", icon: ProjectIcon },
|
||||
[ProjectType.KMS]: { className: "text-project", icon: ProjectIcon },
|
||||
[ProjectType.PAM]: { className: "text-project", icon: ProjectIcon },
|
||||
[ProjectType.SecretScanning]: { className: "text-project", icon: ProjectIcon },
|
||||
namespace: { className: "text-sub-org", icon: SubOrgIcon },
|
||||
instance: { className: "text-neutral", icon: InstanceIcon }
|
||||
};
|
||||
|
||||
export const PageHeader = ({ title, description, children, className, scope }: Props) => (
|
||||
<div className={twMerge("mb-10 w-full", className)}>
|
||||
<div className="flex w-full justify-between">
|
||||
<div className="mr-4 flex w-full items-center">
|
||||
<h1 className="text-3xl font-medium text-white capitalize">{title}</h1>
|
||||
{scope && (
|
||||
<Badge variant={SCOPE_VARIANT[scope]} className="mt-1 ml-2.5">
|
||||
{createElement(SCOPE_NAME[scope].icon)}
|
||||
{SCOPE_NAME[scope].label}
|
||||
</Badge>
|
||||
)}
|
||||
<h1
|
||||
className={twMerge(
|
||||
"text-3xl font-medium text-white capitalize underline decoration-2 underline-offset-4",
|
||||
scope === "org" && "decoration-org/90",
|
||||
scope === "instance" && "decoration-neutral/90",
|
||||
scope === "namespace" && "decoration-sub-org/90",
|
||||
Object.values(ProjectType).includes((scope as ProjectType) ?? "") &&
|
||||
"decoration-project/90",
|
||||
!scope && "no-underline"
|
||||
)}
|
||||
>
|
||||
{scope &&
|
||||
createElement(SCOPE_BADGE[scope].icon, {
|
||||
size: 26,
|
||||
className: twMerge(SCOPE_BADGE[scope].className, "mr-3 mb-1 inline-block")
|
||||
})}
|
||||
{title}
|
||||
</h1>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">{children}</div>
|
||||
</div>
|
||||
|
||||
@@ -47,8 +47,8 @@ export const Tab = ({
|
||||
}) => (
|
||||
<TabsPrimitive.Trigger
|
||||
className={twMerge(
|
||||
"flex h-10 cursor-pointer items-center justify-center border-transparent",
|
||||
"px-3 text-sm font-medium whitespace-nowrap text-mineshaft-400 transition-all select-none",
|
||||
"flex h-11 cursor-pointer items-center justify-center border-transparent",
|
||||
"px-3 text-sm font-medium whitespace-nowrap text-mineshaft-300/75 transition-all select-none",
|
||||
"data-[orientation=vertical]:xl:h-5 data-[orientation=vertical]:xl:border-b-0 data-[orientation=vertical]:xl:border-l",
|
||||
"border-b hover:text-mineshaft-200",
|
||||
"data-[state=active]:border-mineshaft-400 data-[state=active]:text-white",
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { BookOpenIcon } from "lucide-react";
|
||||
import { ExternalLinkIcon } from "lucide-react";
|
||||
|
||||
import { Badge } from "@app/components/v3";
|
||||
|
||||
@@ -8,10 +8,10 @@ type TDocumentationLinkBadgeProps = {
|
||||
|
||||
export function DocumentationLinkBadge({ href }: TDocumentationLinkBadgeProps) {
|
||||
return (
|
||||
<Badge variant="neutral" asChild>
|
||||
<Badge variant="info" asChild>
|
||||
<a href={href} target="_blank" rel="noopener noreferrer">
|
||||
<BookOpenIcon />
|
||||
Documentation
|
||||
<ExternalLinkIcon />
|
||||
</a>
|
||||
</Badge>
|
||||
);
|
||||
|
||||
+162
-162
@@ -25,343 +25,343 @@ export const ROUTE_PATHS = Object.freeze({
|
||||
Organization: {
|
||||
Settings: {
|
||||
OauthCallbackPage: setRoute(
|
||||
"/organization/settings/oauth/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/settings/oauth/callback"
|
||||
"/organizations/$orgId/settings/oauth/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/settings/oauth/callback"
|
||||
)
|
||||
},
|
||||
SecretSharing: setRoute(
|
||||
"/organization/secret-sharing",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/secret-sharing/"
|
||||
"/organizations/$orgId/secret-sharing",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/secret-sharing/"
|
||||
),
|
||||
SettingsPage: setRoute(
|
||||
"/organization/settings",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/settings/"
|
||||
"/organizations/$orgId/settings",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/settings/"
|
||||
),
|
||||
GroupDetailsByIDPage: setRoute(
|
||||
"/organization/groups/$groupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/groups/$groupId"
|
||||
"/organizations/$orgId/groups/$groupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/groups/$groupId"
|
||||
),
|
||||
IdentityDetailsByIDPage: setRoute(
|
||||
"/organization/identities/$identityId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/identities/$identityId"
|
||||
"/organizations/$orgId/identities/$identityId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/identities/$identityId"
|
||||
),
|
||||
UserDetailsByIDPage: setRoute(
|
||||
"/organization/members/$membershipId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/members/$membershipId"
|
||||
"/organizations/$orgId/members/$membershipId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/members/$membershipId"
|
||||
),
|
||||
AccessControlPage: setRoute(
|
||||
"/organization/access-management",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/access-management"
|
||||
"/organizations/$orgId/access-management",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/access-management"
|
||||
),
|
||||
RoleByIDPage: setRoute(
|
||||
"/organization/roles/$roleId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/roles/$roleId"
|
||||
"/organizations/$orgId/roles/$roleId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/roles/$roleId"
|
||||
),
|
||||
AppConnections: {
|
||||
OauthCallbackPage: setRoute(
|
||||
"/organization/app-connections/$appConnection/oauth/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/app-connections/$appConnection/oauth/callback"
|
||||
"/organizations/$orgId/app-connections/$appConnection/oauth/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/app-connections/$appConnection/oauth/callback"
|
||||
)
|
||||
},
|
||||
NetworkingPage: setRoute(
|
||||
"/organization/networking",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/networking"
|
||||
"/organizations/$orgId/networking",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/networking"
|
||||
)
|
||||
},
|
||||
SecretManager: {
|
||||
ApprovalPage: setRoute(
|
||||
"/projects/secret-management/$projectId/approval",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/approval"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/approval",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/approval"
|
||||
),
|
||||
SecretDashboardPage: setRoute(
|
||||
"/projects/secret-management/$projectId/secrets/$envSlug",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/secrets/$envSlug"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/secrets/$envSlug",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/secrets/$envSlug"
|
||||
),
|
||||
RollbackPreviewPage: setRoute(
|
||||
"/projects/secret-management/$projectId/commits/$environment/$folderId/$commitId/restore",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/commits/$environment/$folderId/$commitId/restore"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/commits/$environment/$folderId/$commitId/restore",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/commits/$environment/$folderId/$commitId/restore"
|
||||
),
|
||||
CommitDetailsPage: setRoute(
|
||||
"/projects/secret-management/$projectId/commits/$environment/$folderId/$commitId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/commits/$environment/$folderId/$commitId"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/commits/$environment/$folderId/$commitId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/commits/$environment/$folderId/$commitId"
|
||||
),
|
||||
CommitsPage: setRoute(
|
||||
"/projects/secret-management/$projectId/commits/$environment/$folderId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/commits/$environment/$folderId"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/commits/$environment/$folderId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/commits/$environment/$folderId"
|
||||
),
|
||||
OverviewPage: setRoute(
|
||||
"/projects/secret-management/$projectId/overview",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/overview"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/overview",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/overview"
|
||||
),
|
||||
IntegrationsListPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/"
|
||||
),
|
||||
IntegrationDetailsByIDPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/$integrationId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/$integrationId"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/$integrationId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/$integrationId"
|
||||
),
|
||||
SecretSyncDetailsByIDPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/secret-syncs/$destination/$syncId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/secret-syncs/$destination/$syncId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/secret-syncs/$destination/$syncId"
|
||||
),
|
||||
Integratons: {
|
||||
SelectIntegrationAuth: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/select-integration-auth",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/select-integration-auth"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/select-integration-auth",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/select-integration-auth"
|
||||
),
|
||||
HerokuOauthCallbackPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/heroku/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/heroku/oauth2/callback"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/heroku/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/heroku/oauth2/callback"
|
||||
),
|
||||
HerokuConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/heroku/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/heroku/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/heroku/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/heroku/create"
|
||||
),
|
||||
AwsParameterStoreConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/aws-parameter-store/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/aws-parameter-store/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/aws-parameter-store/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/aws-parameter-store/create"
|
||||
),
|
||||
AwsSecretManagerConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/aws-secret-manager/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/aws-secret-manager/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/aws-secret-manager/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/aws-secret-manager/create"
|
||||
),
|
||||
AzureAppConfigurationsOauthCallbackPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/azure-app-configuration/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-app-configuration/oauth2/callback"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/azure-app-configuration/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-app-configuration/oauth2/callback"
|
||||
),
|
||||
AzureAppConfigurationsConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/azure-app-configuration/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-app-configuration/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/azure-app-configuration/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-app-configuration/create"
|
||||
),
|
||||
AzureDevopsConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/azure-devops/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-devops/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/azure-devops/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-devops/create"
|
||||
),
|
||||
AzureKeyVaultAuthorizePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/azure-key-vault/authorize",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/azure-key-vault/authorize",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-key-vault/authorize"
|
||||
),
|
||||
AzureKeyVaultOauthCallbackPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/azure-key-vault/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-key-vault/oauth2/callback"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/azure-key-vault/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-key-vault/oauth2/callback"
|
||||
),
|
||||
AzureKeyVaultConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/azure-key-vault/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-key-vault/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/azure-key-vault/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/azure-key-vault/create"
|
||||
),
|
||||
BitbucketOauthCallbackPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/bitbucket/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/bitbucket/oauth2/callback"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/bitbucket/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/bitbucket/oauth2/callback"
|
||||
),
|
||||
BitbucketConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/bitbucket/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/bitbucket/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/bitbucket/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/bitbucket/create"
|
||||
),
|
||||
ChecklyConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/checkly/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/checkly/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/checkly/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/checkly/create"
|
||||
),
|
||||
CircleConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/circleci/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/circleci/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/circleci/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/circleci/create"
|
||||
),
|
||||
CloudflarePagesConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/cloudflare-pages/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/cloudflare-pages/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/cloudflare-pages/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/cloudflare-pages/create"
|
||||
),
|
||||
DigitalOceanAppPlatformConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/digital-ocean-app-platform/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/digital-ocean-app-platform/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/digital-ocean-app-platform/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/digital-ocean-app-platform/create"
|
||||
),
|
||||
CloudflareWorkersConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/cloudflare-workers/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/cloudflare-workers/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/cloudflare-workers/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/cloudflare-workers/create"
|
||||
),
|
||||
CodefreshConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/codefresh/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/codefresh/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/codefresh/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/codefresh/create"
|
||||
),
|
||||
GcpSecretManagerConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/gcp-secret-manager/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/gcp-secret-manager/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/gcp-secret-manager/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/gcp-secret-manager/create"
|
||||
),
|
||||
GcpSecretManagerOauthCallbackPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/gcp-secret-manager/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/gcp-secret-manager/oauth2/callback"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/gcp-secret-manager/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/gcp-secret-manager/oauth2/callback"
|
||||
),
|
||||
GithubConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/github/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/github/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/github/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/github/create"
|
||||
),
|
||||
GithubOauthCallbackPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/github/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/github/oauth2/callback"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/github/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/github/oauth2/callback"
|
||||
),
|
||||
GitlabConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/gitlab/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/gitlab/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/gitlab/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/gitlab/create"
|
||||
),
|
||||
GitlabOauthCallbackPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/gitlab/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/gitlab/oauth2/callback"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/gitlab/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/gitlab/oauth2/callback"
|
||||
),
|
||||
VercelOauthCallbackPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/vercel/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/vercel/oauth2/callback"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/vercel/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/vercel/oauth2/callback"
|
||||
),
|
||||
VercelConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/vercel/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/vercel/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/vercel/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/vercel/create"
|
||||
),
|
||||
FlyioConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/flyio/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/flyio/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/flyio/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/flyio/create"
|
||||
),
|
||||
HashicorpVaultConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/hashicorp-vault/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/hashicorp-vault/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/hashicorp-vault/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/hashicorp-vault/create"
|
||||
),
|
||||
HasuraCloudConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/hasura-cloud/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/hasura-cloud/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/hasura-cloud/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/hasura-cloud/create"
|
||||
),
|
||||
LaravelForgeConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/laravel-forge/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/laravel-forge/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/laravel-forge/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/laravel-forge/create"
|
||||
),
|
||||
NorthflankConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/northflank/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/northflank/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/northflank/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/northflank/create"
|
||||
),
|
||||
RailwayConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/railway/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/railway/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/railway/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/railway/create"
|
||||
),
|
||||
RenderConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/render/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/render/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/render/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/render/create"
|
||||
),
|
||||
RundeckConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/rundeck/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/rundeck/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/rundeck/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/rundeck/create"
|
||||
),
|
||||
WindmillConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/windmill/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/windmill/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/windmill/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/windmill/create"
|
||||
),
|
||||
TravisCIConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/travisci/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/travisci/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/travisci/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/travisci/create"
|
||||
),
|
||||
TerraformCloudConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/terraform-cloud/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/terraform-cloud/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/terraform-cloud/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/terraform-cloud/create"
|
||||
),
|
||||
TeamcityConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/teamcity/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/teamcity/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/teamcity/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/teamcity/create"
|
||||
),
|
||||
SupabaseConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/supabase/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/supabase/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/supabase/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/supabase/create"
|
||||
),
|
||||
OctopusDeployCloudConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/octopus-deploy/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/octopus-deploy/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/octopus-deploy/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/octopus-deploy/create"
|
||||
),
|
||||
DatabricksConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/databricks/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/databricks/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/databricks/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/databricks/create"
|
||||
),
|
||||
QoveryConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/qovery/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/qovery/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/qovery/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/qovery/create"
|
||||
),
|
||||
Cloud66ConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/cloud-66/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/cloud-66/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/cloud-66/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/cloud-66/create"
|
||||
),
|
||||
NetlifyConfigurePage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/netlify/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/netlify/create"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/netlify/create",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/netlify/create"
|
||||
),
|
||||
NetlifyOuathCallbackPage: setRoute(
|
||||
"/projects/secret-management/$projectId/integrations/netlify/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/integrations/netlify/oauth2/callback"
|
||||
"/organizations/$orgId/projects/secret-management/$projectId/integrations/netlify/oauth2/callback",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-management/$projectId/_secret-manager-layout/integrations/netlify/oauth2/callback"
|
||||
)
|
||||
}
|
||||
},
|
||||
CertManager: {
|
||||
CertAuthDetailsByIDPage: setRoute(
|
||||
"/projects/cert-management/$projectId/ca/$caName",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName"
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/ca/$caId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId"
|
||||
),
|
||||
SubscribersPage: setRoute(
|
||||
"/projects/cert-management/$projectId/subscribers",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/subscribers"
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/subscribers",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/subscribers"
|
||||
),
|
||||
CertificateAuthoritiesPage: setRoute(
|
||||
"/projects/cert-management/$projectId/certificate-authorities",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/certificate-authorities"
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/certificate-authorities",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/certificate-authorities"
|
||||
),
|
||||
AlertingPage: setRoute(
|
||||
"/projects/cert-management/$projectId/alerting",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/alerting"
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/alerting",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/alerting"
|
||||
),
|
||||
PkiCollectionDetailsByIDPage: setRoute(
|
||||
"/projects/cert-management/$projectId/pki-collections/$collectionId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/pki-collections/$collectionId"
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/pki-collections/$collectionId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/pki-collections/$collectionId"
|
||||
),
|
||||
PkiSubscriberDetailsByIDPage: setRoute(
|
||||
"/projects/cert-management/$projectId/subscribers/$subscriberName",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/subscribers/$subscriberName"
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/subscribers/$subscriberName",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/subscribers/$subscriberName"
|
||||
),
|
||||
IntegrationsListPage: setRoute(
|
||||
"/projects/cert-management/$projectId/integrations",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/integrations/"
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/integrations",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/integrations/"
|
||||
),
|
||||
PkiSyncDetailsByIDPage: setRoute(
|
||||
"/projects/cert-management/$projectId/integrations/$syncId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/integrations/$syncId"
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/integrations/$syncId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/integrations/$syncId"
|
||||
)
|
||||
},
|
||||
Ssh: {
|
||||
SshCaByIDPage: setRoute(
|
||||
"/projects/ssh/$projectId/ca/$caId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/ssh/$projectId/_ssh-layout/ca/$caId"
|
||||
"/organizations/$orgId/projects/ssh/$projectId/ca/$caId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/ssh/$projectId/_ssh-layout/ca/$caId"
|
||||
),
|
||||
SshHostGroupDetailsByIDPage: setRoute(
|
||||
"/projects/ssh/$projectId/ssh-host-groups/$sshHostGroupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/ssh/$projectId/_ssh-layout/ssh-host-groups/$sshHostGroupId"
|
||||
"/organizations/$orgId/projects/ssh/$projectId/ssh-host-groups/$sshHostGroupId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/ssh/$projectId/_ssh-layout/ssh-host-groups/$sshHostGroupId"
|
||||
)
|
||||
},
|
||||
SecretScanning: {
|
||||
DataSourceByIdPage: setRoute(
|
||||
"/projects/secret-scanning/$projectId/data-sources/$type/$dataSourceId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-scanning/$projectId/_secret-scanning-layout/data-sources/$type/$dataSourceId"
|
||||
"/organizations/$orgId/projects/secret-scanning/$projectId/data-sources/$type/$dataSourceId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-scanning/$projectId/_secret-scanning-layout/data-sources/$type/$dataSourceId"
|
||||
),
|
||||
FindingsPage: setRoute(
|
||||
"/projects/secret-scanning/$projectId/findings",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/secret-scanning/$projectId/_secret-scanning-layout/findings"
|
||||
"/organizations/$orgId/projects/secret-scanning/$projectId/findings",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/secret-scanning/$projectId/_secret-scanning-layout/findings"
|
||||
)
|
||||
},
|
||||
Pam: {
|
||||
AccountsPage: setRoute(
|
||||
"/projects/pam/$projectId/accounts",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/pam/$projectId/_pam-layout/accounts"
|
||||
"/organizations/$orgId/projects/pam/$projectId/accounts",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/accounts"
|
||||
),
|
||||
ResourcesPage: setRoute(
|
||||
"/projects/pam/$projectId/resources",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/pam/$projectId/_pam-layout/resources"
|
||||
"/organizations/$orgId/projects/pam/$projectId/resources",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/resources"
|
||||
),
|
||||
SessionsPage: setRoute(
|
||||
"/projects/pam/$projectId/sessions",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/pam/$projectId/_pam-layout/sessions/"
|
||||
"/organizations/$orgId/projects/pam/$projectId/sessions",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/"
|
||||
),
|
||||
PamSessionByIDPage: setRoute(
|
||||
"/projects/pam/$projectId/sessions/$sessionId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/pam/$projectId/_pam-layout/sessions/$sessionId"
|
||||
"/organizations/$orgId/projects/pam/$projectId/sessions/$sessionId",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/pam/$projectId/_pam-layout/sessions/$sessionId"
|
||||
)
|
||||
},
|
||||
Public: {
|
||||
|
||||
@@ -50,6 +50,7 @@ import { BitbucketConnectionMethod } from "@app/hooks/api/appConnections/types/b
|
||||
import { ChecklyConnectionMethod } from "@app/hooks/api/appConnections/types/checkly-connection";
|
||||
import { ChefConnectionMethod } from "@app/hooks/api/appConnections/types/chef-connection";
|
||||
import { DigitalOceanConnectionMethod } from "@app/hooks/api/appConnections/types/digital-ocean";
|
||||
import { DNSMadeEasyConnectionMethod } from "@app/hooks/api/appConnections/types/dns-made-easy-connection";
|
||||
import { HerokuConnectionMethod } from "@app/hooks/api/appConnections/types/heroku-connection";
|
||||
import { LaravelForgeConnectionMethod } from "@app/hooks/api/appConnections/types/laravel-forge-connection";
|
||||
import { NetlifyConnectionMethod } from "@app/hooks/api/appConnections/types/netlify-connection";
|
||||
@@ -112,6 +113,7 @@ export const APP_CONNECTION_MAP: Record<
|
||||
[AppConnection.Flyio]: { name: "Fly.io", image: "Flyio.svg" },
|
||||
[AppConnection.GitLab]: { name: "GitLab", image: "GitLab.png" },
|
||||
[AppConnection.Cloudflare]: { name: "Cloudflare", image: "Cloudflare.png" },
|
||||
[AppConnection.DNSMadeEasy]: { name: "DNS Made Easy", image: "DNSMadeEasy.svg", size: 120 },
|
||||
[AppConnection.Zabbix]: { name: "Zabbix", image: "Zabbix.png" },
|
||||
[AppConnection.Railway]: { name: "Railway", image: "Railway.png" },
|
||||
[AppConnection.Bitbucket]: { name: "Bitbucket", image: "Bitbucket.png" },
|
||||
@@ -217,6 +219,8 @@ export const getAppConnectionMethodDetails = (method: TAppConnection["method"])
|
||||
return { name: "Client Secret", icon: faKey };
|
||||
case AzureClientSecretsConnectionMethod.Certificate:
|
||||
return { name: "Certificate", icon: faCertificate };
|
||||
case DNSMadeEasyConnectionMethod.APIKeySecret:
|
||||
return { name: "API Key & Secret", icon: faKey };
|
||||
default:
|
||||
throw new Error(`Unhandled App Connection Method: ${method}`);
|
||||
}
|
||||
|
||||
@@ -14,11 +14,6 @@ const secretsToBeAdded = [
|
||||
secretValue: "OVERRIDE_THIS",
|
||||
secretComment: "Override secrets with personal value"
|
||||
},
|
||||
{
|
||||
secretKey: "DB_PASSWORD",
|
||||
secretValue: "OVERRIDE_THIS",
|
||||
secretComment: "Another secret override"
|
||||
},
|
||||
{
|
||||
secretKey: "DB_PASSWORD",
|
||||
secretValue: "example_password"
|
||||
@@ -64,11 +59,11 @@ export const initProjectHelper = async ({ projectName }: { projectName: string }
|
||||
export const getProjectBaseURL = (type: ProjectType) => {
|
||||
switch (type) {
|
||||
case ProjectType.SecretManager:
|
||||
return "/projects/secret-management/$projectId";
|
||||
return "/organizations/$orgId/projects/secret-management/$projectId";
|
||||
case ProjectType.CertificateManager:
|
||||
return "/projects/cert-management/$projectId";
|
||||
return "/organizations/$orgId/projects/cert-management/$projectId";
|
||||
default:
|
||||
return `/projects/${type}/$projectId` as const;
|
||||
return `/organizations/$orgId/projects/${type}/$projectId` as const;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -77,15 +72,15 @@ export const getProjectBaseURL = (type: ProjectType) => {
|
||||
export const getProjectHomePage = (type: ProjectType, environments: ProjectEnv[]) => {
|
||||
switch (type) {
|
||||
case ProjectType.SecretManager:
|
||||
return "/projects/secret-management/$projectId/overview" as const;
|
||||
return "/organizations/$orgId/projects/secret-management/$projectId/overview" as const;
|
||||
case ProjectType.CertificateManager:
|
||||
return "/projects/cert-management/$projectId/policies" as const;
|
||||
return "/organizations/$orgId/projects/cert-management/$projectId/policies" as const;
|
||||
case ProjectType.SecretScanning:
|
||||
return `/projects/${type}/$projectId/data-sources` as const;
|
||||
return `/organizations/$orgId/projects/${type}/$projectId/data-sources` as const;
|
||||
case ProjectType.PAM:
|
||||
return `/projects/${type}/$projectId/accounts` as const;
|
||||
return `/organizations/$orgId/projects/${type}/$projectId/accounts` as const;
|
||||
default:
|
||||
return `/projects/${type}/$projectId/overview` as const;
|
||||
return `/organizations/$orgId/projects/${type}/$projectId/overview` as const;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from "./queries";
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,37 @@
|
||||
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { appConnectionKeys } from "../queries";
|
||||
import { TDNSMadeEasyZone } from "./types";
|
||||
|
||||
const dnsMadeEasyConnectionKeys = {
|
||||
all: [...appConnectionKeys.all, "dns-made-easy"] as const,
|
||||
listZones: (connectionId: string) =>
|
||||
[...dnsMadeEasyConnectionKeys.all, "zones", connectionId] as const
|
||||
};
|
||||
|
||||
export const useDNSMadeEasyConnectionListZones = (
|
||||
connectionId: string,
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
TDNSMadeEasyZone[],
|
||||
unknown,
|
||||
TDNSMadeEasyZone[],
|
||||
ReturnType<typeof dnsMadeEasyConnectionKeys.listZones>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: dnsMadeEasyConnectionKeys.listZones(connectionId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<TDNSMadeEasyZone[]>(
|
||||
`/api/v1/app-connections/dns-made-easy/${connectionId}/dns-made-easy-zones`
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
...options
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
export type TDNSMadeEasyZone = {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
@@ -29,6 +29,7 @@ export enum AppConnection {
|
||||
Flyio = "flyio",
|
||||
GitLab = "gitlab",
|
||||
Cloudflare = "cloudflare",
|
||||
DNSMadeEasy = "dns-made-easy",
|
||||
Bitbucket = "bitbucket",
|
||||
Zabbix = "zabbix",
|
||||
Railway = "railway",
|
||||
|
||||
@@ -188,6 +188,10 @@ export type TMongoDBConnectionOption = TAppConnectionOptionBase & {
|
||||
app: AppConnection.MongoDB;
|
||||
};
|
||||
|
||||
export type TDNSMadeEasyConnectionOption = TAppConnectionOptionBase & {
|
||||
app: AppConnection.DNSMadeEasy;
|
||||
};
|
||||
|
||||
export type TAppConnectionOption =
|
||||
| TAwsConnectionOption
|
||||
| TGitHubConnectionOption
|
||||
@@ -231,7 +235,8 @@ export type TAppConnectionOption =
|
||||
| TLaravelForgeConnectionOption
|
||||
| TRedisConnectionOption
|
||||
| TMongoDBConnectionOption
|
||||
| TChefConnectionOption;
|
||||
| TChefConnectionOption
|
||||
| TDNSMadeEasyConnectionOption;
|
||||
|
||||
export type TAppConnectionOptionMap = {
|
||||
[AppConnection.AWS]: TAwsConnectionOption;
|
||||
@@ -263,6 +268,7 @@ export type TAppConnectionOptionMap = {
|
||||
[AppConnection.Flyio]: TFlyioConnectionOption;
|
||||
[AppConnection.GitLab]: TGitlabConnectionOption;
|
||||
[AppConnection.Cloudflare]: TCloudflareConnectionOption;
|
||||
[AppConnection.DNSMadeEasy]: TDNSMadeEasyConnectionOption;
|
||||
[AppConnection.Bitbucket]: TBitbucketConnectionOption;
|
||||
[AppConnection.Zabbix]: TZabbixConnectionOption;
|
||||
[AppConnection.Railway]: TRailwayConnectionOption;
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection";
|
||||
|
||||
export enum DNSMadeEasyConnectionMethod {
|
||||
APIKeySecret = "api-key-secret"
|
||||
}
|
||||
|
||||
export type TDNSMadeEasyConnection = TRootAppConnection & { app: AppConnection.DNSMadeEasy } & {
|
||||
method: DNSMadeEasyConnectionMethod.APIKeySecret;
|
||||
credentials: {
|
||||
apiKey: string;
|
||||
secretKey: string;
|
||||
};
|
||||
};
|
||||
@@ -15,6 +15,7 @@ import { TChefConnection } from "./chef-connection";
|
||||
import { TCloudflareConnection } from "./cloudflare-connection";
|
||||
import { TDatabricksConnection } from "./databricks-connection";
|
||||
import { TDigitalOceanConnection } from "./digital-ocean";
|
||||
import { TDNSMadeEasyConnection } from "./dns-made-easy-connection";
|
||||
import { TFlyioConnection } from "./flyio-connection";
|
||||
import { TGcpConnection } from "./gcp-connection";
|
||||
import { TGitHubConnection } from "./github-connection";
|
||||
@@ -58,6 +59,7 @@ export * from "./checkly-connection";
|
||||
export * from "./chef-connection";
|
||||
export * from "./cloudflare-connection";
|
||||
export * from "./databricks-connection";
|
||||
export * from "./dns-made-easy-connection";
|
||||
export * from "./flyio-connection";
|
||||
export * from "./gcp-connection";
|
||||
export * from "./github-connection";
|
||||
@@ -130,7 +132,8 @@ export type TAppConnection =
|
||||
| TOktaConnection
|
||||
| TRedisConnection
|
||||
| TMongoDBConnection
|
||||
| TChefConnection;
|
||||
| TChefConnection
|
||||
| TDNSMadeEasyConnection;
|
||||
|
||||
export type TAvailableAppConnection = Pick<TAppConnection, "name" | "id" | "projectId">;
|
||||
|
||||
|
||||
@@ -16,12 +16,14 @@ export const caStatusToNameMap: { [K in CaStatus]: string } = {
|
||||
|
||||
export const ACME_DNS_PROVIDER_NAME_MAP: Record<AcmeDnsProvider, string> = {
|
||||
[AcmeDnsProvider.ROUTE53]: "Route53",
|
||||
[AcmeDnsProvider.Cloudflare]: "Cloudflare"
|
||||
[AcmeDnsProvider.Cloudflare]: "Cloudflare",
|
||||
[AcmeDnsProvider.DNSMadeEasy]: "DNS Made Easy"
|
||||
};
|
||||
|
||||
export const ACME_DNS_PROVIDER_APP_CONNECTION_MAP: Record<AcmeDnsProvider, AppConnection> = {
|
||||
[AcmeDnsProvider.ROUTE53]: AppConnection.AWS,
|
||||
[AcmeDnsProvider.Cloudflare]: AppConnection.Cloudflare
|
||||
[AcmeDnsProvider.Cloudflare]: AppConnection.Cloudflare,
|
||||
[AcmeDnsProvider.DNSMadeEasy]: AppConnection.DNSMadeEasy
|
||||
};
|
||||
|
||||
export const CA_TYPE_CAPABILITIES_MAP: Record<CaType, CaCapability[]> = {
|
||||
|
||||
@@ -21,7 +21,8 @@ export enum CaRenewalType {
|
||||
|
||||
export enum AcmeDnsProvider {
|
||||
ROUTE53 = "route53",
|
||||
Cloudflare = "cloudflare"
|
||||
Cloudflare = "cloudflare",
|
||||
DNSMadeEasy = "dns-made-easy"
|
||||
}
|
||||
|
||||
export enum CaCapability {
|
||||
|
||||
@@ -13,12 +13,12 @@ export {
|
||||
export {
|
||||
useGetAzureAdcsTemplates,
|
||||
useGetCa,
|
||||
useGetCaById,
|
||||
useGetCaCert,
|
||||
useGetCaCerts,
|
||||
useGetCaCertTemplates,
|
||||
useGetCaCrls,
|
||||
useGetCaCsr,
|
||||
useGetInternalCaById,
|
||||
useListCasByProjectId,
|
||||
useListCasByTypeAndProjectId,
|
||||
useListExternalCasByProjectId
|
||||
|
||||
@@ -27,21 +27,20 @@ import {
|
||||
export const useUpdateCa = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TUnifiedCertificateAuthority, object, TUpdateCertificateAuthorityDTO>({
|
||||
mutationFn: async ({ caName, ...body }) => {
|
||||
mutationFn: async ({ id, ...body }) => {
|
||||
const { data } = await apiRequest.patch<TUnifiedCertificateAuthority>(
|
||||
`/api/v1/pki/ca/${body.type}/${caName}`,
|
||||
`/api/v1/cert-manager/ca/${body.type}/${id}`,
|
||||
body
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: ({ projectId, type }, { caName }) => {
|
||||
caKeys.getCaByNameAndProjectId(caName, projectId);
|
||||
onSuccess: ({ projectId, type }, { id }) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: caKeys.listCasByTypeAndProjectId(type, projectId)
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: caKeys.getCaByNameAndProjectId(caName, projectId)
|
||||
queryKey: caKeys.getCaById(id)
|
||||
});
|
||||
// Invalidate external CAs list
|
||||
queryClient.invalidateQueries({
|
||||
@@ -56,7 +55,7 @@ export const useCreateCa = () => {
|
||||
return useMutation<TUnifiedCertificateAuthority, object, TCreateCertificateAuthorityDTO>({
|
||||
mutationFn: async (body) => {
|
||||
const { data } = await apiRequest.post<TUnifiedCertificateAuthority>(
|
||||
`/api/v1/pki/ca/${body.type}`,
|
||||
`/api/v1/cert-manager/ca/${body.type}`,
|
||||
body
|
||||
);
|
||||
return data;
|
||||
@@ -76,14 +75,9 @@ export const useCreateCa = () => {
|
||||
export const useDeleteCa = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TUnifiedCertificateAuthority, object, TDeleteCertificateAuthorityDTO>({
|
||||
mutationFn: async ({ caName, type, projectId }) => {
|
||||
mutationFn: async ({ id, type }) => {
|
||||
const { data } = await apiRequest.delete<TUnifiedCertificateAuthority>(
|
||||
`/api/v1/pki/ca/${type}/${caName}`,
|
||||
{
|
||||
data: {
|
||||
projectId
|
||||
}
|
||||
}
|
||||
`/api/v1/cert-manager/ca/${type}/${id}`
|
||||
);
|
||||
return data;
|
||||
},
|
||||
@@ -104,7 +98,7 @@ export const useSignIntermediate = () => {
|
||||
return useMutation<TSignIntermediateResponse, object, TSignIntermediateDTO>({
|
||||
mutationFn: async (body) => {
|
||||
const { data } = await apiRequest.post<TSignIntermediateResponse>(
|
||||
`/api/v1/pki/ca/${body.caId}/sign-intermediate`,
|
||||
`/api/v1/cert-manager/ca/internal/${body.caId}/sign-intermediate`,
|
||||
body
|
||||
);
|
||||
return data;
|
||||
@@ -117,13 +111,14 @@ export const useImportCaCertificate = (projectId: string) => {
|
||||
return useMutation<TImportCaCertificateResponse, object, TImportCaCertificateDTO>({
|
||||
mutationFn: async ({ caId, ...body }) => {
|
||||
const { data } = await apiRequest.post<TImportCaCertificateResponse>(
|
||||
`/api/v1/pki/ca/${caId}/import-certificate`,
|
||||
`/api/v1/cert-manager/ca/internal/${caId}/import-certificate`,
|
||||
body
|
||||
);
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { caId }) => {
|
||||
queryClient.invalidateQueries({ queryKey: projectKeys.getProjectCas({ projectId }) });
|
||||
queryClient.invalidateQueries({ queryKey: caKeys.getCaById(caId) });
|
||||
queryClient.invalidateQueries({ queryKey: caKeys.getCaCerts(caId) });
|
||||
queryClient.invalidateQueries({ queryKey: caKeys.getCaCert(caId) });
|
||||
queryClient.invalidateQueries({
|
||||
@@ -133,7 +128,7 @@ export const useImportCaCertificate = (projectId: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
// consider rename to issue certificate
|
||||
// TODO: DEPRECATE
|
||||
export const useCreateCertificate = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCreateCertificateResponse, object, TCreateCertificateDTO>({
|
||||
@@ -157,7 +152,7 @@ export const useCreateCertificateV3 = (options?: { projectId?: string }) => {
|
||||
return useMutation<TCreateCertificateV3Response, object, TCreateCertificateV3DTO>({
|
||||
mutationFn: async (body) => {
|
||||
const { data } = await apiRequest.post<TCreateCertificateV3Response>(
|
||||
"/api/v3/pki/certificates/issue-certificate",
|
||||
"/api/v1/cert-manager/certificates/issue-certificate",
|
||||
body
|
||||
);
|
||||
return data;
|
||||
@@ -185,7 +180,7 @@ export const useOrderCertificateWithProfile = () => {
|
||||
return useMutation<TOrderCertificateResponse, object, TOrderCertificateDTO>({
|
||||
mutationFn: async (body) => {
|
||||
const { data } = await apiRequest.post<TOrderCertificateResponse>(
|
||||
"/api/v3/pki/certificates/order-certificate",
|
||||
"/api/v1/cert-manager/certificates/order-certificate",
|
||||
body
|
||||
);
|
||||
return data;
|
||||
@@ -203,7 +198,7 @@ export const useRenewCa = () => {
|
||||
return useMutation<TRenewCaResponse, object, TRenewCaDTO>({
|
||||
mutationFn: async (body) => {
|
||||
const { data } = await apiRequest.post<TRenewCaResponse>(
|
||||
`/api/v1/pki/ca/${body.caId}/renew`,
|
||||
`/api/v1/cert-manager/ca/internal/${body.caId}/renew`,
|
||||
body
|
||||
);
|
||||
return data;
|
||||
|
||||
@@ -4,7 +4,11 @@ import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { TCertificateTemplate } from "../certificateTemplates/types";
|
||||
import { CaType } from "./enums";
|
||||
import { TAzureAdCsTemplate, TCertificateAuthority, TUnifiedCertificateAuthority } from "./types";
|
||||
import {
|
||||
TAzureAdCsTemplate,
|
||||
TInternalCertificateAuthority,
|
||||
TUnifiedCertificateAuthority
|
||||
} from "./types";
|
||||
|
||||
export const caKeys = {
|
||||
getCaById: (caId: string) => [{ caId }, "ca"],
|
||||
@@ -25,24 +29,16 @@ export const caKeys = {
|
||||
]
|
||||
};
|
||||
|
||||
export const useGetCa = ({
|
||||
caName,
|
||||
projectId,
|
||||
type
|
||||
}: {
|
||||
caName: string;
|
||||
projectId: string;
|
||||
type: CaType;
|
||||
}) => {
|
||||
export const useGetCa = ({ caId, type }: { caId: string; type: CaType }) => {
|
||||
return useQuery({
|
||||
queryKey: caKeys.getCaByNameAndProjectId(caName, projectId),
|
||||
queryKey: caKeys.getCaById(caId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<TUnifiedCertificateAuthority>(
|
||||
`/api/v1/pki/ca/${type}/${caName}?projectId=${projectId}`
|
||||
`/api/v1/cert-manager/ca/${type}/${caId}`
|
||||
);
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(caName && projectId && type)
|
||||
enabled: Boolean(caId && type)
|
||||
});
|
||||
};
|
||||
|
||||
@@ -51,7 +47,7 @@ export const useListCasByTypeAndProjectId = (type: CaType, projectId: string) =>
|
||||
queryKey: caKeys.listCasByTypeAndProjectId(type, projectId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<TUnifiedCertificateAuthority[]>(
|
||||
`/api/v1/pki/ca/${type}?projectId=${projectId}`
|
||||
`/api/v1/cert-manager/ca/${type}?projectId=${projectId}`
|
||||
);
|
||||
|
||||
return data;
|
||||
@@ -65,7 +61,7 @@ export const useListCasByProjectId = (projectId: string) => {
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{
|
||||
certificateAuthorities: TUnifiedCertificateAuthority[];
|
||||
}>(`/api/v2/pki/ca?projectId=${projectId}`);
|
||||
}>(`/api/v1/cert-manager/ca?projectId=${projectId}`);
|
||||
|
||||
return data.certificateAuthorities;
|
||||
}
|
||||
@@ -78,10 +74,10 @@ export const useListExternalCasByProjectId = (projectId: string) => {
|
||||
queryFn: async () => {
|
||||
const [acmeResponse, azureAdCsResponse] = await Promise.allSettled([
|
||||
apiRequest.get<TUnifiedCertificateAuthority[]>(
|
||||
`/api/v1/pki/ca/${CaType.ACME}?projectId=${projectId}`
|
||||
`/api/v1/cert-manager/ca/${CaType.ACME}?projectId=${projectId}`
|
||||
),
|
||||
apiRequest.get<TUnifiedCertificateAuthority[]>(
|
||||
`/api/v1/pki/ca/${CaType.AZURE_AD_CS}?projectId=${projectId}`
|
||||
`/api/v1/cert-manager/ca/${CaType.AZURE_AD_CS}?projectId=${projectId}`
|
||||
)
|
||||
]);
|
||||
|
||||
@@ -100,14 +96,14 @@ export const useListExternalCasByProjectId = (projectId: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetCaById = (caId: string) => {
|
||||
export const useGetInternalCaById = (caId: string) => {
|
||||
return useQuery({
|
||||
queryKey: caKeys.getCaById(caId),
|
||||
queryFn: async () => {
|
||||
const {
|
||||
data: { ca }
|
||||
} = await apiRequest.get<{ ca: TCertificateAuthority }>(`/api/v1/pki/ca/${caId}`);
|
||||
return ca;
|
||||
const { data } = await apiRequest.get<TInternalCertificateAuthority>(
|
||||
`/api/v1/cert-manager/ca/internal/${caId}`
|
||||
);
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
});
|
||||
@@ -124,7 +120,7 @@ export const useGetCaCerts = (caId: string) => {
|
||||
serialNumber: string;
|
||||
version: number;
|
||||
}[]
|
||||
>(`/api/v1/pki/ca/${caId}/ca-certificates`); // TODO: consider updating endpoint structure
|
||||
>(`/api/v1/cert-manager/ca/internal/${caId}/ca-certificates`);
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
@@ -139,7 +135,7 @@ export const useGetCaCert = (caId: string) => {
|
||||
certificate: string;
|
||||
certificateChain: string;
|
||||
serialNumber: string;
|
||||
}>(`/api/v1/pki/ca/${caId}/certificate`); // TODO: consider updating endpoint structure
|
||||
}>(`/api/v1/cert-manager/ca/internal/${caId}/certificate`);
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
@@ -154,7 +150,7 @@ export const useGetCaCsr = (caId: string) => {
|
||||
data: { csr }
|
||||
} = await apiRequest.get<{
|
||||
csr: string;
|
||||
}>(`/api/v1/pki/ca/${caId}/csr`);
|
||||
}>(`/api/v1/cert-manager/ca/internal/${caId}/csr`);
|
||||
return csr;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
@@ -170,13 +166,14 @@ export const useGetCaCrls = (caId: string) => {
|
||||
id: string;
|
||||
crl: string;
|
||||
}[]
|
||||
>(`/api/v1/pki/ca/${caId}/crls`);
|
||||
>(`/api/v1/cert-manager/ca/internal/${caId}/crls`);
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(caId)
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useGetCaCertTemplates = (caId: string) => {
|
||||
return useQuery({
|
||||
queryKey: caKeys.getCaCertTemplates(caId),
|
||||
@@ -192,19 +189,21 @@ export const useGetCaCertTemplates = (caId: string) => {
|
||||
|
||||
export const useGetAzureAdcsTemplates = ({
|
||||
caId,
|
||||
projectId
|
||||
projectId,
|
||||
isAzureAdcsCa
|
||||
}: {
|
||||
caId: string;
|
||||
projectId: string;
|
||||
isAzureAdcsCa: boolean;
|
||||
}) => {
|
||||
return useQuery({
|
||||
queryKey: caKeys.getAzureAdcsTemplates(caId, projectId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{
|
||||
templates: TAzureAdCsTemplate[];
|
||||
}>(`/api/v1/pki/ca/azure-ad-cs/${caId}/templates?projectId=${projectId}`);
|
||||
}>(`/api/v1/cert-manager/ca/azure-ad-cs/${caId}/templates?projectId=${projectId}`);
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(caId && projectId)
|
||||
enabled: Boolean(caId && projectId && isAzureAdcsCa)
|
||||
});
|
||||
};
|
||||
|
||||
@@ -66,17 +66,19 @@ export type TUnifiedCertificateAuthority =
|
||||
| TAzureAdCsCertificateAuthority
|
||||
| TInternalCertificateAuthority;
|
||||
|
||||
export type TCreateCertificateAuthorityDTO = Omit<TUnifiedCertificateAuthority, "id">;
|
||||
export type TCreateCertificateAuthorityDTO = Omit<
|
||||
TUnifiedCertificateAuthority,
|
||||
"id" | "enableDirectIssuance"
|
||||
>;
|
||||
export type TUpdateCertificateAuthorityDTO = Partial<TUnifiedCertificateAuthority> & {
|
||||
caName: string;
|
||||
projectId: string;
|
||||
id: string;
|
||||
type: CaType;
|
||||
};
|
||||
|
||||
export type TDeleteCertificateAuthorityDTO = {
|
||||
caName: string;
|
||||
type: CaType;
|
||||
id: string;
|
||||
projectId: string;
|
||||
type: CaType;
|
||||
};
|
||||
|
||||
export type TCertificateAuthority = {
|
||||
|
||||
@@ -10,4 +10,4 @@ export {
|
||||
useGetProfileCertificates,
|
||||
useListCertificateProfiles
|
||||
} from "./queries";
|
||||
export type * from "./types";
|
||||
export * from "./types";
|
||||
|
||||
@@ -17,7 +17,7 @@ export const useCreateCertificateProfile = () => {
|
||||
mutationFn: async (data) => {
|
||||
const { data: response } = await apiRequest.post<{
|
||||
certificateProfile: TCertificateProfile;
|
||||
}>("/api/v1/pki/certificate-profiles", data);
|
||||
}>("/api/v1/cert-manager/certificate-profiles", data);
|
||||
return response.certificateProfile;
|
||||
},
|
||||
onSuccess: (_, { projectId }) => {
|
||||
@@ -35,7 +35,7 @@ export const useUpdateCertificateProfile = () => {
|
||||
mutationFn: async ({ profileId, ...data }) => {
|
||||
const { data: response } = await apiRequest.patch<{
|
||||
certificateProfile: TCertificateProfile;
|
||||
}>(`/api/v1/pki/certificate-profiles/${profileId}`, data);
|
||||
}>(`/api/v1/cert-manager/certificate-profiles/${profileId}`, data);
|
||||
return response.certificateProfile;
|
||||
},
|
||||
onSuccess: (profile, { profileId }) => {
|
||||
@@ -56,7 +56,7 @@ export const useDeleteCertificateProfile = () => {
|
||||
mutationFn: async ({ profileId }) => {
|
||||
const { data: response } = await apiRequest.delete<{
|
||||
certificateProfile: TCertificateProfile;
|
||||
}>(`/api/v1/pki/certificate-profiles/${profileId}`);
|
||||
}>(`/api/v1/cert-manager/certificate-profiles/${profileId}`);
|
||||
return response.certificateProfile;
|
||||
},
|
||||
onSuccess: (profile, { profileId }) => {
|
||||
|
||||
@@ -71,7 +71,7 @@ export const useListCertificateProfiles = ({
|
||||
const { data } = await apiRequest.get<{
|
||||
certificateProfiles: TCertificateProfile[];
|
||||
totalCount: number;
|
||||
}>("/api/v1/pki/certificate-profiles", {
|
||||
}>("/api/v1/cert-manager/certificate-profiles", {
|
||||
params: {
|
||||
projectId,
|
||||
limit,
|
||||
@@ -93,7 +93,7 @@ export const useGetCertificateProfileById = ({ profileId }: TGetCertificateProfi
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{
|
||||
certificateProfile: TCertificateProfileWithDetails;
|
||||
}>(`/api/v1/pki/certificate-profiles/${profileId}`);
|
||||
}>(`/api/v1/cert-manager/certificate-profiles/${profileId}`);
|
||||
return data.certificateProfile;
|
||||
},
|
||||
enabled: Boolean(profileId)
|
||||
@@ -109,7 +109,7 @@ export const useGetCertificateProfileBySlug = ({
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{
|
||||
certificateProfile: TCertificateProfile;
|
||||
}>(`/api/v1/pki/certificate-profiles/slug/${slug}`, {
|
||||
}>(`/api/v1/cert-manager/certificate-profiles/slug/${slug}`, {
|
||||
params: { projectId }
|
||||
});
|
||||
return data.certificateProfile;
|
||||
@@ -125,7 +125,7 @@ export const useRevealAcmeEabSecret = ({ profileId }: TRevealAcmeEabSecretDTO) =
|
||||
const { data } = await apiRequest.get<{
|
||||
eabKid: string;
|
||||
eabSecret: string;
|
||||
}>(`/api/v1/pki/certificate-profiles/${profileId}/acme/eab-secret/reveal`);
|
||||
}>(`/api/v1/cert-manager/certificate-profiles/${profileId}/acme/eab-secret/reveal`);
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(profileId)
|
||||
@@ -144,7 +144,7 @@ export const useGetProfileCertificates = ({
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{
|
||||
certificates: TProfileCertificate[];
|
||||
}>(`/api/v1/pki/certificate-profiles/${profileId}/certificates`, {
|
||||
}>(`/api/v1/cert-manager/certificate-profiles/${profileId}/certificates`, {
|
||||
params: {
|
||||
offset,
|
||||
limit,
|
||||
|
||||
@@ -1,23 +1,46 @@
|
||||
export enum EnrollmentType {
|
||||
API = "api",
|
||||
EST = "est",
|
||||
ACME = "acme"
|
||||
}
|
||||
|
||||
export enum IssuerType {
|
||||
CA = "ca",
|
||||
SELF_SIGNED = "self-signed"
|
||||
}
|
||||
|
||||
export type TCertificateProfile = {
|
||||
id: string;
|
||||
projectId: string;
|
||||
caId: string;
|
||||
caId: string | null;
|
||||
certificateTemplateId: string;
|
||||
slug: string;
|
||||
description?: string;
|
||||
enrollmentType: "api" | "est" | "acme";
|
||||
enrollmentType: EnrollmentType;
|
||||
issuerType: IssuerType;
|
||||
estConfigId?: string;
|
||||
apiConfigId?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
externalConfigs?: Record<string, unknown> | null;
|
||||
certificateAuthority?: {
|
||||
id: string;
|
||||
projectId?: string;
|
||||
status: string;
|
||||
name: string;
|
||||
isExternal?: boolean;
|
||||
externalType?: string | null;
|
||||
};
|
||||
};
|
||||
|
||||
export type TCertificateProfileWithDetails = TCertificateProfile & {
|
||||
certificateAuthority?: {
|
||||
id: string;
|
||||
projectId: string;
|
||||
projectId?: string;
|
||||
status: string;
|
||||
name: string;
|
||||
isExternal?: boolean;
|
||||
externalType?: string | null;
|
||||
};
|
||||
certificateTemplate?: {
|
||||
id: string;
|
||||
@@ -44,11 +67,12 @@ export type TCertificateProfileWithDetails = TCertificateProfile & {
|
||||
|
||||
export type TCreateCertificateProfileDTO = {
|
||||
projectId: string;
|
||||
caId: string;
|
||||
caId?: string;
|
||||
certificateTemplateId: string;
|
||||
slug: string;
|
||||
description?: string;
|
||||
enrollmentType: "api" | "est" | "acme";
|
||||
enrollmentType: EnrollmentType;
|
||||
issuerType: IssuerType;
|
||||
estConfig?: {
|
||||
disableBootstrapCaValidation?: boolean;
|
||||
passphrase: string;
|
||||
@@ -59,12 +83,15 @@ export type TCreateCertificateProfileDTO = {
|
||||
renewBeforeDays?: number;
|
||||
};
|
||||
acmeConfig?: unknown;
|
||||
externalConfigs?: Record<string, unknown> | null;
|
||||
};
|
||||
|
||||
export type TUpdateCertificateProfileDTO = {
|
||||
profileId: string;
|
||||
slug?: string;
|
||||
description?: string;
|
||||
enrollmentType?: EnrollmentType;
|
||||
issuerType?: IssuerType;
|
||||
estConfig?: {
|
||||
disableBootstrapCaValidation?: boolean;
|
||||
passphrase?: string;
|
||||
@@ -75,6 +102,7 @@ export type TUpdateCertificateProfileDTO = {
|
||||
renewBeforeDays?: number;
|
||||
};
|
||||
acmeConfig?: unknown;
|
||||
externalConfigs?: Record<string, unknown> | null;
|
||||
};
|
||||
|
||||
export type TDeleteCertificateProfileDTO = {
|
||||
@@ -87,7 +115,9 @@ export type TListCertificateProfilesDTO = {
|
||||
offset?: number;
|
||||
search?: string;
|
||||
includeConfigs?: boolean;
|
||||
enrollmentType?: "api" | "est" | "acme";
|
||||
enrollmentType?: EnrollmentType;
|
||||
issuerType?: IssuerType;
|
||||
caId?: string;
|
||||
};
|
||||
|
||||
export type TGetCertificateProfileByIdDTO = {
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
TUpdateEstConfigDTO
|
||||
} from "./types";
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useCreateCertTemplate = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificateTemplate, object, TCreateCertificateTemplateDTO>({
|
||||
@@ -40,6 +41,7 @@ export const useCreateCertTemplate = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useUpdateCertTemplate = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificateTemplate, object, TUpdateCertificateTemplateDTO>({
|
||||
@@ -61,6 +63,7 @@ export const useUpdateCertTemplate = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useDeleteCertTemplate = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificateTemplate, object, TDeleteCertificateTemplateDTO>({
|
||||
@@ -147,6 +150,7 @@ export const useDeleteCertTemplateV2 = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useCreateEstConfig = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<object, object, TCreateEstConfigDTO>({
|
||||
@@ -165,6 +169,7 @@ export const useCreateEstConfig = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useUpdateEstConfig = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<object, object, TUpdateEstConfigDTO>({
|
||||
@@ -193,7 +198,7 @@ export const useCreateCertificateTemplateV2WithPolicies = () => {
|
||||
mutationFn: async (data) => {
|
||||
const { data: response } = await apiRequest.post<{
|
||||
certificateTemplate: TCertificateTemplateV2WithPolicies;
|
||||
}>("/api/v2/certificate-templates", data);
|
||||
}>("/api/v1/cert-manager/certificate-templates", data);
|
||||
return response.certificateTemplate;
|
||||
},
|
||||
onSuccess: (_, { projectId }) => {
|
||||
@@ -214,7 +219,7 @@ export const useUpdateCertificateTemplateV2WithPolicies = () => {
|
||||
mutationFn: async ({ templateId, ...data }) => {
|
||||
const { data: response } = await apiRequest.patch<{
|
||||
certificateTemplate: TCertificateTemplateV2WithPolicies;
|
||||
}>(`/api/v2/certificate-templates/${templateId}`, data);
|
||||
}>(`/api/v1/cert-manager/certificate-templates/${templateId}`, data);
|
||||
return response.certificateTemplate;
|
||||
},
|
||||
onSuccess: (template, { templateId }) => {
|
||||
@@ -238,7 +243,7 @@ export const useDeleteCertificateTemplateV2WithPolicies = () => {
|
||||
mutationFn: async ({ templateId }) => {
|
||||
const { data: response } = await apiRequest.delete<{
|
||||
certificateTemplate: TCertificateTemplateV2WithPolicies;
|
||||
}>(`/api/v2/certificate-templates/${templateId}`);
|
||||
}>(`/api/v1/cert-manager/certificate-templates/${templateId}`);
|
||||
return response.certificateTemplate;
|
||||
},
|
||||
onSuccess: (template, { templateId }) => {
|
||||
|
||||
@@ -31,6 +31,7 @@ export const certTemplateKeys = {
|
||||
getTemplateV2ById: (id: string) => ["cert-template-v2", id]
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useGetCertTemplate = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: certTemplateKeys.getCertTemplateById(id),
|
||||
@@ -44,6 +45,7 @@ export const useGetCertTemplate = (id: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useListCertificateTemplates = ({
|
||||
limit = 100,
|
||||
offset = 0,
|
||||
@@ -67,6 +69,7 @@ export const useListCertificateTemplates = ({
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useGetEstConfig = (certificateTemplateId: string) => {
|
||||
return useQuery({
|
||||
queryKey: certTemplateKeys.getEstConfig(certificateTemplateId),
|
||||
@@ -92,7 +95,7 @@ export const useListCertificateTemplatesV2 = ({
|
||||
const { data } = await apiRequest.get<{
|
||||
certificateTemplates: TCertificateTemplateV2WithPolicies[];
|
||||
totalCount: number;
|
||||
}>("/api/v2/certificate-templates", {
|
||||
}>("/api/v1/cert-manager/certificate-templates", {
|
||||
params: {
|
||||
projectId,
|
||||
limit,
|
||||
@@ -113,7 +116,7 @@ export const useGetCertificateTemplateV2ById = ({
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{
|
||||
certificateTemplate: TCertificateTemplateV2WithPolicies;
|
||||
}>(`/api/v2/certificate-templates/${templateId}`);
|
||||
}>(`/api/v1/cert-manager/certificate-templates/${templateId}`);
|
||||
return data.certificateTemplate;
|
||||
},
|
||||
enabled: Boolean(templateId)
|
||||
|
||||
@@ -13,17 +13,19 @@ import {
|
||||
TRenewCertificateDTO,
|
||||
TRenewCertificateResponse,
|
||||
TRevokeCertDTO,
|
||||
TUnifiedCertificateIssuanceDTO,
|
||||
TUnifiedCertificateIssuanceResponse,
|
||||
TUpdateRenewalConfigDTO
|
||||
} from "./types";
|
||||
|
||||
export const useDeleteCert = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificate, object, TDeleteCertDTO>({
|
||||
mutationFn: async ({ serialNumber }) => {
|
||||
mutationFn: async ({ id }) => {
|
||||
const {
|
||||
data: { certificate }
|
||||
} = await apiRequest.delete<{ certificate: TCertificate }>(
|
||||
`/api/v1/pki/certificates/${serialNumber}`
|
||||
`/api/v1/cert-manager/certificates/${id}`
|
||||
);
|
||||
return certificate;
|
||||
},
|
||||
@@ -47,11 +49,11 @@ export const useDeleteCert = () => {
|
||||
export const useRevokeCert = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TCertificate, object, TRevokeCertDTO>({
|
||||
mutationFn: async ({ serialNumber, revocationReason }) => {
|
||||
mutationFn: async ({ id, revocationReason }) => {
|
||||
const {
|
||||
data: { certificate }
|
||||
} = await apiRequest.post<{ certificate: TCertificate }>(
|
||||
`/api/v1/pki/certificates/${serialNumber}/revoke`,
|
||||
`/api/v1/cert-manager/certificates/${id}/revoke`,
|
||||
{
|
||||
revocationReason
|
||||
}
|
||||
@@ -80,7 +82,7 @@ export const useImportCertificate = () => {
|
||||
return useMutation<TImportCertificateResponse, object, TImportCertificateDTO>({
|
||||
mutationFn: async (body) => {
|
||||
const { data } = await apiRequest.post<TImportCertificateResponse>(
|
||||
"/api/v1/pki/certificates/import-certificate",
|
||||
"/api/v1/cert-manager/certificates/import-certificate",
|
||||
body
|
||||
);
|
||||
return data;
|
||||
@@ -98,7 +100,7 @@ export const useRenewCertificate = () => {
|
||||
return useMutation<TRenewCertificateResponse, object, TRenewCertificateDTO>({
|
||||
mutationFn: async ({ certificateId }) => {
|
||||
const { data } = await apiRequest.post<TRenewCertificateResponse>(
|
||||
`/api/v3/pki/certificates/${certificateId}/renew`,
|
||||
`/api/v1/cert-manager/certificates/${certificateId}/renew`,
|
||||
{}
|
||||
);
|
||||
return data;
|
||||
@@ -131,7 +133,7 @@ export const useUpdateRenewalConfig = () => {
|
||||
>({
|
||||
mutationFn: async ({ certificateId, renewBeforeDays, enableAutoRenewal }) => {
|
||||
const { data } = await apiRequest.patch<{ message: string; renewBeforeDays?: number }>(
|
||||
`/api/v3/pki/certificates/${certificateId}/config`,
|
||||
`/api/v1/cert-manager/certificates/${certificateId}/config`,
|
||||
{ renewBeforeDays, enableAutoRenewal }
|
||||
);
|
||||
return data;
|
||||
@@ -149,10 +151,10 @@ export const useUpdateRenewalConfig = () => {
|
||||
|
||||
export const useDownloadCertPkcs12 = () => {
|
||||
return useMutation<void, object, TDownloadPkcs12DTO>({
|
||||
mutationFn: async ({ serialNumber, projectSlug, password, alias }) => {
|
||||
mutationFn: async ({ certificateId, projectSlug, password, alias }) => {
|
||||
try {
|
||||
const response = await apiRequest.post(
|
||||
`/api/v1/pki/certificates/${serialNumber}/pkcs12`,
|
||||
`/api/v1/cert-manager/certificates/${certificateId}/pkcs12`,
|
||||
{
|
||||
password,
|
||||
alias
|
||||
@@ -168,7 +170,7 @@ export const useDownloadCertPkcs12 = () => {
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.download = `certificate-${serialNumber}.p12`;
|
||||
link.download = `certificate-${certificateId}.p12`;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
@@ -185,3 +187,31 @@ export const useDownloadCertPkcs12 = () => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useUnifiedCertificateIssuance = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TUnifiedCertificateIssuanceResponse, object, TUnifiedCertificateIssuanceDTO>({
|
||||
mutationFn: async (body) => {
|
||||
const { projectSlug, ...requestData } = body;
|
||||
const { data } = await apiRequest.post<TUnifiedCertificateIssuanceResponse>(
|
||||
"/api/v1/cert-manager/certificates",
|
||||
requestData
|
||||
);
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectSlug }) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["certificate-profiles", "list"]
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: pkiSubscriberKeys.allPkiSubscriberCertificates()
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: projectKeys.allProjectCertificates()
|
||||
});
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: projectKeys.forProjectCertificates(projectSlug)
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -7,7 +7,11 @@ import { TCertificate } from "./types";
|
||||
export const certKeys = {
|
||||
getCertById: (serialNumber: string) => [{ serialNumber }, "cert"],
|
||||
getCertBody: (serialNumber: string) => [{ serialNumber }, "certBody"],
|
||||
getCertBundle: (serialNumber: string) => [{ serialNumber }, "certBundle"]
|
||||
getCertBundle: (serialNumber: string) => [{ serialNumber }, "certBundle"],
|
||||
getCertificateRequest: (requestId: string, projectSlug: string) => [
|
||||
{ requestId, projectSlug },
|
||||
"certificateRequest"
|
||||
]
|
||||
};
|
||||
|
||||
export const useGetCert = (serialNumber: string) => {
|
||||
|
||||
@@ -24,13 +24,13 @@ export type TCertificate = {
|
||||
};
|
||||
|
||||
export type TDeleteCertDTO = {
|
||||
id: string;
|
||||
projectId: string;
|
||||
serialNumber: string;
|
||||
};
|
||||
|
||||
export type TRevokeCertDTO = {
|
||||
projectId: string;
|
||||
serialNumber: string;
|
||||
id: string;
|
||||
revocationReason: string;
|
||||
};
|
||||
|
||||
@@ -64,6 +64,7 @@ export type TRenewCertificateResponse = {
|
||||
serialNumber: string;
|
||||
certificateId: string;
|
||||
projectId: string;
|
||||
certificateRequestId?: string;
|
||||
};
|
||||
|
||||
export type TUpdateRenewalConfigDTO = {
|
||||
@@ -74,8 +75,64 @@ export type TUpdateRenewalConfigDTO = {
|
||||
};
|
||||
|
||||
export type TDownloadPkcs12DTO = {
|
||||
serialNumber: string;
|
||||
certificateId: string;
|
||||
projectSlug: string;
|
||||
password: string;
|
||||
alias: string;
|
||||
};
|
||||
|
||||
export type TUnifiedCertificateIssuanceDTO = {
|
||||
projectSlug: string;
|
||||
profileId: string;
|
||||
projectId: string;
|
||||
csr?: string;
|
||||
attributes?: {
|
||||
commonName?: string;
|
||||
keyUsages?: string[];
|
||||
extendedKeyUsages?: string[];
|
||||
altNames?: Array<{
|
||||
type: string;
|
||||
value: string;
|
||||
}>;
|
||||
signatureAlgorithm: string;
|
||||
keyAlgorithm: string;
|
||||
subjectAlternativeNames?: Array<{
|
||||
type: string;
|
||||
value: string;
|
||||
}>;
|
||||
ttl: string;
|
||||
notBefore?: string;
|
||||
notAfter?: string;
|
||||
};
|
||||
removeRootsFromChain?: boolean;
|
||||
};
|
||||
|
||||
export type TUnifiedCertificateResponse = {
|
||||
certificate: {
|
||||
certificate: string;
|
||||
issuingCaCertificate: string;
|
||||
certificateChain: string;
|
||||
privateKey?: string;
|
||||
serialNumber: string;
|
||||
certificateId: string;
|
||||
};
|
||||
certificateRequestId: string;
|
||||
};
|
||||
|
||||
export type TCertificateRequestResponse = {
|
||||
certificateRequestId: string;
|
||||
status: "pending" | "issued" | "failed";
|
||||
projectId: string;
|
||||
};
|
||||
|
||||
export type TUnifiedCertificateIssuanceResponse =
|
||||
| TUnifiedCertificateResponse
|
||||
| TCertificateRequestResponse;
|
||||
|
||||
export type TCertificateRequestDetails = {
|
||||
status: "pending" | "issued" | "failed";
|
||||
certificate: TCertificate | null;
|
||||
errorMessage: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ import { projectKeys } from "../projects";
|
||||
import { pkiAlertKeys } from "./queries";
|
||||
import { TCreatePkiAlertDTO, TDeletePkiAlertDTO, TPkiAlert, TUpdatePkiAlertDTO } from "./types";
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useCreatePkiAlert = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TPkiAlert, object, TCreatePkiAlertDTO>({
|
||||
@@ -19,6 +20,7 @@ export const useCreatePkiAlert = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useUpdatePkiAlert = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TPkiAlert, object, TUpdatePkiAlertDTO>({
|
||||
@@ -36,6 +38,7 @@ export const useUpdatePkiAlert = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useDeletePkiAlert = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation<TPkiAlert, object, TDeletePkiAlertDTO>({
|
||||
|
||||
@@ -8,6 +8,7 @@ export const pkiAlertKeys = {
|
||||
getPkiAlertById: (alertId: string) => [{ alertId }, "alert"]
|
||||
};
|
||||
|
||||
// TODO: DEPRECATE
|
||||
export const useGetPkiAlertById = (alertId: string) => {
|
||||
return useQuery({
|
||||
queryKey: pkiAlertKeys.getPkiAlertById(alertId),
|
||||
|
||||
@@ -11,7 +11,7 @@ export const useCreatePkiAlertV2 = () => {
|
||||
return useMutation<TPkiAlertV2, unknown, TCreatePkiAlertV2>({
|
||||
mutationFn: async (data) => {
|
||||
const { data: response } = await apiRequest.post<{ alert: TPkiAlertV2 }>(
|
||||
"/api/v2/pki/alerts",
|
||||
"/api/v1/cert-manager/alerts",
|
||||
data
|
||||
);
|
||||
return response.alert;
|
||||
@@ -30,7 +30,7 @@ export const useUpdatePkiAlertV2 = () => {
|
||||
return useMutation<TPkiAlertV2, unknown, TUpdatePkiAlertV2>({
|
||||
mutationFn: async ({ alertId, ...data }) => {
|
||||
const { data: response } = await apiRequest.patch<{ alert: TPkiAlertV2 }>(
|
||||
`/api/v2/pki/alerts/${alertId}`,
|
||||
`/api/v1/cert-manager/alerts/${alertId}`,
|
||||
data
|
||||
);
|
||||
return response.alert;
|
||||
@@ -52,7 +52,7 @@ export const useDeletePkiAlertV2 = () => {
|
||||
return useMutation<TPkiAlertV2, unknown, TDeletePkiAlertV2>({
|
||||
mutationFn: async ({ alertId }) => {
|
||||
const { data } = await apiRequest.delete<{ alert: TPkiAlertV2 }>(
|
||||
`/api/v2/pki/alerts/${alertId}`
|
||||
`/api/v1/cert-manager/alerts/${alertId}`
|
||||
);
|
||||
return data.alert;
|
||||
},
|
||||
|
||||
@@ -24,14 +24,16 @@ export const pkiAlertsV2Keys = {
|
||||
};
|
||||
|
||||
const fetchPkiAlertsV2 = async (params: TGetPkiAlertsV2): Promise<TGetPkiAlertsV2Response> => {
|
||||
const { data } = await apiRequest.get<TGetPkiAlertsV2Response>("/api/v2/pki/alerts", {
|
||||
const { data } = await apiRequest.get<TGetPkiAlertsV2Response>("/api/v1/cert-manager/alerts", {
|
||||
params
|
||||
});
|
||||
return data;
|
||||
};
|
||||
|
||||
const fetchPkiAlertV2ById = async ({ alertId }: TGetPkiAlertV2ById): Promise<TPkiAlertV2> => {
|
||||
const { data } = await apiRequest.get<{ alert: TPkiAlertV2 }>(`/api/v2/pki/alerts/${alertId}`);
|
||||
const { data } = await apiRequest.get<{ alert: TPkiAlertV2 }>(
|
||||
`/api/v1/cert-manager/alerts/${alertId}`
|
||||
);
|
||||
return data.alert;
|
||||
};
|
||||
|
||||
@@ -40,7 +42,7 @@ const fetchPkiAlertV2MatchingCertificates = async (
|
||||
): Promise<TGetPkiAlertV2MatchingCertificatesResponse> => {
|
||||
const { alertId, ...queryParams } = params;
|
||||
const { data } = await apiRequest.get<TGetPkiAlertV2MatchingCertificatesResponse>(
|
||||
`/api/v2/pki/alerts/${alertId}/certificates`,
|
||||
`/api/v1/cert-manager/alerts/${alertId}/certificates`,
|
||||
{ params: queryParams }
|
||||
);
|
||||
return data;
|
||||
@@ -50,7 +52,7 @@ const fetchPkiAlertV2CurrentMatchingCertificates = async (
|
||||
params: TGetPkiAlertV2CurrentMatchingCertificates
|
||||
): Promise<TGetPkiAlertV2CurrentMatchingCertificatesResponse> => {
|
||||
const { data } = await apiRequest.post<TGetPkiAlertV2CurrentMatchingCertificatesResponse>(
|
||||
"/api/v2/pki/alerts/preview/certificates",
|
||||
"/api/v1/cert-manager/alerts/preview/certificates",
|
||||
params
|
||||
);
|
||||
return data;
|
||||
|
||||
@@ -17,7 +17,10 @@ export const useCreatePkiSync = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ destination, ...params }: TCreatePkiSyncDTO) => {
|
||||
const { data } = await apiRequest.post<TPkiSync>(`/api/v1/pki/syncs/${destination}`, params);
|
||||
const { data } = await apiRequest.post<TPkiSync>(
|
||||
`/api/v1/cert-manager/syncs/${destination}`,
|
||||
params
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
@@ -31,7 +34,7 @@ export const useUpdatePkiSync = () => {
|
||||
return useMutation({
|
||||
mutationFn: async ({ syncId, projectId, destination, ...params }: TUpdatePkiSyncDTO) => {
|
||||
const { data } = await apiRequest.patch<TPkiSync>(
|
||||
`/api/v1/pki/syncs/${destination}/${syncId}`,
|
||||
`/api/v1/cert-manager/syncs/${destination}/${syncId}`,
|
||||
params,
|
||||
{ params: { projectId } }
|
||||
);
|
||||
@@ -49,9 +52,12 @@ export const useDeletePkiSync = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ syncId, projectId, destination }: TDeletePkiSyncDTO) => {
|
||||
const { data } = await apiRequest.delete(`/api/v1/pki/syncs/${destination}/${syncId}`, {
|
||||
params: { projectId }
|
||||
});
|
||||
const { data } = await apiRequest.delete(
|
||||
`/api/v1/cert-manager/syncs/${destination}/${syncId}`,
|
||||
{
|
||||
params: { projectId }
|
||||
}
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
@@ -66,7 +72,9 @@ export const useTriggerPkiSyncSyncCertificates = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ syncId, destination }: TTriggerPkiSyncSyncCertificatesDTO) => {
|
||||
const { data } = await apiRequest.post(`/api/v1/pki/syncs/${destination}/${syncId}/sync`);
|
||||
const { data } = await apiRequest.post(
|
||||
`/api/v1/cert-manager/syncs/${destination}/${syncId}/sync`
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
@@ -111,7 +119,9 @@ export const useTriggerPkiSyncImportCertificates = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ syncId, destination }: TTriggerPkiSyncImportCertificatesDTO) => {
|
||||
const { data } = await apiRequest.post(`/api/v1/pki/syncs/${destination}/${syncId}/import`);
|
||||
const { data } = await apiRequest.post(
|
||||
`/api/v1/cert-manager/syncs/${destination}/${syncId}/import`
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
@@ -157,7 +167,7 @@ export const useTriggerPkiSyncRemoveCertificates = () => {
|
||||
return useMutation({
|
||||
mutationFn: async ({ syncId, destination }: TTriggerPkiSyncRemoveCertificatesDTO) => {
|
||||
const { data } = await apiRequest.post(
|
||||
`/api/v1/pki/syncs/${destination}/${syncId}/remove-certificates`
|
||||
`/api/v1/cert-manager/syncs/${destination}/${syncId}/remove-certificates`
|
||||
);
|
||||
|
||||
return data;
|
||||
@@ -209,9 +219,12 @@ export const useAddCertificatesToPkiSync = () => {
|
||||
pkiSyncId: string;
|
||||
certificateIds: string[];
|
||||
}) => {
|
||||
const { data } = await apiRequest.post(`/api/v1/pki/syncs/${pkiSyncId}/certificates`, {
|
||||
certificateIds
|
||||
});
|
||||
const { data } = await apiRequest.post(
|
||||
`/api/v1/cert-manager/syncs/${pkiSyncId}/certificates`,
|
||||
{
|
||||
certificateIds
|
||||
}
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
@@ -231,9 +244,12 @@ export const useRemoveCertificatesFromPkiSync = () => {
|
||||
pkiSyncId: string;
|
||||
certificateIds: string[];
|
||||
}) => {
|
||||
const { data } = await apiRequest.delete(`/api/v1/pki/syncs/${pkiSyncId}/certificates`, {
|
||||
data: { certificateIds }
|
||||
});
|
||||
const { data } = await apiRequest.delete(
|
||||
`/api/v1/cert-manager/syncs/${pkiSyncId}/certificates`,
|
||||
{
|
||||
data: { certificateIds }
|
||||
}
|
||||
);
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
@@ -37,7 +37,9 @@ export const usePkiSyncOptions = (
|
||||
return useQuery({
|
||||
queryKey: pkiSyncKeys.options(),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<TListPkiSyncOptions>("/api/v1/pki/syncs/options");
|
||||
const { data } = await apiRequest.get<TListPkiSyncOptions>(
|
||||
"/api/v1/cert-manager/syncs/options"
|
||||
);
|
||||
|
||||
return data.pkiSyncOptions;
|
||||
},
|
||||
@@ -58,7 +60,7 @@ export const fetchPkiSyncsByProjectId = async (projectId: string, certificateId?
|
||||
params.certificateId = certificateId;
|
||||
}
|
||||
|
||||
const { data } = await apiRequest.get<TListPkiSyncs>("/api/v1/pki/syncs", {
|
||||
const { data } = await apiRequest.get<TListPkiSyncs>("/api/v1/cert-manager/syncs", {
|
||||
params
|
||||
});
|
||||
|
||||
@@ -110,7 +112,7 @@ export const useGetPkiSync = (
|
||||
return useQuery({
|
||||
queryKey: pkiSyncKeys.byId(syncId, projectId),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<TPkiSync>(`/api/v1/pki/syncs/${syncId}`, {
|
||||
const { data } = await apiRequest.get<TPkiSync>(`/api/v1/cert-manager/syncs/${syncId}`, {
|
||||
params: { projectId }
|
||||
});
|
||||
|
||||
@@ -138,7 +140,7 @@ export const useListPkiSyncCertificates = (
|
||||
return useQuery({
|
||||
queryKey: pkiSyncKeys.certificates(syncId, { offset, limit }),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get(`/api/v1/pki/syncs/${syncId}/certificates`, {
|
||||
const { data } = await apiRequest.get(`/api/v1/cert-manager/syncs/${syncId}/certificates`, {
|
||||
params: { offset, limit }
|
||||
});
|
||||
return {
|
||||
|
||||
@@ -338,7 +338,7 @@ export const clearSession = (keepQueryClient?: boolean) => {
|
||||
sessionStorage.removeItem(SessionStorageKeys.CLI_TERMINAL_TOKEN);
|
||||
|
||||
if (!keepQueryClient) {
|
||||
qc.clear(); // Clear React Query cache
|
||||
qc.invalidateQueries();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+10
-14
@@ -1,9 +1,5 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@import "@fontsource/inter/400.css" layer(base);
|
||||
@import "@fontsource/inter/500.css" layer(base);
|
||||
@import "@fontsource/inter/700.css" layer(base);
|
||||
|
||||
@source not "../public";
|
||||
|
||||
/*
|
||||
@@ -29,11 +25,11 @@
|
||||
}
|
||||
|
||||
:root {
|
||||
font-family: var(--font-inter);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--background: oklch(0.145 0 0);
|
||||
font-family: var(--font-inter);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--background: oklch(0.145 0 0);
|
||||
|
||||
--toastify-color-dark: var(--color-mineshaft-700);
|
||||
--toastify-color-dark: var(--color-mineshaft-700);
|
||||
}
|
||||
|
||||
@theme {
|
||||
@@ -45,16 +41,16 @@
|
||||
--color-background: #19191c;
|
||||
--color-foreground: white;
|
||||
--color-success: #2ecc71;
|
||||
--color-info: #34c2db;
|
||||
--color-info: #63b0bd;
|
||||
--color-warning: #f1c40f;
|
||||
--color-danger: #e74c3c;
|
||||
--color-org: #30B3FF;
|
||||
--color-org: #30b3ff;
|
||||
--color-sub-org: #96ff59;
|
||||
--color-project: #e0ed34;
|
||||
--color-neutral: #adaeb0;
|
||||
|
||||
/*legacy color schema */
|
||||
--color-org-v1: #30B3FF;
|
||||
--color-org-v1: #30b3ff;
|
||||
--color-namespace-v1: #96ff59;
|
||||
|
||||
/* Primary */
|
||||
@@ -418,15 +414,15 @@
|
||||
}
|
||||
|
||||
.Toastify__toast {
|
||||
@apply rounded-md;
|
||||
@apply rounded-md;
|
||||
}
|
||||
|
||||
.Toastify__toast-body {
|
||||
@apply items-start;
|
||||
@apply items-start;
|
||||
}
|
||||
|
||||
.Toastify__toast-icon {
|
||||
@apply w-4 pt-1;
|
||||
@apply w-4 pt-1;
|
||||
}
|
||||
|
||||
.tags-conic-bg {
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Link, useMatchRoute } from "@tanstack/react-router";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
import { Tab, TabList, Tabs, Tooltip } from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
|
||||
const generalTabs = [
|
||||
{
|
||||
@@ -60,6 +61,7 @@ const generalTabs = [
|
||||
|
||||
export const AdminNavBar = () => {
|
||||
const matchRoute = useMatchRoute();
|
||||
const { currentOrg } = useOrganization();
|
||||
|
||||
return (
|
||||
<div className="border-b border-mineshaft-600 bg-mineshaft-900">
|
||||
@@ -74,7 +76,7 @@ export const AdminNavBar = () => {
|
||||
<Tabs value="selected">
|
||||
<TabList className="border-b-0">
|
||||
<Tooltip position="bottom" content="Back to organization">
|
||||
<Link to="/organization/projects">
|
||||
<Link to="/organizations/$orgId/projects" params={{ orgId: currentOrg.id }}>
|
||||
<Tab value="back">
|
||||
<FontAwesomeIcon icon={faArrowLeft} />
|
||||
</Tab>
|
||||
|
||||
@@ -2,19 +2,20 @@ import { Link, Outlet, useLocation } from "@tanstack/react-router";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
import { Tab, TabList, Tabs } from "@app/components/v2";
|
||||
import { useProject, useProjectPermission } from "@app/context";
|
||||
import { useOrganization, useProject, useProjectPermission } from "@app/context";
|
||||
|
||||
import { AssumePrivilegeModeBanner } from "../ProjectLayout/components/AssumePrivilegeModeBanner";
|
||||
|
||||
export const KmsLayout = () => {
|
||||
const { currentProject } = useProject();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { assumedPrivilegeDetails } = useProjectPermission();
|
||||
|
||||
const location = useLocation();
|
||||
|
||||
return (
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden">
|
||||
<div className="border-b border-mineshaft-600 bg-mineshaft-900">
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden bg-mineshaft-900">
|
||||
<div className="border-y border-t-project/10 border-b-project/5 bg-gradient-to-b from-project/[0.075] to-project/[0.025] px-4 pt-0.5">
|
||||
<motion.div
|
||||
key="menu-project-items"
|
||||
initial={{ x: -150 }}
|
||||
@@ -27,24 +28,27 @@ export const KmsLayout = () => {
|
||||
<Tabs value="selected">
|
||||
<TabList className="border-b-0">
|
||||
<Link
|
||||
to="/projects/kms/$projectId/overview"
|
||||
to="/organizations/$orgId/projects/kms/$projectId/overview"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Overview</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/kms/$projectId/kmip"
|
||||
to="/organizations/$orgId/projects/kms/$projectId/kmip"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>KMIP</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/kms/$projectId/access-management"
|
||||
to="/organizations/$orgId/projects/kms/$projectId/access-management"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -62,16 +66,18 @@ export const KmsLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/kms/$projectId/audit-logs"
|
||||
to="/organizations/$orgId/projects/kms/$projectId/audit-logs"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Audit Logs</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/kms/$projectId/settings"
|
||||
to="/organizations/$orgId/projects/kms/$projectId/settings"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -22,8 +22,8 @@ import {
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { Link, useLocation, useNavigate, useRouter, useRouterState } from "@tanstack/react-router";
|
||||
import { UserPlusIcon } from "lucide-react";
|
||||
import { Link, useLocation, useNavigate, useRouter } from "@tanstack/react-router";
|
||||
import { ChevronRight, UserPlusIcon } from "lucide-react";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
import { Mfa } from "@app/components/auth/Mfa";
|
||||
@@ -31,7 +31,6 @@ import { createNotification } from "@app/components/notifications";
|
||||
import { OrgPermissionCan } from "@app/components/permissions";
|
||||
import SecurityClient from "@app/components/utilities/SecurityClient";
|
||||
import {
|
||||
BreadcrumbContainer,
|
||||
Button,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -43,7 +42,6 @@ import {
|
||||
IconButton,
|
||||
Modal,
|
||||
ModalContent,
|
||||
TBreadcrumbFormat,
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { Badge, InstanceIcon, OrgIcon, SubOrgIcon } from "@app/components/v3";
|
||||
@@ -69,6 +67,7 @@ import { MfaMethod } from "@app/hooks/api/auth/types";
|
||||
import { getAuthToken } from "@app/hooks/api/reactQuery";
|
||||
import { Organization, SubscriptionPlan } from "@app/hooks/api/types";
|
||||
import { AuthMethod } from "@app/hooks/api/users/types";
|
||||
import { ProjectSelect } from "@app/layouts/ProjectLayout/components/ProjectSelect";
|
||||
import { navigateUserToOrg } from "@app/pages/auth/LoginPage/Login.utils";
|
||||
|
||||
import { ServerAdminsPanel } from "../ServerAdminsPanel/ServerAdminsPanel";
|
||||
@@ -183,9 +182,6 @@ export const Navbar = () => {
|
||||
}
|
||||
}, [subscription, isBillingPage, isModalIntrusive]);
|
||||
|
||||
const matches = useRouterState({ select: (s) => s.matches.at(-1)?.context });
|
||||
const breadcrumbs = matches && "breadcrumbs" in matches ? matches.breadcrumbs : undefined;
|
||||
|
||||
const handleOrgChange = async (orgId: string) => {
|
||||
queryClient.removeQueries({ queryKey: authKeys.getAuthToken });
|
||||
queryClient.removeQueries({ queryKey: projectKeys.getAllUserProjects() });
|
||||
@@ -249,7 +245,9 @@ export const Navbar = () => {
|
||||
|
||||
const isServerAdminPanel = location.pathname.startsWith("/admin");
|
||||
|
||||
const isOrgScope = location.pathname.startsWith("/organization"); // TODO: scott/akhil is this adequate?
|
||||
const isProjectScope =
|
||||
location.pathname.startsWith(`/organizations/${currentOrg.id}/projects`) &&
|
||||
location.pathname !== `/organizations/${currentOrg.id}/projects`;
|
||||
|
||||
const handleOrgNav = async (org: Organization) => {
|
||||
if (currentOrg?.id === org.id) return;
|
||||
@@ -279,64 +277,59 @@ export const Navbar = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="z-10 flex min-h-12 items-center bg-mineshaft-900 px-4 pt-1">
|
||||
<div className="mr-auto flex items-center overflow-hidden">
|
||||
<div className="shrink-0">
|
||||
<Link to="/organization/projects">
|
||||
<div className="z-10 flex min-h-12 items-center bg-mineshaft-900 px-4">
|
||||
<div className="mr-auto flex h-full min-w-34 items-center">
|
||||
<div className="mt-0.5 shrink-0">
|
||||
<Link to="/organizations/$orgId/projects" params={{ orgId: currentOrg.id }}>
|
||||
<img alt="infisical logo" src="/images/logotransparent.png" className="h-4" />
|
||||
</Link>
|
||||
</div>
|
||||
<p className="pr-3 pl-1 text-lg text-mineshaft-400/70">/</p>
|
||||
<ChevronRight size={18} className="mx-3 mt-[3px] text-mineshaft-400/70" />
|
||||
{isServerAdminPanel ? (
|
||||
<>
|
||||
<Link
|
||||
to="/admin"
|
||||
className="group flex cursor-pointer items-center gap-2 text-sm text-white transition-all duration-100 hover:text-primary"
|
||||
>
|
||||
<InstanceIcon className="size-3.5 text-xs text-bunker-300" />
|
||||
<div className="whitespace-nowrap">Server Console</div>
|
||||
</Link>
|
||||
<p className="pr-3 pl-3 text-lg text-mineshaft-400/70">/</p>
|
||||
{breadcrumbs ? (
|
||||
// scott: remove /admin as we show server console above
|
||||
<BreadcrumbContainer breadcrumbs={breadcrumbs.slice(1) as TBreadcrumbFormat[]} />
|
||||
) : null}
|
||||
</>
|
||||
<Link
|
||||
to="/admin"
|
||||
className="group flex cursor-pointer items-center gap-2 text-sm text-white transition-all duration-100 hover:text-primary"
|
||||
>
|
||||
<InstanceIcon className="size-3.5 text-xs text-bunker-300" />
|
||||
<div className="whitespace-nowrap">Server Console</div>
|
||||
</Link>
|
||||
) : (
|
||||
<>
|
||||
<div className="flex min-w-12 items-center overflow-hidden">
|
||||
<div
|
||||
className={twMerge(
|
||||
"relative flex min-w-16 items-center self-end rounded-t-md border-x border-t pt-1.5 pr-2 pb-2.5 pl-3",
|
||||
!isProjectScope && !isSubOrganization
|
||||
? "border-org/15 bg-gradient-to-b from-org/10 to-org/[0.075]"
|
||||
: "border-transparent"
|
||||
)}
|
||||
>
|
||||
{/* scott: the below is used to hide the top border from the org nav bar */}
|
||||
{!isProjectScope && !isSubOrganization && (
|
||||
<div className="absolute -bottom-px left-0 h-px w-full bg-mineshaft-900">
|
||||
<div className="h-full bg-org/[0.075]" />
|
||||
</div>
|
||||
)}
|
||||
<DropdownMenu modal={false} open={isOrgSelectOpen} onOpenChange={setIsOrgSelectOpen}>
|
||||
<div className="group flex cursor-pointer items-center gap-2 overflow-hidden text-sm text-white transition-all duration-100 hover:text-primary">
|
||||
<Badge
|
||||
asChild
|
||||
variant="org"
|
||||
isTruncatable
|
||||
// TODO(scott): either add badge size/style variant or create designated component for namespace/org nav bar
|
||||
className={twMerge(
|
||||
"gap-x-1.5 text-sm",
|
||||
(!isOrgScope || isSubOrganization) &&
|
||||
"bg-transparent text-mineshaft-200 hover:!bg-transparent hover:underline [&>svg]:!text-org"
|
||||
)}
|
||||
<div className="group mr-1 flex min-w-0 cursor-pointer items-center gap-2 overflow-hidden text-sm text-white transition-all duration-100">
|
||||
<button
|
||||
className="flex cursor-pointer items-center gap-x-2 truncate whitespace-nowrap"
|
||||
type="button"
|
||||
onClick={async () => {
|
||||
navigate({
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId: currentOrg.id }
|
||||
});
|
||||
if (isSubOrganization) {
|
||||
await router.invalidate({ sync: true }).catch(() => null);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={async () => {
|
||||
navigate({
|
||||
to: "/organization/projects",
|
||||
search: (search) => ({ ...search, subOrganization: undefined })
|
||||
});
|
||||
if (isSubOrganization) {
|
||||
await router.invalidate({ sync: true }).catch(() => null);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<OrgIcon className="size-[12px]" />
|
||||
<span>{currentOrg?.name}</span>
|
||||
</button>
|
||||
</Badge>
|
||||
<div className="mr-1 hidden rounded-sm border border-mineshaft-500 px-1 text-xs text-bunker-300 no-underline! md:inline-block">
|
||||
{getPlan(subscription)}
|
||||
</div>
|
||||
<OrgIcon className={twMerge("size-[14px] shrink-0 text-org")} />
|
||||
<span className="truncate">{currentOrg?.name}</span>
|
||||
<Badge variant="org" className="hidden lg:inline-flex">
|
||||
Organization
|
||||
</Badge>
|
||||
</button>
|
||||
{subscription.cardDeclined && (
|
||||
<Tooltip
|
||||
content={`Your payment could not be processed${subscription.cardDeclinedReason ? `: ${subscription.cardDeclinedReason}` : ""}. Please update your payment method to continue enjoying premium features.`}
|
||||
@@ -407,8 +400,8 @@ export const Navbar = () => {
|
||||
<DropdownMenuItem
|
||||
onClick={async () => {
|
||||
navigate({
|
||||
to: "/organization/projects",
|
||||
search: (prev) => ({ ...prev, subOrganization: subOrg.name })
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId: subOrg.id }
|
||||
});
|
||||
await router.invalidate({ sync: true }).catch(() => null);
|
||||
}}
|
||||
@@ -477,11 +470,11 @@ export const Navbar = () => {
|
||||
// TODO(scott): either add badge size/style variant or create designated component for namespace/org nav bar
|
||||
className={twMerge(
|
||||
"gap-x-1.5 text-sm",
|
||||
!isOrgScope &&
|
||||
isProjectScope &&
|
||||
"min-w-6 bg-transparent text-mineshaft-200 hover:!bg-transparent hover:underline [&>svg]:!text-sub-org"
|
||||
)}
|
||||
>
|
||||
<Link to="/organization/projects">
|
||||
<Link to="/organizations/$orgId/projects" params={{ orgId: currentOrg.id }}>
|
||||
<SubOrgIcon className="size-[12px]" />
|
||||
<span>{currentOrg.subOrganization.name}</span>
|
||||
</Link>
|
||||
@@ -511,8 +504,8 @@ export const Navbar = () => {
|
||||
<DropdownMenuItem
|
||||
onClick={async () => {
|
||||
navigate({
|
||||
to: "/organization/projects",
|
||||
search: (prev) => ({ ...prev, subOrganization: subOrg.name })
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId: subOrg.id }
|
||||
});
|
||||
await router.invalidate({ sync: true }).catch(() => null);
|
||||
}}
|
||||
@@ -541,21 +534,17 @@ export const Navbar = () => {
|
||||
</DropdownMenu>
|
||||
</>
|
||||
)}
|
||||
{!isOrgScope && (
|
||||
{isProjectScope && (
|
||||
<>
|
||||
<p className="pr-3 pl-1 text-lg text-mineshaft-400/70">/</p>
|
||||
{breadcrumbs ? (
|
||||
<BreadcrumbContainer
|
||||
className="min-w-[15rem] flex-1"
|
||||
breadcrumbs={[breadcrumbs[0]] as TBreadcrumbFormat[]}
|
||||
/>
|
||||
) : null}
|
||||
<ChevronRight size={18} className="mx-3 mt-[3px] text-mineshaft-400/70" />
|
||||
<ProjectSelect />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{subscription && subscription.slug === "starter" && !subscription.has_used_trial && (
|
||||
|
||||
{subscription && subscription.slug === "starter" && !subscription.has_used_trial ? (
|
||||
<Tooltip content="Start Free Pro Trial">
|
||||
<Button
|
||||
variant="plain"
|
||||
@@ -576,6 +565,10 @@ export const Navbar = () => {
|
||||
Free Pro Trial
|
||||
</Button>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<div className="mt-0.5 mr-3 hidden rounded-sm border border-mineshaft-400 px-1 text-xs text-mineshaft-100 no-underline! opacity-50 md:inline-block">
|
||||
{getPlan(subscription)}
|
||||
</div>
|
||||
)}
|
||||
{/* eslint-disable-next-line no-nested-ternary */}
|
||||
{!location.pathname.startsWith("/admin") ? (
|
||||
@@ -593,14 +586,15 @@ export const Navbar = () => {
|
||||
isAllowed ? (
|
||||
<Link
|
||||
className="mr-2 flex h-[34px] items-center rounded-md border border-mineshaft-500 px-2.5 py-1.5 text-sm whitespace-nowrap text-mineshaft-200 hover:bg-mineshaft-600"
|
||||
to="/organization/access-management"
|
||||
to="/organizations/$orgId/access-management"
|
||||
params={{ orgId: currentOrg.id }}
|
||||
search={{
|
||||
selectedTab: "members",
|
||||
action: "invite-members"
|
||||
}}
|
||||
>
|
||||
<UserPlusIcon className="inline-block size-3.5" />
|
||||
<span className="ml-2 hidden md:inline-block">Invite Members</span>
|
||||
<span className="ml-2 hidden md:inline-block">Invite Users</span>
|
||||
</Link>
|
||||
) : null
|
||||
}
|
||||
@@ -696,14 +690,15 @@ export const Navbar = () => {
|
||||
{(isAllowed) =>
|
||||
isAllowed ? (
|
||||
<Link
|
||||
to="/organization/access-management"
|
||||
to="/organizations/$orgId/access-management"
|
||||
params={{ orgId: currentOrg.id }}
|
||||
search={{
|
||||
selectedTab: "members",
|
||||
action: "invite-members"
|
||||
}}
|
||||
>
|
||||
<DropdownMenuItem icon={<FontAwesomeIcon icon={faUserPlus} />}>
|
||||
Invite Members
|
||||
Invite Users
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
) : null
|
||||
@@ -778,7 +773,11 @@ export const Navbar = () => {
|
||||
</div>
|
||||
<div className="mt-4">
|
||||
<div className="flex space-x-3">
|
||||
<Link to="/organization/billing" className="inline-flex">
|
||||
<Link
|
||||
to="/organizations/$orgId/billing"
|
||||
params={{ orgId: currentOrg.id }}
|
||||
className="inline-flex"
|
||||
>
|
||||
<Button
|
||||
colorSchema="primary"
|
||||
variant="solid"
|
||||
|
||||
+2
-2
@@ -47,8 +47,8 @@ export const NewSubOrganizationForm = ({ onClose }: ContentProps) => {
|
||||
onClose();
|
||||
|
||||
navigate({
|
||||
to: "/organization/projects",
|
||||
search: (prev) => ({ ...prev, subOrganization: organization.name })
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId: organization.id }
|
||||
});
|
||||
await router.invalidate({ sync: true }).catch(() => null);
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const OrgNavBar = ({ isHidden }: Props) => {
|
||||
const { isRootOrganization } = useOrganization();
|
||||
const { isRootOrganization, currentOrg } = useOrganization();
|
||||
const { popUp, handlePopUpToggle } = usePopUp(["createOrg"] as const);
|
||||
|
||||
const { pathname } = useLocation();
|
||||
@@ -19,9 +19,9 @@ export const OrgNavBar = ({ isHidden }: Props) => {
|
||||
const variant = isRootOrganization ? "org" : "namespace";
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="bg-mineshaft-900">
|
||||
{!isHidden && (
|
||||
<div className="dark flex w-full flex-col overflow-x-hidden border-b border-mineshaft-600 bg-mineshaft-900 px-4">
|
||||
<div className="dark flex w-full flex-col overflow-x-hidden border-y border-t-org/15 border-b-org/5 bg-gradient-to-b from-org/[0.075] to-org/[0.025] px-4 pt-0.5">
|
||||
<motion.div
|
||||
key="menu-org-items"
|
||||
initial={{ x: -150 }}
|
||||
@@ -32,43 +32,47 @@ export const OrgNavBar = ({ isHidden }: Props) => {
|
||||
<nav className="w-full">
|
||||
<Tabs value="selected">
|
||||
<TabList className="border-b-0">
|
||||
<Link to="/organization/projects">
|
||||
<Link to="/organizations/$orgId/projects" params={{ orgId: currentOrg.id }}>
|
||||
{({ isActive }) => (
|
||||
<Tab variant={variant} value={isActive ? "selected" : ""}>
|
||||
Overview
|
||||
</Tab>
|
||||
)}
|
||||
</Link>
|
||||
<Link to="/organization/app-connections">
|
||||
<Link
|
||||
to="/organizations/$orgId/app-connections"
|
||||
params={{ orgId: currentOrg.id }}
|
||||
>
|
||||
{({ isActive }) => (
|
||||
<Tab variant={variant} value={isActive ? "selected" : ""}>
|
||||
App Connections
|
||||
</Tab>
|
||||
)}
|
||||
</Link>
|
||||
<Link to="/organization/networking">
|
||||
<Link to="/organizations/$orgId/networking" params={{ orgId: currentOrg.id }}>
|
||||
{({ isActive }) => (
|
||||
<Tab variant={variant} value={isActive ? "selected" : ""}>
|
||||
Networking
|
||||
</Tab>
|
||||
)}
|
||||
</Link>
|
||||
<Link to="/organization/secret-sharing">
|
||||
<Link to="/organizations/$orgId/secret-sharing" params={{ orgId: currentOrg.id }}>
|
||||
{({ isActive }) => (
|
||||
<Tab value={isActive ? "selected" : ""} variant={variant}>
|
||||
Secret Sharing
|
||||
</Tab>
|
||||
)}
|
||||
</Link>
|
||||
<Link to="/organization/access-management">
|
||||
<Link
|
||||
to="/organizations/$orgId/access-management"
|
||||
params={{ orgId: currentOrg.id }}
|
||||
>
|
||||
{({ isActive }) => (
|
||||
<Tab
|
||||
variant={variant}
|
||||
value={
|
||||
isActive ||
|
||||
pathname.match(
|
||||
/organization\/members|organization\/identities|organization\/groups|organization\/roles/
|
||||
)
|
||||
pathname.match(/organizations\/[^/]+\/(members|identities|groups|roles)/)
|
||||
? "selected"
|
||||
: ""
|
||||
}
|
||||
@@ -77,7 +81,7 @@ export const OrgNavBar = ({ isHidden }: Props) => {
|
||||
</Tab>
|
||||
)}
|
||||
</Link>
|
||||
<Link to="/organization/audit-logs">
|
||||
<Link to="/organizations/$orgId/audit-logs" params={{ orgId: currentOrg.id }}>
|
||||
{({ isActive }) => (
|
||||
<Tab variant={variant} value={isActive ? "selected" : ""}>
|
||||
Audit Logs
|
||||
@@ -85,7 +89,7 @@ export const OrgNavBar = ({ isHidden }: Props) => {
|
||||
)}
|
||||
</Link>
|
||||
{isRootOrganization && (
|
||||
<Link to="/organization/billing">
|
||||
<Link to="/organizations/$orgId/billing" params={{ orgId: currentOrg.id }}>
|
||||
{({ isActive }) => (
|
||||
<Tab variant={variant} value={isActive ? "selected" : ""}>
|
||||
Usage & Billing
|
||||
@@ -93,7 +97,7 @@ export const OrgNavBar = ({ isHidden }: Props) => {
|
||||
)}
|
||||
</Link>
|
||||
)}
|
||||
<Link to="/organization/settings">
|
||||
<Link to="/organizations/$orgId/settings" params={{ orgId: currentOrg.id }}>
|
||||
{({ isActive }) => (
|
||||
<Tab variant={variant} value={isActive ? "selected" : ""}>
|
||||
Settings
|
||||
@@ -110,6 +114,6 @@ export const OrgNavBar = ({ isHidden }: Props) => {
|
||||
isOpen={popUp?.createOrg?.isOpen}
|
||||
onClose={() => handlePopUpToggle("createOrg", false)}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,13 +4,14 @@ import { motion } from "framer-motion";
|
||||
|
||||
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
||||
import { Tab, TabList, Tabs } from "@app/components/v2";
|
||||
import { useProject, useProjectPermission, useSubscription } from "@app/context";
|
||||
import { useOrganization, useProject, useProjectPermission, useSubscription } from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
|
||||
import { AssumePrivilegeModeBanner } from "../ProjectLayout/components/AssumePrivilegeModeBanner";
|
||||
|
||||
export const PamLayout = () => {
|
||||
const { currentProject } = useProject();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { subscription } = useSubscription();
|
||||
const { assumedPrivilegeDetails } = useProjectPermission();
|
||||
const location = useLocation();
|
||||
@@ -28,8 +29,8 @@ export const PamLayout = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden">
|
||||
<div className="border-b border-mineshaft-600 bg-mineshaft-900">
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden bg-mineshaft-900">
|
||||
<div className="border-y border-t-project/10 border-b-project/5 bg-gradient-to-b from-project/[0.075] to-project/[0.025] px-4 pt-0.5">
|
||||
<motion.div
|
||||
key="menu-project-items"
|
||||
initial={{ x: -150 }}
|
||||
@@ -42,32 +43,36 @@ export const PamLayout = () => {
|
||||
<Tabs value="selected">
|
||||
<TabList className="border-b-0">
|
||||
<Link
|
||||
to="/projects/pam/$projectId/accounts"
|
||||
to="/organizations/$orgId/projects/pam/$projectId/accounts"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Accounts</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/pam/$projectId/resources"
|
||||
to="/organizations/$orgId/projects/pam/$projectId/resources"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Resources</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/pam/$projectId/sessions"
|
||||
to="/organizations/$orgId/projects/pam/$projectId/sessions"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Sessions</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/pam/$projectId/access-management"
|
||||
to="/organizations/$orgId/projects/pam/$projectId/access-management"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -85,16 +90,18 @@ export const PamLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/pam/$projectId/audit-logs"
|
||||
to="/organizations/$orgId/projects/pam/$projectId/audit-logs"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Audit Logs</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/pam/$projectId/settings"
|
||||
to="/organizations/$orgId/projects/pam/$projectId/settings"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Link, Outlet, useLocation } from "@tanstack/react-router";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
import { Tab, TabList, Tabs } from "@app/components/v2";
|
||||
import { useProject, useProjectPermission, useSubscription } from "@app/context";
|
||||
import { useOrganization, useProject, useProjectPermission, useSubscription } from "@app/context";
|
||||
import {
|
||||
useListWorkspaceCertificateTemplates,
|
||||
useListWorkspacePkiSubscribers
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import { AssumePrivilegeModeBanner } from "../ProjectLayout/components/AssumePrivilegeModeBanner";
|
||||
|
||||
export const PkiManagerLayout = () => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentProject } = useProject();
|
||||
const { assumedPrivilegeDetails } = useProjectPermission();
|
||||
const { subscription } = useSubscription();
|
||||
@@ -28,8 +29,8 @@ export const PkiManagerLayout = () => {
|
||||
|
||||
const location = useLocation();
|
||||
return (
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden">
|
||||
<div className="border-b border-mineshaft-600 bg-mineshaft-900">
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden bg-mineshaft-900">
|
||||
<div className="border-y border-t-project/10 border-b-project/5 bg-gradient-to-b from-project/[0.075] to-project/[0.025] px-4 pt-0.5">
|
||||
<motion.div
|
||||
key="menu-project-items"
|
||||
initial={{ x: -150 }}
|
||||
@@ -42,16 +43,18 @@ export const PkiManagerLayout = () => {
|
||||
<Tabs value="selected">
|
||||
<TabList className="border-b-0">
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/policies"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/policies"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Certificates</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/certificate-authorities"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/certificate-authorities"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -62,24 +65,27 @@ export const PkiManagerLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/alerting"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/alerting"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Alerting</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/integrations"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/integrations"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Integrations</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/app-connections"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/app-connections"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -89,8 +95,9 @@ export const PkiManagerLayout = () => {
|
||||
<>
|
||||
{(subscription.pkiLegacyTemplates || hasExistingSubscribers) && (
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/subscribers"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/subscribers"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -101,8 +108,9 @@ export const PkiManagerLayout = () => {
|
||||
)}
|
||||
{(subscription.pkiLegacyTemplates || hasExistingTemplates) && (
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/certificate-templates"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/certificate-templates"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -116,8 +124,9 @@ export const PkiManagerLayout = () => {
|
||||
</>
|
||||
)}
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/access-management"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/access-management"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -135,16 +144,18 @@ export const PkiManagerLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/audit-logs"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/audit-logs"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Audit Logs</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/settings"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/settings"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
|
||||
+3
-1
@@ -38,7 +38,9 @@ export const AssumePrivilegeModeBanner = () => {
|
||||
{
|
||||
onSuccess: () => {
|
||||
const url = `${getProjectHomePage(currentProject.type, currentProject.environments)}${isSubOrganization ? `?subOrganization=${currentOrg.slug}` : ""}`;
|
||||
window.location.href = url.replace("$projectId", currentProject.id);
|
||||
window.location.assign(
|
||||
url.replace("$orgId", currentOrg.id).replace("$projectId", currentProject.id)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
faStar as faSolidStar
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Link, linkOptions } from "@tanstack/react-router";
|
||||
import { Link, linkOptions, useParams } from "@tanstack/react-router";
|
||||
|
||||
import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal";
|
||||
import { OrgPermissionCan } from "@app/components/permissions";
|
||||
@@ -46,7 +46,7 @@ const PROJECT_TYPE_NAME: Record<ProjectType, string> = {
|
||||
[ProjectType.SecretScanning]: "Secret Scanning"
|
||||
};
|
||||
|
||||
export const ProjectSelect = () => {
|
||||
const ProjectSelectInner = () => {
|
||||
const [searchProject, setSearchProject] = useState("");
|
||||
const { currentProject: currentWorkspace } = useProject();
|
||||
const { currentOrg } = useOrganization();
|
||||
@@ -92,23 +92,24 @@ export const ProjectSelect = () => {
|
||||
}, [projects, projectFavorites, currentWorkspace]);
|
||||
|
||||
return (
|
||||
<div className="mr-2 flex items-center gap-1 overflow-hidden">
|
||||
<div className="relative mr-2 flex min-w-16 items-center gap-1 self-end rounded-t-md border-x border-t border-project/10 bg-gradient-to-b from-project/10 to-project/[0.075] pt-1.5 pr-1 pb-2.5 pl-3">
|
||||
{/* scott: the below is used to hide the top border from the org nav bar */}
|
||||
<div className="absolute -bottom-px left-0 h-px w-full bg-mineshaft-900">
|
||||
<div className="h-full bg-project/[0.075]" />
|
||||
</div>
|
||||
<DropdownMenu modal={false}>
|
||||
<Link
|
||||
to={getProjectHomePage(currentWorkspace.type, currentWorkspace.environments)}
|
||||
params={{
|
||||
projectId: currentWorkspace.id
|
||||
projectId: currentWorkspace.id,
|
||||
orgId: currentWorkspace.orgId
|
||||
}}
|
||||
className="group flex cursor-pointer items-center gap-x-1.5 overflow-hidden hover:text-white"
|
||||
className="group flex cursor-pointer items-center gap-x-2 overflow-hidden pt-0.5 text-sm text-white"
|
||||
>
|
||||
<p className="inline-block truncate text-mineshaft-200 group-hover:underline">
|
||||
{currentWorkspace?.name}
|
||||
</p>
|
||||
<Badge variant="project">
|
||||
<ProjectIcon />
|
||||
<span className="hidden sm:inline-block">
|
||||
{currentWorkspace.type ? PROJECT_TYPE_NAME[currentWorkspace.type] : "Project"}
|
||||
</span>
|
||||
<ProjectIcon className="size-[14px] shrink-0 text-project" />
|
||||
<span className="truncate">{currentWorkspace?.name}</span>
|
||||
<Badge variant="project" className="hidden lg:inline-flex">
|
||||
{currentWorkspace.type ? PROJECT_TYPE_NAME[currentWorkspace.type] : "Project"}
|
||||
</Badge>
|
||||
</Link>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -117,7 +118,7 @@ export const ProjectSelect = () => {
|
||||
variant="plain"
|
||||
colorSchema="secondary"
|
||||
ariaLabel="switch-project"
|
||||
className="px-2 py-1"
|
||||
className="top-px px-2 py-1"
|
||||
>
|
||||
<FontAwesomeIcon icon={faCaretDown} className="text-xs text-bunker-300" />
|
||||
</IconButton>
|
||||
@@ -154,14 +155,15 @@ export const ProjectSelect = () => {
|
||||
const url = linkOptions({
|
||||
to: getProjectHomePage(workspace.type, workspace.environments),
|
||||
params: {
|
||||
projectId: workspace.id
|
||||
projectId: workspace.id,
|
||||
orgId: workspace.orgId
|
||||
},
|
||||
search: {
|
||||
subOrganization: currentOrg?.subOrganization?.name
|
||||
}
|
||||
});
|
||||
const urlInstance = new URL(
|
||||
`${window.location.origin}/${url.to.replaceAll("$projectId", workspace.id)}`
|
||||
`${window.location.origin}${url.to.replaceAll("$orgId", url.params.orgId).replaceAll("$projectId", url.params.projectId)}`
|
||||
);
|
||||
if (currentOrg?.subOrganization) {
|
||||
urlInstance.searchParams.set(
|
||||
@@ -236,3 +238,14 @@ export const ProjectSelect = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ProjectSelect = () => {
|
||||
const params = useParams({ strict: false });
|
||||
|
||||
// Return null during navigation when projectId is not available
|
||||
if (!params.projectId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <ProjectSelectInner />;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { motion } from "framer-motion";
|
||||
|
||||
import { Tab, TabList, Tabs } from "@app/components/v2";
|
||||
import { Badge } from "@app/components/v3";
|
||||
import { useProject, useProjectPermission } from "@app/context";
|
||||
import { useOrganization, useProject, useProjectPermission } from "@app/context";
|
||||
import {
|
||||
useGetAccessRequestsCount,
|
||||
useGetSecretApprovalRequestCount,
|
||||
@@ -15,6 +15,7 @@ import { AssumePrivilegeModeBanner } from "../ProjectLayout/components/AssumePri
|
||||
export const SecretManagerLayout = () => {
|
||||
const { currentProject, projectId } = useProject();
|
||||
const { assumedPrivilegeDetails } = useProjectPermission();
|
||||
const { currentOrg } = useOrganization();
|
||||
const location = useLocation();
|
||||
|
||||
const projectSlug = currentProject?.slug || "";
|
||||
@@ -38,8 +39,8 @@ export const SecretManagerLayout = () => {
|
||||
(secretApprovalReqCount?.open || 0) + (accessApprovalRequestCount?.pendingCount || 0);
|
||||
|
||||
return (
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden">
|
||||
<div className="border-b border-mineshaft-600 bg-mineshaft-900">
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden bg-mineshaft-900">
|
||||
<div className="border-y border-t-project/10 border-b-project/5 bg-gradient-to-b from-project/[0.075] to-project/[0.025] px-4 pt-0.5">
|
||||
<motion.div
|
||||
key="menu-project-items"
|
||||
initial={{ x: -150 }}
|
||||
@@ -52,8 +53,9 @@ export const SecretManagerLayout = () => {
|
||||
<Tabs value="selected">
|
||||
<TabList className="border-b-0">
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/overview"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/overview"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id,
|
||||
...(currentProject.environments.length
|
||||
? { envSlug: currentProject.environments[0]?.slug }
|
||||
@@ -73,8 +75,9 @@ export const SecretManagerLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/approval"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/approval"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -92,8 +95,9 @@ export const SecretManagerLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/integrations"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/integrations"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -101,8 +105,9 @@ export const SecretManagerLayout = () => {
|
||||
</Link>
|
||||
{Boolean(secretRotations?.length) && (
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/secret-rotation"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/secret-rotation"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -112,16 +117,18 @@ export const SecretManagerLayout = () => {
|
||||
</Link>
|
||||
)}
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/app-connections"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/app-connections"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>App Connections</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/access-management"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/access-management"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -139,16 +146,18 @@ export const SecretManagerLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/audit-logs"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/audit-logs"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Audit Logs</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-management/$projectId/settings"
|
||||
to="/organizations/$orgId/projects/secret-management/$projectId/settings"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Tab, TabList, Tabs } from "@app/components/v2";
|
||||
import { Badge } from "@app/components/v3";
|
||||
import {
|
||||
ProjectPermissionSub,
|
||||
useOrganization,
|
||||
useProject,
|
||||
useProjectPermission,
|
||||
useSubscription
|
||||
@@ -15,6 +16,7 @@ import { useGetSecretScanningUnresolvedFindingCount } from "@app/hooks/api/secre
|
||||
import { AssumePrivilegeModeBanner } from "../ProjectLayout/components/AssumePrivilegeModeBanner";
|
||||
|
||||
export const SecretScanningLayout = () => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentProject } = useProject();
|
||||
const { assumedPrivilegeDetails } = useProjectPermission();
|
||||
|
||||
@@ -36,8 +38,8 @@ export const SecretScanningLayout = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden">
|
||||
<div className="border-b border-mineshaft-600 bg-mineshaft-900">
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden bg-mineshaft-900">
|
||||
<div className="border-y border-t-project/10 border-b-project/5 bg-gradient-to-b from-project/[0.075] to-project/[0.025] px-4 pt-0.5">
|
||||
<motion.div
|
||||
key="menu-project-items"
|
||||
initial={{ x: -150 }}
|
||||
@@ -50,16 +52,18 @@ export const SecretScanningLayout = () => {
|
||||
<Tabs value="selected">
|
||||
<TabList className="border-b-0">
|
||||
<Link
|
||||
to="/projects/secret-scanning/$projectId/data-sources"
|
||||
to="/organizations/$orgId/projects/secret-scanning/$projectId/data-sources"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Data Sources</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-scanning/$projectId/findings"
|
||||
to="/organizations/$orgId/projects/secret-scanning/$projectId/findings"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -75,16 +79,18 @@ export const SecretScanningLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-scanning/$projectId/app-connections"
|
||||
to="/organizations/$orgId/projects/secret-scanning/$projectId/app-connections"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>App Connections</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-scanning/$projectId/access-management"
|
||||
to="/organizations/$orgId/projects/secret-scanning/$projectId/access-management"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -102,16 +108,18 @@ export const SecretScanningLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-scanning/$projectId/audit-logs"
|
||||
to="/organizations/$orgId/projects/secret-scanning/$projectId/audit-logs"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Audit Logs</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/secret-scanning/$projectId/settings"
|
||||
to="/organizations/$orgId/projects/secret-scanning/$projectId/settings"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Tab, TabList, Tabs } from "@app/components/v2";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
useOrganization,
|
||||
useProject,
|
||||
useProjectPermission
|
||||
} from "@app/context";
|
||||
@@ -13,13 +14,14 @@ import {
|
||||
import { AssumePrivilegeModeBanner } from "../ProjectLayout/components/AssumePrivilegeModeBanner";
|
||||
|
||||
export const SshLayout = () => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentProject } = useProject();
|
||||
const { assumedPrivilegeDetails } = useProjectPermission();
|
||||
const location = useLocation();
|
||||
|
||||
return (
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden">
|
||||
<div className="border-b border-mineshaft-600 bg-mineshaft-900">
|
||||
<div className="dark flex h-full w-full flex-col overflow-x-hidden bg-mineshaft-900">
|
||||
<div className="border-y border-t-project/10 border-b-project/5 bg-gradient-to-b from-project/[0.075] to-project/[0.025] px-4 pt-0.5">
|
||||
<motion.div
|
||||
key="menu-project-items"
|
||||
initial={{ x: -150 }}
|
||||
@@ -32,8 +34,9 @@ export const SshLayout = () => {
|
||||
<Tabs value="selected">
|
||||
<TabList className="border-b-0">
|
||||
<Link
|
||||
to="/projects/ssh/$projectId/overview"
|
||||
to="/organizations/$orgId/projects/ssh/$projectId/overview"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -54,8 +57,9 @@ export const SshLayout = () => {
|
||||
{(isAllowed) =>
|
||||
isAllowed && (
|
||||
<Link
|
||||
to="/projects/ssh/$projectId/cas"
|
||||
to="/organizations/$orgId/projects/ssh/$projectId/cas"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -71,8 +75,9 @@ export const SshLayout = () => {
|
||||
}
|
||||
</ProjectPermissionCan>
|
||||
<Link
|
||||
to="/projects/ssh/$projectId/access-management"
|
||||
to="/organizations/$orgId/projects/ssh/$projectId/access-management"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
@@ -90,16 +95,18 @@ export const SshLayout = () => {
|
||||
)}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/ssh/$projectId/audit-logs"
|
||||
to="/organizations/$orgId/projects/ssh/$projectId/audit-logs"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
{({ isActive }) => <Tab value={isActive ? "selected" : ""}>Audit Logs</Tab>}
|
||||
</Link>
|
||||
<Link
|
||||
to="/projects/ssh/$projectId/settings"
|
||||
to="/organizations/$orgId/projects/ssh/$projectId/settings"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -12,6 +12,8 @@ import { NotFoundPage } from "./pages/public/NotFoundPage/NotFoundPage";
|
||||
// Import the generated route tree
|
||||
import { routeTree } from "./routeTree.gen";
|
||||
|
||||
import "@fontsource/inter/400.css";
|
||||
import "@fontsource/inter/500.css";
|
||||
import "@xyflow/react/dist/style.css";
|
||||
import "nprogress/nprogress.css";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
|
||||
@@ -17,7 +17,7 @@ export const AccessManagementPage = () => {
|
||||
<div className="mx-auto mb-6 w-full max-w-8xl">
|
||||
<PageHeader
|
||||
scope="instance"
|
||||
title="Access Control"
|
||||
title="Server Admin Access Control"
|
||||
description="Manage server admins within your Infisical instance."
|
||||
/>
|
||||
<ServerAdminsTable />
|
||||
|
||||
@@ -29,7 +29,7 @@ export const ResourceOverviewPage = () => {
|
||||
Users
|
||||
</Tab>
|
||||
<Tab variant="instance" value="tab-identities">
|
||||
Identities
|
||||
Machine Identities
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanel value="tab-organizations">
|
||||
|
||||
@@ -90,7 +90,7 @@ const IdentityPanelTable = ({
|
||||
value={searchIdentityFilter}
|
||||
onChange={(e) => setSearchIdentityFilter(e.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||
placeholder="Search identities by name..."
|
||||
placeholder="Search machine identities by name..."
|
||||
className="flex-1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -350,8 +350,8 @@ const ViewMembersModalContent = ({
|
||||
className="my-auto bg-mineshaft-700"
|
||||
title={
|
||||
members.length
|
||||
? "No organization members match search..."
|
||||
: "No organization members found"
|
||||
? "No organization users match search..."
|
||||
: "No organization users found"
|
||||
}
|
||||
icon={faUsers}
|
||||
/>
|
||||
|
||||
@@ -7,7 +7,8 @@ export const Route = createFileRoute("/_authenticate/_inject-org-details/admin/_
|
||||
beforeLoad: ({ context }) => {
|
||||
if (!context.user.superAdmin) {
|
||||
throw redirect({
|
||||
to: "/organization/projects"
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId: context.organizationId }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,10 @@ export const navigateUserToOrg = async (navigate: NavigateFn, organizationId?: s
|
||||
|
||||
if (organizationId) {
|
||||
localStorage.setItem("orgData.id", organizationId);
|
||||
navigate({ to: "/organization/projects" });
|
||||
navigate({
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId: organizationId }
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -20,11 +23,14 @@ export const navigateUserToOrg = async (navigate: NavigateFn, organizationId?: s
|
||||
// user is part of at least 1 non-auth enforced org
|
||||
const userOrg = nonAuthEnforcedOrgs[0] && nonAuthEnforcedOrgs[0].id;
|
||||
localStorage.setItem("orgData.id", userOrg);
|
||||
navigate({ to: "/organization/projects" });
|
||||
navigate({
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId: userOrg }
|
||||
});
|
||||
} else {
|
||||
// user is not part of any non-auth enforced orgs
|
||||
localStorage.removeItem("orgData.id");
|
||||
navigate({ to: "/organization/none" });
|
||||
navigate({ to: "/organizations/none" });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ export const SelectOrganizationSection = () => {
|
||||
// Case: User has no organizations.
|
||||
// This can happen if the user was previously a member, but the organization was deleted or the user was removed.
|
||||
if (organizations.data.length === 0) {
|
||||
navigate({ to: "/organization/none" });
|
||||
navigate({ to: "/organizations/none" });
|
||||
} else if (organizations.data.length === 1) {
|
||||
if (callbackPort) {
|
||||
handleCliRedirect();
|
||||
|
||||
@@ -122,7 +122,8 @@ export const SignupInvitePage = () => {
|
||||
localStorage.setItem("orgData.id", orgId);
|
||||
|
||||
navigate({
|
||||
to: "/organization/projects"
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId }
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ export const SignUpPage = () => {
|
||||
|
||||
if (!serverDetails?.emailConfigured && step === 4) {
|
||||
navigate({
|
||||
to: "/organization/projects"
|
||||
to: "/"
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
+2
-1
@@ -129,7 +129,8 @@ export const UserInfoSSOStep = ({
|
||||
|
||||
localStorage.setItem("orgData.id", orgId);
|
||||
navigate({
|
||||
to: "/organization/projects"
|
||||
to: "/organizations/$orgId/projects",
|
||||
params: { orgId }
|
||||
});
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
|
||||
@@ -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 { useProject } from "@app/context";
|
||||
import { useOrganization, useProject } from "@app/context";
|
||||
import {
|
||||
useCreatePkiCollection,
|
||||
useGetPkiCollectionById,
|
||||
@@ -28,6 +28,7 @@ type Props = {
|
||||
|
||||
export const PkiCollectionModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const navigate = useNavigate();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
@@ -81,8 +82,9 @@ export const PkiCollectionModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
});
|
||||
|
||||
navigate({
|
||||
to: "/projects/cert-management/$projectId/pki-collections/$collectionId",
|
||||
to: "/organizations/$orgId/projects/cert-management/$projectId/pki-collections/$collectionId",
|
||||
params: {
|
||||
orgId: currentOrg.id,
|
||||
projectId,
|
||||
collectionId
|
||||
}
|
||||
|
||||
@@ -19,7 +19,12 @@ import {
|
||||
THead,
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
useOrganization,
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { useListWorkspacePkiCollections } from "@app/hooks/api";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
@@ -31,6 +36,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const PkiCollectionTable = ({ handlePopUpOpen }: Props) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const navigate = useNavigate();
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.id || "";
|
||||
@@ -60,8 +66,9 @@ export const PkiCollectionTable = ({ handlePopUpOpen }: Props) => {
|
||||
key={`pki-collection-${pkiCollection.id}`}
|
||||
onClick={() =>
|
||||
navigate({
|
||||
to: "/projects/cert-management/$projectId/pki-collections/$collectionId",
|
||||
to: "/organizations/$orgId/projects/cert-management/$projectId/pki-collections/$collectionId",
|
||||
params: {
|
||||
orgId: currentOrg.id,
|
||||
projectId,
|
||||
collectionId: pkiCollection.id
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createFileRoute } from "@tanstack/react-router";
|
||||
import { AlertingPage } from "./AlertingPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/alerting"
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/alerting"
|
||||
)({
|
||||
component: AlertingPage,
|
||||
beforeLoad: ({ context }) => {
|
||||
|
||||
+15
-8
@@ -17,7 +17,12 @@ import {
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
useOrganization,
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { CaType, useDeleteCa, useGetCa } from "@app/hooks/api";
|
||||
import { TInternalCertificateAuthority } from "@app/hooks/api/ca/types";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
@@ -34,14 +39,14 @@ import {
|
||||
|
||||
const Page = () => {
|
||||
const { currentProject } = useProject();
|
||||
const { currentOrg } = useOrganization();
|
||||
const navigate = useNavigate();
|
||||
const params = useParams({
|
||||
from: ROUTE_PATHS.CertManager.CertAuthDetailsByIDPage.id
|
||||
});
|
||||
const { caName } = params as { caName: string };
|
||||
const { caId } = params as { caId: string };
|
||||
const { data } = useGetCa({
|
||||
caName,
|
||||
projectId: currentProject?.id || "",
|
||||
caId,
|
||||
type: CaType.INTERNAL
|
||||
}) as { data: TInternalCertificateAuthority };
|
||||
|
||||
@@ -60,7 +65,7 @@ const Page = () => {
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await deleteCa({
|
||||
caName,
|
||||
id: data.id,
|
||||
projectId: currentProject.id,
|
||||
type: CaType.INTERNAL
|
||||
});
|
||||
@@ -72,8 +77,9 @@ const Page = () => {
|
||||
|
||||
handlePopUpClose("deleteCa");
|
||||
navigate({
|
||||
to: "/projects/cert-management/$projectId/certificate-authorities",
|
||||
to: "/organizations/$orgId/projects/cert-management/$projectId/certificate-authorities",
|
||||
params: {
|
||||
orgId: currentOrg.id,
|
||||
projectId
|
||||
}
|
||||
});
|
||||
@@ -84,8 +90,9 @@ const Page = () => {
|
||||
{data && (
|
||||
<div className="mx-auto mb-6 w-full max-w-8xl">
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/certificate-authorities"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/certificate-authorities"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId
|
||||
}}
|
||||
className="mb-4 flex items-center gap-x-2 text-sm text-mineshaft-400"
|
||||
@@ -130,7 +137,7 @@ const Page = () => {
|
||||
</PageHeader>
|
||||
<div className="flex">
|
||||
<div className="mr-4 w-96">
|
||||
<CaDetailsSection caName={data.name} handlePopUpOpen={handlePopUpOpen} />
|
||||
<CaDetailsSection caId={data.id} handlePopUpOpen={handlePopUpOpen} />
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<CaCertificatesSection caId={data.id} />
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ export const CaCrlsTable = ({ caId }: Props) => {
|
||||
<Tr key={`ca-crl-${id}`}>
|
||||
<Td>
|
||||
<div className="flex items-center">
|
||||
{`${window.origin}/api/v1/pki/crl/${id}`}
|
||||
{`${window.origin}/api/v1/cert-manager/crl/${id}`}
|
||||
</div>
|
||||
</Td>
|
||||
{/* <Td>{format(new Date(caCrlObj.thisUpdate), "yyyy-MM-dd")}</Td> */}
|
||||
|
||||
+5
-11
@@ -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, useProject } from "@app/context";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub } 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";
|
||||
@@ -13,15 +13,14 @@ import { certKeyAlgorithmToNameMap } from "@app/hooks/api/certificates/constants
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
|
||||
type Props = {
|
||||
caName: string;
|
||||
caId: string;
|
||||
handlePopUpOpen: (
|
||||
popUpName: keyof UsePopUpState<["ca", "renewCa", "installCaCert"]>,
|
||||
data?: object
|
||||
) => void;
|
||||
};
|
||||
|
||||
export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
|
||||
const { currentProject } = useProject();
|
||||
export const CaDetailsSection = ({ caId, handlePopUpOpen }: Props) => {
|
||||
const [copyTextId, isCopyingId, setCopyTextId] = useTimedReset<string>({
|
||||
initialState: "Copy ID to clipboard"
|
||||
});
|
||||
@@ -30,8 +29,7 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
|
||||
});
|
||||
|
||||
const { data } = useGetCa({
|
||||
caName,
|
||||
projectId: currentProject.id,
|
||||
caId,
|
||||
type: CaType.INTERNAL
|
||||
});
|
||||
|
||||
@@ -53,7 +51,7 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePopUpOpen("ca", {
|
||||
name: ca.name
|
||||
caId: ca.id
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -154,10 +152,6 @@ export const CaDetailsSection = ({ caName, handlePopUpOpen }: Props) => {
|
||||
: "-"}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-medium text-mineshaft-300">Enable Direct Issuance</p>
|
||||
<p className="text-sm text-mineshaft-300">{ca.enableDirectIssuance ? "True" : "False"}</p>
|
||||
</div>
|
||||
{ca.status === CaStatus.ACTIVE && (
|
||||
<ProjectPermissionCan
|
||||
I={ProjectPermissionActions.Edit}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
import { CertAuthDetailsByIDPage } from "./CertAuthDetailsByIDPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/ca/$caName"
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/ca/$caId"
|
||||
)({
|
||||
component: CertAuthDetailsByIDPage,
|
||||
beforeLoad: ({ context, params }) => {
|
||||
@@ -13,14 +13,15 @@ export const Route = createFileRoute(
|
||||
{
|
||||
label: "Certificate Authorities",
|
||||
link: linkOptions({
|
||||
to: "/projects/cert-management/$projectId/certificate-authorities",
|
||||
to: "/organizations/$orgId/projects/cert-management/$projectId/certificate-authorities",
|
||||
params: {
|
||||
orgId: params.orgId,
|
||||
projectId: params.projectId
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
label: params.caName
|
||||
label: params.caId
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
+11
-8
@@ -9,8 +9,8 @@ import { Button, FormControl, Input, Select, SelectItem } from "@app/components/
|
||||
import { useProject } from "@app/context";
|
||||
import {
|
||||
CaStatus,
|
||||
useGetCaById,
|
||||
useGetCaCsr,
|
||||
useGetInternalCaById,
|
||||
useImportCaCertificate,
|
||||
useListWorkspaceCas,
|
||||
useSignIntermediate
|
||||
@@ -51,7 +51,7 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
|
||||
projectId: currentProject.id,
|
||||
status: CaStatus.ACTIVE
|
||||
});
|
||||
const { data: ca } = useGetCaById(caId);
|
||||
const { data: ca } = useGetInternalCaById(caId);
|
||||
const { data: csr } = useGetCaCsr(caId);
|
||||
|
||||
const { mutateAsync: signIntermediate } = useSignIntermediate();
|
||||
@@ -83,18 +83,21 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
|
||||
|
||||
const parentCaId = watch("parentCaId");
|
||||
|
||||
const { data: parentCa } = useGetCaById(parentCaId);
|
||||
const { data: parentCa } = useGetInternalCaById(parentCaId);
|
||||
|
||||
useEffect(() => {
|
||||
if (parentCa?.maxPathLength) {
|
||||
if (parentCa?.configuration.maxPathLength) {
|
||||
setValue(
|
||||
"maxPathLength",
|
||||
(parentCa.maxPathLength === -1 ? 3 : parentCa.maxPathLength - 1).toString()
|
||||
(parentCa.configuration.maxPathLength === -1
|
||||
? 3
|
||||
: parentCa.configuration.maxPathLength - 1
|
||||
).toString()
|
||||
);
|
||||
}
|
||||
|
||||
if (parentCa?.notAfter) {
|
||||
const parentCaNotAfter = new Date(parentCa.notAfter);
|
||||
if (parentCa?.configuration.notAfter) {
|
||||
const parentCaNotAfter = new Date(parentCa.configuration.notAfter);
|
||||
const middleDate = getMiddleDate(new Date(), parentCaNotAfter);
|
||||
setValue("notAfter", format(middleDate, "yyyy-MM-dd"));
|
||||
}
|
||||
@@ -197,7 +200,7 @@ export const InternalCaInstallForm = ({ caId, handlePopUpToggle }: Props) => {
|
||||
onValueChange={onChange}
|
||||
className="w-full"
|
||||
>
|
||||
{generatePathLengthOpts(parentCa?.maxPathLength || 0).map((value) => (
|
||||
{generatePathLengthOpts(parentCa?.configuration.maxPathLength || 0).map((value) => (
|
||||
<SelectItem value={String(value)} key={`ca-path-length-${value}`}>
|
||||
{`${value}`}
|
||||
</SelectItem>
|
||||
|
||||
@@ -46,7 +46,6 @@ const schema = z
|
||||
name: slugSchema({
|
||||
field: "Name"
|
||||
}),
|
||||
enableDirectIssuance: z.boolean(),
|
||||
status: z.nativeEnum(CaStatus),
|
||||
configuration: z
|
||||
.object({
|
||||
@@ -80,8 +79,7 @@ const caTypes = [
|
||||
export const CaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentProject } = useProject();
|
||||
const { data: ca } = useGetCa({
|
||||
caName: (popUp?.ca?.data as { name: string })?.name || "",
|
||||
projectId: currentProject?.id || "",
|
||||
caId: (popUp?.ca?.data as { caId: string })?.caId || "",
|
||||
type: CaType.INTERNAL
|
||||
});
|
||||
|
||||
@@ -100,7 +98,6 @@ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
type: CaType.INTERNAL,
|
||||
name: "",
|
||||
status: CaStatus.ACTIVE,
|
||||
enableDirectIssuance: true,
|
||||
configuration: {
|
||||
type: InternalCaType.ROOT,
|
||||
organization: "",
|
||||
@@ -124,7 +121,6 @@ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
type: ca.type,
|
||||
name: ca.name,
|
||||
status: ca.status,
|
||||
enableDirectIssuance: ca.enableDirectIssuance,
|
||||
configuration: {
|
||||
type: ca.configuration.type,
|
||||
organization: ca.configuration.organization,
|
||||
@@ -151,7 +147,6 @@ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
type: CaType.INTERNAL,
|
||||
name: "",
|
||||
status: CaStatus.ACTIVE,
|
||||
enableDirectIssuance: false,
|
||||
configuration: {
|
||||
type: InternalCaType.ROOT,
|
||||
organization: "",
|
||||
@@ -168,24 +163,16 @@ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
}
|
||||
}, [ca]);
|
||||
|
||||
const onFormSubmit = async ({
|
||||
type,
|
||||
name,
|
||||
enableDirectIssuance,
|
||||
status,
|
||||
configuration
|
||||
}: FormData) => {
|
||||
const onFormSubmit = async ({ type, name, status, configuration }: FormData) => {
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
if (ca) {
|
||||
// update
|
||||
await updateMutateAsync({
|
||||
caName: ca.name,
|
||||
projectId: currentProject.id,
|
||||
id: ca.id,
|
||||
name,
|
||||
type: CaType.INTERNAL,
|
||||
status,
|
||||
enableDirectIssuance
|
||||
status
|
||||
});
|
||||
} else {
|
||||
// create
|
||||
@@ -194,7 +181,6 @@ export const CaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
name,
|
||||
type,
|
||||
status,
|
||||
enableDirectIssuance,
|
||||
configuration: {
|
||||
...configuration,
|
||||
maxPathLength: Number(configuration.maxPathLength)
|
||||
|
||||
@@ -26,10 +26,10 @@ export const CaSection = () => {
|
||||
"caStatus" // enable / disable
|
||||
] as const);
|
||||
|
||||
const onRemoveCaSubmit = async (caName: string) => {
|
||||
const onRemoveCaSubmit = async (id: string) => {
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await deleteCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL });
|
||||
await deleteCa({ id, projectId: currentProject.id, type: CaType.INTERNAL });
|
||||
|
||||
createNotification({
|
||||
text: "Successfully deleted CA",
|
||||
@@ -39,10 +39,10 @@ export const CaSection = () => {
|
||||
handlePopUpClose("deleteCa");
|
||||
};
|
||||
|
||||
const onUpdateCaStatus = async ({ caName, status }: { caName: string; status: CaStatus }) => {
|
||||
const onUpdateCaStatus = async ({ caId, status }: { caId: string; status: CaStatus }) => {
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await updateCa({ caName, projectId: currentProject.id, type: CaType.INTERNAL, status });
|
||||
await updateCa({ id: caId, type: CaType.INTERNAL, status });
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`,
|
||||
@@ -85,9 +85,7 @@ export const CaSection = () => {
|
||||
subTitle="This action will delete other CAs and certificates below it in your CA hierarchy."
|
||||
onChange={(isOpen) => handlePopUpToggle("deleteCa", isOpen)}
|
||||
deleteKey="confirm"
|
||||
onDeleteApproved={() =>
|
||||
onRemoveCaSubmit((popUp?.deleteCa?.data as { caName: string })?.caName)
|
||||
}
|
||||
onDeleteApproved={() => onRemoveCaSubmit((popUp?.deleteCa?.data as { caId: string })?.caId)}
|
||||
/>
|
||||
<DeleteActionModal
|
||||
isOpen={popUp.caStatus.isOpen}
|
||||
@@ -104,7 +102,7 @@ export const CaSection = () => {
|
||||
onChange={(isOpen) => handlePopUpToggle("caStatus", isOpen)}
|
||||
deleteKey="confirm"
|
||||
onDeleteApproved={() =>
|
||||
onUpdateCaStatus(popUp?.caStatus?.data as { caName: string; status: CaStatus })
|
||||
onUpdateCaStatus(popUp?.caStatus?.data as { caId: string; status: CaStatus })
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,12 @@ import {
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { Badge } from "@app/components/v3";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
useOrganization,
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { CaStatus, CaType, useListCasByTypeAndProjectId } from "@app/hooks/api";
|
||||
import {
|
||||
caStatusToNameMap,
|
||||
@@ -46,6 +51,7 @@ type Props = {
|
||||
|
||||
export const CaTable = ({ handlePopUpOpen }: Props) => {
|
||||
const navigate = useNavigate();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentProject } = useProject();
|
||||
const { data, isPending } = useListCasByTypeAndProjectId(CaType.INTERNAL, currentProject.id);
|
||||
const cas = data as TInternalCertificateAuthority[];
|
||||
@@ -75,10 +81,11 @@ export const CaTable = ({ handlePopUpOpen }: Props) => {
|
||||
key={`ca-${ca.id}`}
|
||||
onClick={() =>
|
||||
navigate({
|
||||
to: "/projects/cert-management/$projectId/ca/$caName",
|
||||
to: "/organizations/$orgId/projects/cert-management/$projectId/ca/$caId",
|
||||
params: {
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id,
|
||||
caName: ca.name
|
||||
caId: ca.id
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -173,7 +180,7 @@ export const CaTable = ({ handlePopUpOpen }: Props) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePopUpOpen("caStatus", {
|
||||
caName: ca.name,
|
||||
caId: ca.id,
|
||||
status:
|
||||
ca.status === CaStatus.ACTIVE
|
||||
? CaStatus.DISABLED
|
||||
@@ -200,7 +207,7 @@ export const CaTable = ({ handlePopUpOpen }: Props) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePopUpOpen("deleteCa", {
|
||||
caName: ca.name
|
||||
caId: ca.id
|
||||
});
|
||||
}}
|
||||
disabled={!isAllowed}
|
||||
|
||||
+53
-34
@@ -14,8 +14,7 @@ import {
|
||||
Modal,
|
||||
ModalContent,
|
||||
Select,
|
||||
SelectItem,
|
||||
Switch
|
||||
SelectItem
|
||||
} from "@app/components/v2";
|
||||
import { useProject } from "@app/context";
|
||||
import { APP_CONNECTION_MAP } from "@app/helpers/appConnections";
|
||||
@@ -27,6 +26,10 @@ import {
|
||||
TCloudflareZone,
|
||||
useCloudflareConnectionListZones
|
||||
} from "@app/hooks/api/appConnections/cloudflare";
|
||||
import {
|
||||
TDNSMadeEasyZone,
|
||||
useDNSMadeEasyConnectionListZones
|
||||
} from "@app/hooks/api/appConnections/dns-made-easy";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import {
|
||||
AcmeDnsProvider,
|
||||
@@ -59,7 +62,6 @@ const baseSchema = z.object({
|
||||
name: slugSchema({
|
||||
field: "Name"
|
||||
}),
|
||||
enableDirectIssuance: z.boolean(),
|
||||
status: z.nativeEnum(CaStatus)
|
||||
});
|
||||
|
||||
@@ -131,8 +133,7 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { data: ca, isLoading: isCaLoading } = useGetCa({
|
||||
caName: (popUp?.ca?.data as { name: string })?.name || "",
|
||||
projectId: currentProject?.id || "",
|
||||
caId: (popUp?.ca?.data as { caId: string })?.caId || "",
|
||||
type: (popUp?.ca?.data as { type: CaType })?.type || ""
|
||||
});
|
||||
|
||||
@@ -168,7 +169,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
type: CaType.AZURE_AD_CS,
|
||||
name: "",
|
||||
status: CaStatus.ACTIVE,
|
||||
enableDirectIssuance: false,
|
||||
configuration: {
|
||||
azureAdcsConnection: {
|
||||
id: "",
|
||||
@@ -181,7 +181,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
type: CaType.ACME,
|
||||
name: "",
|
||||
status: CaStatus.ACTIVE,
|
||||
enableDirectIssuance: true,
|
||||
configuration: {
|
||||
dnsAppConnection: {
|
||||
id: "",
|
||||
@@ -211,6 +210,11 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
enabled: caType === CaType.ACME
|
||||
});
|
||||
|
||||
const { data: availableDNSMadeEasyConnections, isPending: isDNSMadeEasyPending } =
|
||||
useListAvailableAppConnections(AppConnection.DNSMadeEasy, currentProject.id, {
|
||||
enabled: caType === CaType.ACME
|
||||
});
|
||||
|
||||
const { data: availableAzureConnections, isPending: isAzurePending } =
|
||||
useListAvailableAppConnections(AppConnection.AzureADCS, currentProject.id, {
|
||||
enabled: caType === CaType.AZURE_AD_CS
|
||||
@@ -220,16 +224,24 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
if (caType === CaType.AZURE_AD_CS) {
|
||||
return availableAzureConnections || [];
|
||||
}
|
||||
return [...(availableRoute53Connections || []), ...(availableCloudflareConnections || [])];
|
||||
return [
|
||||
...(availableRoute53Connections || []),
|
||||
...(availableCloudflareConnections || []),
|
||||
...(availableDNSMadeEasyConnections || [])
|
||||
];
|
||||
}, [
|
||||
caType,
|
||||
availableRoute53Connections,
|
||||
availableCloudflareConnections,
|
||||
availableDNSMadeEasyConnections,
|
||||
availableAzureConnections
|
||||
]);
|
||||
|
||||
const isPending =
|
||||
isRoute53Pending || isCloudflarePending || (isAzurePending && caType === CaType.AZURE_AD_CS);
|
||||
isRoute53Pending ||
|
||||
isCloudflarePending ||
|
||||
isDNSMadeEasyPending ||
|
||||
(isAzurePending && caType === CaType.AZURE_AD_CS);
|
||||
|
||||
const dnsAppConnection =
|
||||
caType === CaType.ACME && configuration && "dnsAppConnection" in configuration
|
||||
@@ -241,6 +253,11 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
enabled: dnsProvider === AcmeDnsProvider.Cloudflare && !!dnsAppConnection.id
|
||||
});
|
||||
|
||||
const { data: dnsMadeEasyZones = [], isPending: isDNSMadeEasyZonesPending } =
|
||||
useDNSMadeEasyConnectionListZones(dnsAppConnection.id, {
|
||||
enabled: dnsProvider === AcmeDnsProvider.DNSMadeEasy && !!dnsAppConnection.id
|
||||
});
|
||||
|
||||
// Populate form with CA data when editing
|
||||
useEffect(() => {
|
||||
if (ca && !isCaLoading) {
|
||||
@@ -253,7 +270,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
type: ca.type,
|
||||
name: ca.name,
|
||||
status: ca.status,
|
||||
enableDirectIssuance: ca.enableDirectIssuance,
|
||||
configuration: {
|
||||
dnsAppConnection: {
|
||||
id: ca.configuration.dnsAppConnectionId,
|
||||
@@ -278,7 +294,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
type: ca.type,
|
||||
name: ca.name,
|
||||
status: ca.status,
|
||||
enableDirectIssuance: false,
|
||||
configuration: {
|
||||
azureAdcsConnection: {
|
||||
id: ca.configuration.azureAdcsConnectionId,
|
||||
@@ -293,7 +308,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
const onFormSubmit = async ({
|
||||
type,
|
||||
name,
|
||||
enableDirectIssuance,
|
||||
status,
|
||||
configuration: formConfiguration
|
||||
}: FormData) => {
|
||||
@@ -320,12 +334,11 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
|
||||
if (ca) {
|
||||
await updateMutateAsync({
|
||||
caName: ca.name,
|
||||
id: ca.id,
|
||||
projectId: currentProject.id,
|
||||
name,
|
||||
type,
|
||||
status,
|
||||
enableDirectIssuance: type === CaType.AZURE_AD_CS ? false : enableDirectIssuance,
|
||||
configuration: configPayload
|
||||
});
|
||||
} else {
|
||||
@@ -334,7 +347,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
name,
|
||||
type,
|
||||
status,
|
||||
enableDirectIssuance: type === CaType.AZURE_AD_CS ? false : enableDirectIssuance,
|
||||
configuration: configPayload
|
||||
});
|
||||
}
|
||||
@@ -500,6 +512,32 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
{dnsProvider === AcmeDnsProvider.DNSMadeEasy && (
|
||||
<Controller
|
||||
name="configuration.dnsProviderConfig.hostedZoneId"
|
||||
control={control}
|
||||
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error?.message)}
|
||||
label="Zone"
|
||||
>
|
||||
<FilterableSelect
|
||||
isLoading={isDNSMadeEasyZonesPending && !!dnsAppConnection.id}
|
||||
isDisabled={!dnsAppConnection.id}
|
||||
value={dnsMadeEasyZones.find((zone) => zone.id === value)}
|
||||
onChange={(option) => {
|
||||
onChange((option as SingleValue<TDNSMadeEasyZone>)?.id ?? null);
|
||||
}}
|
||||
options={dnsMadeEasyZones}
|
||||
placeholder="Select a zone..."
|
||||
getOptionLabel={(option) => option.name}
|
||||
getOptionValue={(option) => option.id}
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
<Controller
|
||||
control={control}
|
||||
defaultValue=""
|
||||
@@ -601,25 +639,6 @@ export const ExternalCaModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
name="configuration.azureAdcsConnection"
|
||||
/>
|
||||
)}
|
||||
{caType === CaType.ACME && (
|
||||
<Controller
|
||||
control={control}
|
||||
name="enableDirectIssuance"
|
||||
render={({ field, fieldState: { error } }) => {
|
||||
return (
|
||||
<FormControl isError={Boolean(error)} errorText={error?.message} className="my-8">
|
||||
<Switch
|
||||
id="is-active"
|
||||
onCheckedChange={(value) => field.onChange(value)}
|
||||
isChecked={field.value}
|
||||
>
|
||||
<p className="w-full">Enable Direct Issuance</p>
|
||||
</Switch>
|
||||
</FormControl>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="flex items-center">
|
||||
<Button
|
||||
className="mr-4"
|
||||
|
||||
+7
-7
@@ -22,10 +22,10 @@ export const ExternalCaSection = () => {
|
||||
"caStatus" // enable / disable
|
||||
] as const);
|
||||
|
||||
const onRemoveCaSubmit = async (caName: string, type: CaType) => {
|
||||
const onRemoveCaSubmit = async (id: string, type: CaType) => {
|
||||
if (!currentProject?.id) return;
|
||||
|
||||
await deleteCa({ caName, type, projectId: currentProject.id });
|
||||
await deleteCa({ id, type, projectId: currentProject.id });
|
||||
|
||||
createNotification({
|
||||
text: "Successfully deleted CA",
|
||||
@@ -36,17 +36,17 @@ export const ExternalCaSection = () => {
|
||||
};
|
||||
|
||||
const onUpdateCaStatus = async ({
|
||||
name,
|
||||
caId,
|
||||
type,
|
||||
status
|
||||
}: {
|
||||
name: string;
|
||||
caId: string;
|
||||
type: CaType;
|
||||
status: CaStatus;
|
||||
}) => {
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await updateCa({ caName: name, type, status, projectId: currentProject.id });
|
||||
await updateCa({ id: caId, type, status });
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${status === CaStatus.ACTIVE ? "enabled" : "disabled"} CA`,
|
||||
@@ -88,7 +88,7 @@ export const ExternalCaSection = () => {
|
||||
deleteKey="confirm"
|
||||
onDeleteApproved={() =>
|
||||
onRemoveCaSubmit(
|
||||
(popUp?.deleteCa?.data as { name: string })?.name,
|
||||
(popUp?.deleteCa?.data as { caId: string })?.caId,
|
||||
(popUp?.deleteCa?.data as { type: CaType })?.type
|
||||
)
|
||||
}
|
||||
@@ -110,7 +110,7 @@ export const ExternalCaSection = () => {
|
||||
deleteKey="confirm"
|
||||
onDeleteApproved={() =>
|
||||
onUpdateCaStatus(
|
||||
popUp?.caStatus?.data as { name: string; type: CaType; status: CaStatus }
|
||||
popUp?.caStatus?.data as { caId: string; type: CaType; status: CaStatus }
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
+5
-2
@@ -35,6 +35,7 @@ type Props = {
|
||||
handlePopUpOpen: (
|
||||
popUpName: keyof UsePopUpState<["ca", "deleteCa", "caStatus"]>,
|
||||
data?: {
|
||||
caId?: string;
|
||||
name?: string;
|
||||
type?: CaType;
|
||||
status?: CaStatus;
|
||||
@@ -70,6 +71,7 @@ export const ExternalCaTable = ({ handlePopUpOpen }: Props) => {
|
||||
key={`ca-${ca.id}`}
|
||||
onClick={() => {
|
||||
handlePopUpOpen("ca", {
|
||||
caId: ca.id,
|
||||
name: ca.name,
|
||||
type: ca.type
|
||||
});
|
||||
@@ -104,6 +106,7 @@ export const ExternalCaTable = ({ handlePopUpOpen }: Props) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePopUpOpen("ca", {
|
||||
caId: ca.id,
|
||||
name: ca.name,
|
||||
type: ca.type
|
||||
});
|
||||
@@ -129,7 +132,7 @@ export const ExternalCaTable = ({ handlePopUpOpen }: Props) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePopUpOpen("caStatus", {
|
||||
name: ca.name,
|
||||
caId: ca.id,
|
||||
type: ca.type,
|
||||
status:
|
||||
ca.status === CaStatus.ACTIVE
|
||||
@@ -157,7 +160,7 @@ export const ExternalCaTable = ({ handlePopUpOpen }: Props) => {
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePopUpOpen("deleteCa", {
|
||||
name: ca.name,
|
||||
caId: ca.id,
|
||||
type: ca.type
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createFileRoute } from "@tanstack/react-router";
|
||||
import { CertificateAuthoritiesPage } from "./CertificateAuthoritiesPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/certificate-authorities"
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/certificate-authorities"
|
||||
)({
|
||||
component: CertificateAuthoritiesPage,
|
||||
beforeLoad: ({ context }) => {
|
||||
|
||||
+22
-6
@@ -21,7 +21,13 @@ type Props = {
|
||||
) => void;
|
||||
onFormatSelected: (
|
||||
format: "pem" | "pkcs12",
|
||||
serialNumber: string,
|
||||
{
|
||||
certificateId,
|
||||
serialNumber
|
||||
}: {
|
||||
certificateId: string;
|
||||
serialNumber: string;
|
||||
},
|
||||
options?: ExportOptions
|
||||
) => void;
|
||||
};
|
||||
@@ -42,8 +48,11 @@ export const CertificateExportModal = ({ popUp, handlePopUpToggle, onFormatSelec
|
||||
alias: ""
|
||||
});
|
||||
|
||||
const serialNumber =
|
||||
(popUp?.certificateExport?.data as { serialNumber: string })?.serialNumber || "";
|
||||
const { certificateId, serialNumber } =
|
||||
(popUp?.certificateExport?.data as {
|
||||
certificateId: string;
|
||||
serialNumber: string;
|
||||
}) || {};
|
||||
|
||||
// Reset form whenever the modal opens
|
||||
useEffect(() => {
|
||||
@@ -64,14 +73,21 @@ export const CertificateExportModal = ({ popUp, handlePopUpToggle, onFormatSelec
|
||||
};
|
||||
|
||||
const handleExport = () => {
|
||||
if (serialNumber && isFormValid()) {
|
||||
if ((certificateId || serialNumber) && isFormValid()) {
|
||||
const options: ExportOptions = {};
|
||||
|
||||
if (selectedFormat === "pkcs12") {
|
||||
options.pkcs12 = pkcs12Options;
|
||||
}
|
||||
|
||||
onFormatSelected(selectedFormat, serialNumber, options);
|
||||
onFormatSelected(
|
||||
selectedFormat,
|
||||
{
|
||||
certificateId,
|
||||
serialNumber
|
||||
},
|
||||
options
|
||||
);
|
||||
handlePopUpToggle("certificateExport", false);
|
||||
}
|
||||
};
|
||||
@@ -151,7 +167,7 @@ export const CertificateExportModal = ({ popUp, handlePopUpToggle, onFormatSelec
|
||||
colorSchema="primary"
|
||||
leftIcon={<FontAwesomeIcon icon={faDownload} />}
|
||||
onClick={handleExport}
|
||||
disabled={!serialNumber || !isFormValid()}
|
||||
disabled={!(certificateId || serialNumber) || !isFormValid()}
|
||||
>
|
||||
Export {selectedFormat.toUpperCase()}
|
||||
</Button>
|
||||
|
||||
+76
-50
@@ -20,9 +20,9 @@ import {
|
||||
} from "@app/components/v2";
|
||||
import { useProject } from "@app/context";
|
||||
import { useGetCert } from "@app/hooks/api";
|
||||
import { useCreateCertificateV3 } from "@app/hooks/api/ca";
|
||||
import { useListCertificateProfiles } from "@app/hooks/api/certificateProfiles";
|
||||
import { EnrollmentType, useListCertificateProfiles } from "@app/hooks/api/certificateProfiles";
|
||||
import { CertExtendedKeyUsage, CertKeyUsage } from "@app/hooks/api/certificates/enums";
|
||||
import { useUnifiedCertificateIssuance } from "@app/hooks/api/certificates/mutations";
|
||||
import { useGetCertificateTemplateV2ById } from "@app/hooks/api/certificateTemplates/queries";
|
||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||
import { CertSubjectAlternativeNameType } from "@app/pages/cert-manager/PoliciesPage/components/CertificateTemplatesV2Tab/shared/certificate-constants";
|
||||
@@ -103,10 +103,11 @@ type Props = {
|
||||
};
|
||||
|
||||
type TCertificateDetails = {
|
||||
serialNumber: string;
|
||||
certificate: string;
|
||||
certificateChain: string;
|
||||
privateKey: string;
|
||||
serialNumber?: string;
|
||||
certificate?: string;
|
||||
certificateChain?: string;
|
||||
privateKey?: string;
|
||||
issuingCaCertificate?: string;
|
||||
};
|
||||
|
||||
export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }: Props) => {
|
||||
@@ -122,12 +123,11 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
|
||||
|
||||
const { data: profilesData } = useListCertificateProfiles({
|
||||
projectId: currentProject?.id || "",
|
||||
enrollmentType: "api"
|
||||
enrollmentType: EnrollmentType.API,
|
||||
includeConfigs: true
|
||||
});
|
||||
|
||||
const { mutateAsync: createCertificate } = useCreateCertificateV3({
|
||||
projectId: currentProject?.id
|
||||
});
|
||||
const { mutateAsync: issueCertificate } = useUnifiedCertificateIssuance();
|
||||
|
||||
const formResolver = useMemo(() => {
|
||||
return zodResolver(createSchema(shouldShowSubjectSection));
|
||||
@@ -243,7 +243,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
|
||||
keyUsages,
|
||||
extendedKeyUsages
|
||||
}: FormData) => {
|
||||
if (!currentProject?.slug) {
|
||||
if (!currentProject?.slug || !currentProject?.id) {
|
||||
createNotification({
|
||||
text: "Project not found. Please refresh and try again.",
|
||||
type: "error"
|
||||
@@ -275,44 +275,70 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
|
||||
}
|
||||
}
|
||||
|
||||
const certificateRequest: any = {
|
||||
profileId: formProfileId,
|
||||
projectSlug: currentProject.slug,
|
||||
ttl,
|
||||
signatureAlgorithm,
|
||||
keyAlgorithm,
|
||||
keyUsages: filterUsages(keyUsages) as CertKeyUsage[],
|
||||
extendedKeyUsages: filterUsages(extendedKeyUsages) as CertExtendedKeyUsage[]
|
||||
};
|
||||
try {
|
||||
// Prepare unified request
|
||||
const request: any = {
|
||||
profileId: formProfileId,
|
||||
projectSlug: currentProject.slug,
|
||||
projectId: currentProject.id,
|
||||
attributes: {
|
||||
ttl,
|
||||
signatureAlgorithm: signatureAlgorithm || "",
|
||||
keyAlgorithm: keyAlgorithm || "",
|
||||
keyUsages: filterUsages(keyUsages) as CertKeyUsage[],
|
||||
extendedKeyUsages: filterUsages(extendedKeyUsages) as CertExtendedKeyUsage[]
|
||||
}
|
||||
};
|
||||
|
||||
if (constraints.shouldShowSubjectSection && commonName) {
|
||||
certificateRequest.commonName = commonName;
|
||||
}
|
||||
if (constraints.shouldShowSanSection && subjectAltNames && subjectAltNames.length > 0) {
|
||||
const formattedSans = formatSubjectAltNames(subjectAltNames);
|
||||
if (formattedSans && formattedSans.length > 0) {
|
||||
certificateRequest.altNames = formattedSans;
|
||||
if (constraints.shouldShowSubjectSection && commonName) {
|
||||
request.attributes.commonName = commonName;
|
||||
}
|
||||
|
||||
if (constraints.shouldShowSanSection && subjectAltNames && subjectAltNames.length > 0) {
|
||||
const formattedSans = formatSubjectAltNames(subjectAltNames);
|
||||
if (formattedSans && formattedSans.length > 0) {
|
||||
request.attributes.altNames = formattedSans;
|
||||
}
|
||||
}
|
||||
|
||||
const response = await issueCertificate(request);
|
||||
|
||||
// Handle certificate issuance response
|
||||
|
||||
if ("certificate" in response && response.certificate) {
|
||||
const certData = response.certificate;
|
||||
const certificateDetailsToSet = {
|
||||
serialNumber: certData.serialNumber || "",
|
||||
certificate: certData.certificate || "",
|
||||
certificateChain: certData.certificateChain || "",
|
||||
privateKey: certData.privateKey || "",
|
||||
issuingCaCertificate: certData.issuingCaCertificate || ""
|
||||
};
|
||||
|
||||
setCertificateDetails(certificateDetailsToSet);
|
||||
|
||||
createNotification({
|
||||
text: "Successfully created certificate",
|
||||
type: "success"
|
||||
});
|
||||
} else {
|
||||
// Certificate request - async processing
|
||||
createNotification({
|
||||
text: `Certificate request submitted successfully. This may take a few minutes to process. Certificate Request ID: ${response.certificateRequestId}`,
|
||||
type: "success"
|
||||
});
|
||||
handlePopUpToggle("issueCertificate", false);
|
||||
}
|
||||
} catch (error) {
|
||||
createNotification({
|
||||
text: `Failed to request certificate: ${(error as Error)?.message || "Unknown error"}`,
|
||||
type: "error"
|
||||
});
|
||||
}
|
||||
|
||||
const { serialNumber, certificate, certificateChain, privateKey } =
|
||||
await createCertificate(certificateRequest);
|
||||
|
||||
setCertificateDetails({
|
||||
serialNumber,
|
||||
certificate,
|
||||
certificateChain,
|
||||
privateKey
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully created certificate",
|
||||
type: "success"
|
||||
});
|
||||
},
|
||||
[
|
||||
currentProject?.slug,
|
||||
createCertificate,
|
||||
issueCertificate,
|
||||
constraints.shouldShowSubjectSection,
|
||||
constraints.shouldShowSanSection
|
||||
]
|
||||
@@ -321,13 +347,13 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
|
||||
const getModalTitle = () => {
|
||||
if (certificateDetails) return "Certificate Created Successfully";
|
||||
if (cert) return "Certificate Details";
|
||||
return "Issue New Certificate";
|
||||
return "Request New Certificate";
|
||||
};
|
||||
|
||||
const getModalSubTitle = () => {
|
||||
if (certificateDetails) return "Certificate has been successfully created and is ready for use";
|
||||
if (cert) return "View certificate information";
|
||||
return "Issue a new certificate using a certificate profile";
|
||||
return "Request a new certificate using a certificate profile";
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -343,10 +369,10 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
|
||||
<ModalContent title={getModalTitle()} subTitle={getModalSubTitle()}>
|
||||
{certificateDetails && (
|
||||
<CertificateContent
|
||||
serialNumber={certificateDetails.serialNumber}
|
||||
certificate={certificateDetails.certificate}
|
||||
certificateChain={certificateDetails.certificateChain}
|
||||
privateKey={certificateDetails.privateKey}
|
||||
serialNumber={certificateDetails.serialNumber!}
|
||||
certificate={certificateDetails.certificate!}
|
||||
certificateChain={certificateDetails.certificateChain!}
|
||||
privateKey={certificateDetails.privateKey!}
|
||||
/>
|
||||
)}
|
||||
{cert && (
|
||||
@@ -498,7 +524,7 @@ export const CertificateIssuanceModal = ({ popUp, handlePopUpToggle, profileId }
|
||||
isLoading={isSubmitting}
|
||||
isDisabled={isSubmitting || (!actualSelectedProfile && !profileId)}
|
||||
>
|
||||
{cert ? "Update" : "Issue Certificate"}
|
||||
{cert ? "Update" : "Request Certificate"}
|
||||
</Button>
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
|
||||
+3
-1
@@ -20,7 +20,7 @@ import {
|
||||
Tr
|
||||
} from "@app/components/v2";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { useProject } from "@app/context";
|
||||
import { useOrganization, useProject } from "@app/context";
|
||||
import {
|
||||
PkiSync,
|
||||
useAddCertificatesToPkiSync,
|
||||
@@ -49,6 +49,7 @@ export const CertificateManagePkiSyncsModal = ({ popUp, handlePopUpToggle }: Pro
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentProject } = useProject();
|
||||
const navigate = useNavigate();
|
||||
const { certificateId, commonName } = popUp.data || {};
|
||||
@@ -92,6 +93,7 @@ export const CertificateManagePkiSyncsModal = ({ popUp, handlePopUpToggle }: Pro
|
||||
navigate({
|
||||
to: ROUTE_PATHS.CertManager.IntegrationsListPage.path,
|
||||
params: {
|
||||
orgId: currentOrg.id,
|
||||
projectId: currentProject.id
|
||||
},
|
||||
search: {
|
||||
|
||||
+6
-2
@@ -20,12 +20,16 @@ export const CertificateRenewalModal = ({ popUp, handlePopUpToggle }: Props) =>
|
||||
const onRenewConfirm = async () => {
|
||||
const { certificateId } = popUp.renewCertificate.data as { certificateId: string };
|
||||
|
||||
await renewCertificate({
|
||||
const result = await renewCertificate({
|
||||
certificateId
|
||||
});
|
||||
|
||||
const notificationText = result.certificateRequestId
|
||||
? `Certificate renewal initiated successfully. Certificate Request ID: ${result.certificateRequestId}`
|
||||
: "Certificate renewed successfully";
|
||||
|
||||
createNotification({
|
||||
text: "Certificate renewed successfully",
|
||||
text: notificationText,
|
||||
type: "success"
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -50,11 +50,11 @@ export const CertificateRevocationModal = ({ popUp, handlePopUpToggle }: Props)
|
||||
const onFormSubmit = async ({ revocationReason }: FormData) => {
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
const { serialNumber } = popUp.revokeCertificate.data as { serialNumber: string };
|
||||
const { certificateId } = popUp.revokeCertificate.data as { certificateId: string };
|
||||
|
||||
await revokeCertificate({
|
||||
projectId: currentProject.id,
|
||||
serialNumber,
|
||||
id: certificateId,
|
||||
revocationReason
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ import { useProject } from "@app/context";
|
||||
import {
|
||||
CaStatus,
|
||||
useCreateCertTemplate,
|
||||
useGetCaById,
|
||||
useGetCertTemplate,
|
||||
useGetInternalCaById,
|
||||
useListWorkspaceCas,
|
||||
useListWorkspacePkiCollections,
|
||||
useUpdateCertTemplate
|
||||
@@ -84,7 +84,7 @@ type Props = {
|
||||
export const CertificateTemplateModal = ({ popUp, handlePopUpToggle, caId }: Props) => {
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { data: ca } = useGetCaById(caId);
|
||||
const { data: ca } = useGetInternalCaById(caId);
|
||||
|
||||
const { data: certTemplate } = useGetCertTemplate(
|
||||
(popUp?.certificateTemplate?.data as { id: string })?.id || ""
|
||||
|
||||
+12
-6
@@ -39,11 +39,11 @@ export const CertificatesSection = () => {
|
||||
"managePkiSyncs"
|
||||
] as const);
|
||||
|
||||
const onRemoveCertificateSubmit = async (serialNumber: string) => {
|
||||
const onRemoveCertificateSubmit = async (id: string) => {
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await deleteCert({
|
||||
serialNumber,
|
||||
id,
|
||||
projectId: currentProject.id
|
||||
});
|
||||
|
||||
@@ -57,7 +57,13 @@ export const CertificatesSection = () => {
|
||||
|
||||
const handleCertificateExport = async (
|
||||
format: "pem" | "pkcs12",
|
||||
serialNumber: string,
|
||||
{
|
||||
certificateId,
|
||||
serialNumber
|
||||
}: {
|
||||
certificateId: string;
|
||||
serialNumber: string;
|
||||
},
|
||||
options?: ExportOptions
|
||||
) => {
|
||||
if (format === "pem") {
|
||||
@@ -75,7 +81,7 @@ export const CertificatesSection = () => {
|
||||
|
||||
try {
|
||||
await downloadCertPkcs12({
|
||||
serialNumber,
|
||||
certificateId,
|
||||
projectSlug: currentProject.slug,
|
||||
password: options.pkcs12.password,
|
||||
alias: options.pkcs12.alias
|
||||
@@ -119,7 +125,7 @@ export const CertificatesSection = () => {
|
||||
onClick={() => handlePopUpOpen("issueCertificate")}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Issue
|
||||
Request
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
@@ -150,7 +156,7 @@ export const CertificatesSection = () => {
|
||||
deleteKey="confirm"
|
||||
onDeleteApproved={() =>
|
||||
onRemoveCertificateSubmit(
|
||||
(popUp?.deleteCertificate?.data as { serialNumber: string })?.serialNumber
|
||||
(popUp?.deleteCertificate?.data as { certificateId: string })?.certificateId
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -277,6 +277,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
)}
|
||||
onClick={async () =>
|
||||
handlePopUpOpen("certificateExport", {
|
||||
certificateId: certificate.id,
|
||||
serialNumber: certificate.serialNumber
|
||||
})
|
||||
}
|
||||
@@ -416,7 +417,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
{/* Manual renewal action for profile-issued certificates that are not revoked/expired (including failed ones) */}
|
||||
{(() => {
|
||||
const canRenew =
|
||||
certificate.profileId &&
|
||||
(certificate.profileId || certificate.caId) &&
|
||||
certificate.hasPrivateKey !== false &&
|
||||
!certificate.renewedByCertificateId &&
|
||||
!isRevoked &&
|
||||
@@ -501,7 +502,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
)}
|
||||
onClick={async () =>
|
||||
handlePopUpOpen("revokeCertificate", {
|
||||
serialNumber: certificate.serialNumber
|
||||
certificateId: certificate.id
|
||||
})
|
||||
}
|
||||
disabled={!isAllowed}
|
||||
@@ -524,7 +525,7 @@ export const CertificatesTable = ({ handlePopUpOpen }: Props) => {
|
||||
)}
|
||||
onClick={async () =>
|
||||
handlePopUpOpen("deleteCertificate", {
|
||||
serialNumber: certificate.serialNumber,
|
||||
certificateId: certificate.id,
|
||||
commonName: certificate.commonName
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useNavigate, useSearch } from "@tanstack/react-router";
|
||||
import { ProjectPermissionCan } from "@app/components/permissions";
|
||||
import { PageHeader, Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { ProjectPermissionSub, useOrganization, useProject } from "@app/context";
|
||||
import { ProjectPermissionPkiSyncActions } from "@app/context/ProjectPermissionContext/types";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
import { IntegrationsListPageTabs } from "@app/types/integrations";
|
||||
@@ -14,6 +14,7 @@ import { PkiSyncsTab } from "./components";
|
||||
|
||||
export const IntegrationsListPage = () => {
|
||||
const navigate = useNavigate();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentProject } = useProject();
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -30,7 +31,8 @@ export const IntegrationsListPage = () => {
|
||||
selectedTab: tab as IntegrationsListPageTabs
|
||||
},
|
||||
params: {
|
||||
projectId: currentProject?.id
|
||||
projectId: currentProject?.id,
|
||||
orgId: currentOrg.id
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -47,7 +49,7 @@ export const IntegrationsListPage = () => {
|
||||
<div className="mb-8">
|
||||
<PageHeader
|
||||
scope={ProjectType.CertificateManager}
|
||||
title="Integrations"
|
||||
title="Project Integrations"
|
||||
description="Manage integrations with third-party certificate services."
|
||||
/>
|
||||
<Tabs orientation="vertical" value={currentTab} onValueChange={updateSelectedTab}>
|
||||
|
||||
+4
-2
@@ -39,7 +39,7 @@ import {
|
||||
} from "@app/components/v2";
|
||||
import { Badge } from "@app/components/v3";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { ProjectPermissionSub } from "@app/context";
|
||||
import { ProjectPermissionSub, useOrganization } from "@app/context";
|
||||
import { ProjectPermissionPkiSyncActions } from "@app/context/ProjectPermissionContext/types";
|
||||
import { PKI_SYNC_MAP } from "@app/helpers/pkiSyncs";
|
||||
import { useToggle } from "@app/hooks";
|
||||
@@ -82,6 +82,7 @@ export const PkiSyncRow = ({
|
||||
|
||||
const { syncOption } = usePkiSyncOption(destination);
|
||||
|
||||
const { currentOrg } = useOrganization();
|
||||
const [isIdCopied, setIsIdCopied] = useToggle(false);
|
||||
|
||||
const handleCopyId = useCallback(() => {
|
||||
@@ -127,7 +128,8 @@ export const PkiSyncRow = ({
|
||||
to: ROUTE_PATHS.CertManager.PkiSyncDetailsByIDPage.path,
|
||||
params: {
|
||||
syncId: id,
|
||||
projectId
|
||||
projectId,
|
||||
orgId: currentOrg.id
|
||||
}
|
||||
});
|
||||
}}
|
||||
|
||||
+8
-6
@@ -8,7 +8,7 @@ import { CreatePkiSyncModal } from "@app/components/pki-syncs";
|
||||
import { Button, Spinner } from "@app/components/v2";
|
||||
import { DocumentationLinkBadge } from "@app/components/v3";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { ProjectPermissionSub, useProject } from "@app/context";
|
||||
import { ProjectPermissionSub, useOrganization, useProject } from "@app/context";
|
||||
import { ProjectPermissionPkiSyncActions } from "@app/context/ProjectPermissionContext/types";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useListPkiSyncs } from "@app/hooks/api/pkiSyncs";
|
||||
@@ -26,18 +26,19 @@ export const PkiSyncsTab = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { currentProject } = useProject();
|
||||
|
||||
const { currentOrg } = useOrganization();
|
||||
const memoizedSearch = useMemo(() => search, [search]);
|
||||
|
||||
const navigateToBase = useCallback(() => {
|
||||
navigate({
|
||||
to: ROUTE_PATHS.CertManager.IntegrationsListPage.path,
|
||||
params: {
|
||||
projectId: currentProject?.id
|
||||
projectId: currentProject?.id,
|
||||
orgId: currentOrg.id
|
||||
},
|
||||
search: memoizedSearch
|
||||
});
|
||||
}, [navigate, currentProject?.id, memoizedSearch]);
|
||||
}, [navigate, currentProject?.id, currentOrg.id, memoizedSearch]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!addSync) return;
|
||||
@@ -59,7 +60,7 @@ export const PkiSyncsTab = () => {
|
||||
handlePopUpOpen("addSync", { destination: parsedData.destination, initialData });
|
||||
navigate({
|
||||
to: ROUTE_PATHS.CertManager.IntegrationsListPage.path,
|
||||
params: { projectId: currentProject?.id },
|
||||
params: { projectId: currentProject?.id, orgId: currentOrg.id },
|
||||
search: { selectedTab: IntegrationsListPageTabs.PkiSyncs },
|
||||
replace: true
|
||||
});
|
||||
@@ -79,7 +80,8 @@ export const PkiSyncsTab = () => {
|
||||
connectionId,
|
||||
connectionName,
|
||||
navigate,
|
||||
currentProject?.id
|
||||
currentProject?.id,
|
||||
currentOrg.id
|
||||
]);
|
||||
|
||||
const { data: pkiSyncs = [], isPending: isPkiSyncsPending } = useListPkiSyncs(
|
||||
|
||||
@@ -15,7 +15,7 @@ const IntegrationsListPageQuerySchema = z.object({
|
||||
});
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/integrations/"
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/integrations/"
|
||||
)({
|
||||
component: IntegrationsListPage,
|
||||
validateSearch: zodValidator(IntegrationsListPageQuerySchema),
|
||||
|
||||
+11
-3
@@ -18,7 +18,12 @@ import {
|
||||
Tooltip
|
||||
} from "@app/components/v2";
|
||||
import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import { ProjectPermissionActions, ProjectPermissionSub, useProject } from "@app/context";
|
||||
import {
|
||||
ProjectPermissionActions,
|
||||
ProjectPermissionSub,
|
||||
useOrganization,
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { useDeletePkiCollection, useGetPkiCollectionById } from "@app/hooks/api";
|
||||
import { PkiItemType } from "@app/hooks/api/pkiCollections/constants";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
@@ -34,6 +39,7 @@ export const PkiCollectionPage = () => {
|
||||
});
|
||||
const collectionId = params.collectionId as string;
|
||||
const { currentProject } = useProject();
|
||||
const { currentOrg } = useOrganization();
|
||||
const projectId = currentProject?.id || "";
|
||||
|
||||
const { data } = useGetPkiCollectionById(collectionId);
|
||||
@@ -58,8 +64,9 @@ export const PkiCollectionPage = () => {
|
||||
});
|
||||
handlePopUpClose("deletePkiCollection");
|
||||
navigate({
|
||||
to: "/projects/cert-management/$projectId/policies",
|
||||
to: "/organizations/$orgId/projects/cert-management/$projectId/policies",
|
||||
params: {
|
||||
orgId: currentOrg.id,
|
||||
projectId: params.projectId
|
||||
}
|
||||
});
|
||||
@@ -70,8 +77,9 @@ export const PkiCollectionPage = () => {
|
||||
{data && (
|
||||
<div className="mx-auto mb-6 w-full max-w-8xl">
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/policies"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/policies"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId: params.projectId
|
||||
}}
|
||||
className="mb-4 flex items-center gap-x-2 text-sm text-mineshaft-400"
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
import { PkiCollectionDetailsByIDPage } from "./PkiCollectionDetailsByIDPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/pki-collections/$collectionId"
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/pki-collections/$collectionId"
|
||||
)({
|
||||
component: PkiCollectionDetailsByIDPage,
|
||||
beforeLoad: ({ context, params }) => {
|
||||
@@ -13,8 +13,9 @@ export const Route = createFileRoute(
|
||||
{
|
||||
label: "Certificate Collections",
|
||||
link: linkOptions({
|
||||
to: "/projects/cert-management/$projectId/policies",
|
||||
to: "/organizations/$orgId/projects/cert-management/$projectId/policies",
|
||||
params: {
|
||||
orgId: params.orgId,
|
||||
projectId: params.projectId
|
||||
}
|
||||
})
|
||||
|
||||
+6
-2
@@ -21,6 +21,7 @@ import { ROUTE_PATHS } from "@app/const/routes";
|
||||
import {
|
||||
ProjectPermissionPkiSubscriberActions,
|
||||
ProjectPermissionSub,
|
||||
useOrganization,
|
||||
useProject
|
||||
} from "@app/context";
|
||||
import { useDeletePkiSubscriber, useGetPkiSubscriber } from "@app/hooks/api";
|
||||
@@ -32,6 +33,7 @@ import { PkiSubscriberCertificatesSection, PkiSubscriberDetailsSection } from ".
|
||||
|
||||
const Page = () => {
|
||||
const navigate = useNavigate();
|
||||
const { currentOrg } = useOrganization();
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject.id;
|
||||
const subscriberName = useParams({
|
||||
@@ -62,8 +64,9 @@ const Page = () => {
|
||||
|
||||
handlePopUpClose("deletePkiSubscriber");
|
||||
navigate({
|
||||
to: "/projects/cert-management/$projectId/subscribers",
|
||||
to: "/organizations/$orgId/projects/cert-management/$projectId/subscribers",
|
||||
params: {
|
||||
orgId: currentOrg.id,
|
||||
projectId
|
||||
}
|
||||
});
|
||||
@@ -74,8 +77,9 @@ const Page = () => {
|
||||
{data && (
|
||||
<div className="mx-auto mb-6 w-full max-w-8xl">
|
||||
<Link
|
||||
to="/projects/cert-management/$projectId/subscribers"
|
||||
to="/organizations/$orgId/projects/cert-management/$projectId/subscribers"
|
||||
params={{
|
||||
orgId: currentOrg.id,
|
||||
projectId
|
||||
}}
|
||||
className="mb-4 flex items-center gap-x-2 text-sm text-mineshaft-400"
|
||||
|
||||
+1
-1
@@ -171,7 +171,7 @@ export const PkiSubscriberCertificatesTable = ({ subscriberName, handlePopUpOpen
|
||||
onClick={() =>
|
||||
handlePopUpOpen &&
|
||||
handlePopUpOpen("revokeCertificate", {
|
||||
serialNumber: certificate.serialNumber
|
||||
certificateId: certificate.id
|
||||
})
|
||||
}
|
||||
disabled={!isAllowed}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
import { PkiSubscriberDetailsByIDPage } from "./PkiSubscriberDetailsByIDPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/projects/cert-management/$projectId/_cert-manager-layout/subscribers/$subscriberName"
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/projects/cert-management/$projectId/_cert-manager-layout/subscribers/$subscriberName"
|
||||
)({
|
||||
component: PkiSubscriberDetailsByIDPage,
|
||||
beforeLoad: ({ context, params }) => {
|
||||
@@ -13,8 +13,9 @@ export const Route = createFileRoute(
|
||||
{
|
||||
label: "Subscribers",
|
||||
link: linkOptions({
|
||||
to: "/projects/cert-management/$projectId/subscribers",
|
||||
to: "/organizations/$orgId/projects/cert-management/$projectId/subscribers",
|
||||
params: {
|
||||
orgId: params.orgId,
|
||||
projectId: params.projectId
|
||||
}
|
||||
})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user