mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 10:28:21 +00:00
Merge remote-tracking branch 'origin/main' into feat/PKI-55
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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 = (
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -294,8 +294,8 @@ export const ROUTE_PATHS = Object.freeze({
|
||||
},
|
||||
CertManager: {
|
||||
CertAuthDetailsByIDPage: setRoute(
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/ca/$caName",
|
||||
"/_authenticate/_inject-org-details/_org-layout/organizations/$orgId/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(
|
||||
"/organizations/$orgId/projects/cert-management/$projectId/subscribers",
|
||||
|
||||
@@ -49,6 +49,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";
|
||||
@@ -111,6 +112,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" },
|
||||
@@ -214,6 +216,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"
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -184,6 +184,10 @@ export type TRedisConnectionOption = TAppConnectionOptionBase & {
|
||||
app: AppConnection.Redis;
|
||||
};
|
||||
|
||||
export type TDNSMadeEasyConnectionOption = TAppConnectionOptionBase & {
|
||||
app: AppConnection.DNSMadeEasy;
|
||||
};
|
||||
|
||||
export type TAppConnectionOption =
|
||||
| TAwsConnectionOption
|
||||
| TGitHubConnectionOption
|
||||
@@ -225,7 +229,8 @@ export type TAppConnectionOption =
|
||||
| TOktaConnectionOption
|
||||
| TAzureAdCsConnectionOption
|
||||
| TLaravelForgeConnectionOption
|
||||
| TChefConnectionOption;
|
||||
| TChefConnectionOption
|
||||
| TDNSMadeEasyConnectionOption;
|
||||
|
||||
export type TAppConnectionOptionMap = {
|
||||
[AppConnection.AWS]: TAwsConnectionOption;
|
||||
@@ -257,6 +262,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";
|
||||
@@ -57,6 +58,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";
|
||||
@@ -127,7 +129,8 @@ export type TAppConnection =
|
||||
| TNorthflankConnection
|
||||
| TOktaConnection
|
||||
| TRedisConnection
|
||||
| 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),
|
||||
@@ -202,7 +199,7 @@ export const useGetAzureAdcsTemplates = ({
|
||||
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)
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -21,11 +21,11 @@ import {
|
||||
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;
|
||||
},
|
||||
@@ -49,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
|
||||
}
|
||||
@@ -82,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;
|
||||
@@ -100,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;
|
||||
@@ -133,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;
|
||||
@@ -151,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
|
||||
@@ -170,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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -75,7 +75,7 @@ export type TUpdateRenewalConfigDTO = {
|
||||
};
|
||||
|
||||
export type TDownloadPkcs12DTO = {
|
||||
serialNumber: string;
|
||||
certificateId: string;
|
||||
projectSlug: string;
|
||||
password: string;
|
||||
alias: 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 {
|
||||
|
||||
@@ -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";
|
||||
|
||||
/*
|
||||
|
||||
@@ -14,8 +14,8 @@ export const KmsLayout = () => {
|
||||
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 }}
|
||||
|
||||
@@ -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 isProjectScope = location.pathname.startsWith(`/organizations/${currentOrg.id}/projects`);
|
||||
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">
|
||||
<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",
|
||||
(isProjectScope || 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: "/organizations/$orgId/projects",
|
||||
params: { orgId: currentOrg.id }
|
||||
});
|
||||
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.`}
|
||||
@@ -543,19 +536,15 @@ export const Navbar = () => {
|
||||
)}
|
||||
{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") ? (
|
||||
@@ -601,7 +594,7 @@ export const Navbar = () => {
|
||||
}}
|
||||
>
|
||||
<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
|
||||
}
|
||||
@@ -705,7 +698,7 @@ export const Navbar = () => {
|
||||
}}
|
||||
>
|
||||
<DropdownMenuItem icon={<FontAwesomeIcon icon={faUserPlus} />}>
|
||||
Invite Members
|
||||
Invite Users
|
||||
</DropdownMenuItem>
|
||||
</Link>
|
||||
) : null
|
||||
|
||||
@@ -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 }}
|
||||
@@ -114,6 +114,6 @@ export const OrgNavBar = ({ isHidden }: Props) => {
|
||||
isOpen={popUp?.createOrg?.isOpen}
|
||||
onClose={() => handlePopUpToggle("createOrg", false)}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -29,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 }}
|
||||
|
||||
@@ -29,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 }}
|
||||
|
||||
@@ -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,7 +92,11 @@ 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)}
|
||||
@@ -100,16 +104,12 @@ export const ProjectSelect = () => {
|
||||
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>
|
||||
@@ -118,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>
|
||||
@@ -238,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 />;
|
||||
};
|
||||
|
||||
@@ -39,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 }}
|
||||
|
||||
@@ -38,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 }}
|
||||
|
||||
@@ -20,8 +20,8 @@ export const SshLayout = () => {
|
||||
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 }}
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
|
||||
@@ -44,10 +44,9 @@ const Page = () => {
|
||||
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 };
|
||||
|
||||
@@ -66,7 +65,7 @@ const Page = () => {
|
||||
if (!currentProject?.slug) return;
|
||||
|
||||
await deleteCa({
|
||||
caName,
|
||||
id: data.id,
|
||||
projectId: currentProject.id,
|
||||
type: CaType.INTERNAL
|
||||
});
|
||||
@@ -138,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/organizations/$orgId/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 }) => {
|
||||
@@ -21,7 +21,7 @@ export const Route = createFileRoute(
|
||||
})
|
||||
},
|
||||
{
|
||||
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>
|
||||
|
||||
@@ -81,11 +81,11 @@ export const CaTable = ({ handlePopUpOpen }: Props) => {
|
||||
key={`ca-${ca.id}`}
|
||||
onClick={() =>
|
||||
navigate({
|
||||
to: "/organizations/$orgId/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
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -180,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
|
||||
@@ -207,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
|
||||
});
|
||||
}}
|
||||
|
||||
+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>
|
||||
|
||||
+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 || ""
|
||||
|
||||
+11
-5
@@ -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
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
@@ -49,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}>
|
||||
|
||||
+1
-1
@@ -171,7 +171,7 @@ export const PkiSubscriberCertificatesTable = ({ subscriberName, handlePopUpOpen
|
||||
onClick={() =>
|
||||
handlePopUpOpen &&
|
||||
handlePopUpOpen("revokeCertificate", {
|
||||
serialNumber: certificate.serialNumber
|
||||
certificateId: certificate.id
|
||||
})
|
||||
}
|
||||
disabled={!isAllowed}
|
||||
|
||||
+1
-1
@@ -675,7 +675,7 @@ export const CreateProfileModal = ({
|
||||
isDisabled={Boolean(isEdit)}
|
||||
>
|
||||
<SelectItem value="ca">Certificate Authority</SelectItem>
|
||||
<SelectItem value="self-signed">Self-signed</SelectItem>
|
||||
<SelectItem value="self-signed">Self-Signed</SelectItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
|
||||
+11
-16
@@ -30,7 +30,7 @@ import {
|
||||
ProjectPermissionSub
|
||||
} from "@app/context/ProjectPermissionContext/types";
|
||||
import { usePopUp, useToggle } from "@app/hooks";
|
||||
import { useGetCaById } from "@app/hooks/api/ca/queries";
|
||||
import { useGetInternalCaById } from "@app/hooks/api/ca/queries";
|
||||
import { IssuerType, TCertificateProfile } from "@app/hooks/api/certificateProfiles";
|
||||
import { useGetCertificateTemplateV2ById } from "@app/hooks/api/certificateTemplates/queries";
|
||||
import { CertificateIssuanceModal } from "@app/pages/cert-manager/CertificatesPage/components/CertificateIssuanceModal";
|
||||
@@ -50,9 +50,7 @@ export const ProfileRow = ({
|
||||
}: Props) => {
|
||||
const { permission } = useProjectPermission();
|
||||
|
||||
const { data: caData } = useGetCaById(
|
||||
profile.certificateAuthority?.isExternal ? "" : (profile.caId ?? "")
|
||||
);
|
||||
const { data: caData } = useGetInternalCaById(profile.caId ?? "");
|
||||
|
||||
const { popUp, handlePopUpToggle } = usePopUp(["issueCertificate"] as const);
|
||||
|
||||
@@ -123,18 +121,15 @@ export const ProfileRow = ({
|
||||
</Td>
|
||||
<Td className="text-start">{getEnrollmentTypeBadge(profile.enrollmentType)}</Td>
|
||||
<Td className="text-start">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-mineshaft-300">
|
||||
{profile.issuerType === IssuerType.SELF_SIGNED
|
||||
? "Self-signed"
|
||||
: profile.certificateAuthority?.isExternal
|
||||
? profile.certificateAuthority.name
|
||||
: caData?.friendlyName ||
|
||||
caData?.commonName ||
|
||||
profile.certificateAuthority?.name ||
|
||||
profile.caId}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-sm text-mineshaft-300">
|
||||
{profile.issuerType === IssuerType.SELF_SIGNED
|
||||
? "Self-signed"
|
||||
: profile.certificateAuthority?.isExternal
|
||||
? profile.certificateAuthority.name
|
||||
: caData?.configuration.friendlyName ||
|
||||
caData?.configuration.commonName ||
|
||||
profile.caId}
|
||||
</span>
|
||||
</Td>
|
||||
<Td>
|
||||
<span className="text-sm text-mineshaft-300">
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Helmet } from "react-helmet";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { InfoIcon } from "lucide-react";
|
||||
|
||||
import { PageHeader, Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
import { ProjectGeneralTab } from "@app/pages/project/SettingsPage/components/ProjectGeneralTab";
|
||||
|
||||
@@ -15,6 +18,7 @@ const tabs = [
|
||||
|
||||
export const SettingsPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const { currentOrg } = useOrganization();
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full justify-center bg-bunker-800 text-white">
|
||||
@@ -22,7 +26,17 @@ export const SettingsPage = () => {
|
||||
<title>{t("common.head-title", { title: t("settings.project.title") })}</title>
|
||||
</Helmet>
|
||||
<div className="w-full max-w-8xl">
|
||||
<PageHeader scope={ProjectType.CertificateManager} title={t("settings.project.title")} />
|
||||
<PageHeader scope={ProjectType.CertificateManager} title={t("settings.project.title")}>
|
||||
<Link
|
||||
to="/organizations/$orgId/settings"
|
||||
params={{
|
||||
orgId: currentOrg.id
|
||||
}}
|
||||
className="flex items-center gap-x-1.5 text-xs whitespace-nowrap text-neutral hover:underline"
|
||||
>
|
||||
<InfoIcon size={12} /> Looking for organization settings?
|
||||
</Link>
|
||||
</PageHeader>
|
||||
<Tabs orientation="vertical" defaultValue={tabs[0].key}>
|
||||
<TabList>
|
||||
{tabs.map((tab) => (
|
||||
|
||||
@@ -20,7 +20,7 @@ export const OverviewPage = () => {
|
||||
<div className="mx-auto mb-6 w-full max-w-8xl">
|
||||
<PageHeader
|
||||
scope={ProjectType.KMS}
|
||||
title="Overview"
|
||||
title="Project Overview"
|
||||
description="Manage keys and perform cryptographic operations."
|
||||
/>
|
||||
<ProjectPermissionCan
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Helmet } from "react-helmet";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { InfoIcon } from "lucide-react";
|
||||
|
||||
import { PageHeader, Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
||||
import { useOrganization } from "@app/context";
|
||||
import { ProjectType } from "@app/hooks/api/projects/types";
|
||||
import { ProjectGeneralTab } from "@app/pages/project/SettingsPage/components/ProjectGeneralTab";
|
||||
|
||||
@@ -16,6 +19,8 @@ const tabs = [
|
||||
export const SettingsPage = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { currentOrg } = useOrganization();
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full justify-center bg-bunker-800 text-white">
|
||||
<Helmet>
|
||||
@@ -24,9 +29,19 @@ export const SettingsPage = () => {
|
||||
<div className="w-full max-w-8xl">
|
||||
<PageHeader
|
||||
scope={ProjectType.KMS}
|
||||
title="Settings"
|
||||
title="Project Settings"
|
||||
description="Configure general project settings"
|
||||
/>
|
||||
>
|
||||
<Link
|
||||
to="/organizations/$orgId/settings"
|
||||
params={{
|
||||
orgId: currentOrg.id
|
||||
}}
|
||||
className="flex items-center gap-x-1.5 text-xs whitespace-nowrap text-neutral hover:underline"
|
||||
>
|
||||
<InfoIcon size={12} /> Looking for organization settings?
|
||||
</Link>
|
||||
</PageHeader>
|
||||
<Tabs orientation="vertical" defaultValue={tabs[0].key}>
|
||||
<TabList>
|
||||
{tabs.map((tab) => (
|
||||
|
||||
@@ -58,7 +58,7 @@ export const AccessManagementPage = () => {
|
||||
},
|
||||
{
|
||||
key: OrgAccessControlTabSections.Identities,
|
||||
label: "Identities",
|
||||
label: "Machine Identities",
|
||||
isHidden: permission.cannot(
|
||||
OrgPermissionIdentityActions.Read,
|
||||
OrgPermissionSubjects.Identity
|
||||
@@ -83,8 +83,8 @@ export const AccessManagementPage = () => {
|
||||
<div className="mx-auto mb-6 w-full max-w-8xl">
|
||||
<PageHeader
|
||||
scope={isSubOrganization ? "namespace" : "org"}
|
||||
title="Access Control"
|
||||
description="Manage fine-grained access for users, groups, roles, and identities within your organization resources."
|
||||
title={`${isSubOrganization ? "Sub-Organization" : "Organization"} Access Control`}
|
||||
description="Manage fine-grained access for users, groups, roles, and machine identities within your organization resources."
|
||||
/>
|
||||
{!currentOrg.shouldUseNewPrivilegeSystem && (
|
||||
<div className="mt-4 mb-4 flex flex-col rounded-r border-l-2 border-l-primary bg-mineshaft-300/5 px-4 py-2.5">
|
||||
|
||||
+3
-3
@@ -51,19 +51,19 @@ export const OrgGroupsSection = () => {
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="mb-4 flex flex-wrap items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-x-2">
|
||||
<p className="text-xl font-medium text-mineshaft-100">Groups</p>
|
||||
<p className="text-xl font-medium text-mineshaft-100">Organization Groups</p>
|
||||
<DocumentationLinkBadge href="https://infisical.com/docs/documentation/platform/groups" />
|
||||
</div>
|
||||
<OrgPermissionCan I={OrgPermissionGroupActions.Create} a={OrgPermissionSubjects.Groups}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => handleAddGroupModal()}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Create Group
|
||||
Create Organization Group
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
|
||||
+2
-2
@@ -159,7 +159,7 @@ export const OrgGroupsTable = ({ handlePopUpOpen }: Props) => {
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||
placeholder="Search groups..."
|
||||
placeholder="Search organization groups..."
|
||||
/>
|
||||
<TableContainer className="mt-4">
|
||||
<Table>
|
||||
@@ -205,7 +205,7 @@ export const OrgGroupsTable = ({ handlePopUpOpen }: Props) => {
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex items-center">
|
||||
Role
|
||||
Organization Role
|
||||
<IconButton
|
||||
variant="plain"
|
||||
className={`ml-2 ${orderBy === GroupsOrderBy.Role ? "" : "opacity-30"}`}
|
||||
|
||||
+3
-1
@@ -154,7 +154,9 @@ export const IdentityAuthTemplateModal = ({ popUp, handlePopUpToggle }: Props) =
|
||||
onOpenChange={handleClose}
|
||||
>
|
||||
<ModalContent
|
||||
title={isEdit ? "Edit Identity Auth Template" : "Create Identity Auth Template"}
|
||||
title={
|
||||
isEdit ? "Edit Machine Identity Auth Template" : "Create Machine Identity Auth Template"
|
||||
}
|
||||
subTitle={
|
||||
isEdit ? "Update the authentication template" : "Create a new authentication template"
|
||||
}
|
||||
|
||||
+26
-14
@@ -73,7 +73,7 @@ export const IdentitySection = withPermission(
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully deleted identity",
|
||||
text: "Successfully deleted machine identity",
|
||||
type: "success"
|
||||
});
|
||||
|
||||
@@ -99,7 +99,9 @@ export const IdentitySection = withPermission(
|
||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="mb-4 flex flex-wrap items-center justify-between gap-2">
|
||||
<div className="flex flex-1 items-center gap-x-2">
|
||||
<p className="text-xl font-medium text-mineshaft-100">Identities</p>
|
||||
<p className="text-xl font-medium text-mineshaft-100">
|
||||
Organization Machine Identities
|
||||
</p>
|
||||
<DocumentationLinkBadge href="https://infisical.com/docs/documentation/platform/identities/machine-identities" />
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
@@ -116,7 +118,7 @@ export const IdentitySection = withPermission(
|
||||
if (!isMoreIdentitiesAllowed && !isEnterprise) {
|
||||
handlePopUpOpen("upgradePlan", {
|
||||
description:
|
||||
"You can add more identities if you upgrade your Infisical Pro plan."
|
||||
"You can add more machine identities if you upgrade your Infisical Pro plan."
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -129,7 +131,9 @@ export const IdentitySection = withPermission(
|
||||
}}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Create Identity
|
||||
{isSubOrganization
|
||||
? "Add Machine Identity to Sub-Organization"
|
||||
: "Create Organization Machine Identity"}
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
@@ -141,7 +145,9 @@ export const IdentitySection = withPermission(
|
||||
<div className="mt-4 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="mb-4 flex flex-wrap items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-x-2">
|
||||
<p className="text-xl font-medium text-mineshaft-100">Identity Auth Templates</p>
|
||||
<p className="text-xl font-medium text-mineshaft-100">
|
||||
Machine Identity Auth Templates
|
||||
</p>
|
||||
<DocumentationLinkBadge href="https://infisical.com/docs/documentation/platform/identities/auth-templates" />
|
||||
</div>
|
||||
<OrgPermissionCan
|
||||
@@ -150,14 +156,14 @@ export const IdentitySection = withPermission(
|
||||
>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => {
|
||||
if (subscription && !subscription.machineIdentityAuthTemplates) {
|
||||
handlePopUpOpen("upgradePlan", {
|
||||
isEnterpriseFeature: true,
|
||||
text: "Your current plan does not include access to creating Identity Auth Templates. To unlock this feature, please upgrade to Infisical Enterprise plan."
|
||||
text: "Your current plan does not include access to creating Machine Identity Auth Templates. To unlock this feature, please upgrade to Infisical Enterprise plan."
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -197,9 +203,15 @@ export const IdentitySection = withPermission(
|
||||
>
|
||||
<ModalContent
|
||||
bodyClassName="overflow-visible"
|
||||
title="Add Identity"
|
||||
title={
|
||||
isSubOrganization
|
||||
? "Add Machine Identity to Sub-Organization"
|
||||
: "Create Organization Machine Identity"
|
||||
}
|
||||
subTitle={
|
||||
isSubOrganization ? "Create a new identity or assign an existing identity" : undefined
|
||||
isSubOrganization
|
||||
? "Create a new machine identity or assign an existing one"
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<AnimatePresence mode="wait">
|
||||
@@ -224,11 +236,11 @@ export const IdentitySection = withPermission(
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<PlusIcon size="1rem" />
|
||||
<div>Create New Identity</div>
|
||||
<div>Create Machine Identity</div>
|
||||
</div>
|
||||
<div className="mt-2 text-xs text-mineshaft-300">
|
||||
Create a new machine identity specifically for this sub-organization. This
|
||||
identity will be managed at the sub-organization level.
|
||||
machine identity will be managed at the sub-organization level.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -244,11 +256,11 @@ export const IdentitySection = withPermission(
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<LinkIcon size="1rem" />
|
||||
<div>Assign Existing Identity</div>
|
||||
<div>Assign Existing Machine Identity</div>
|
||||
</div>
|
||||
<div className="mt-2 text-xs text-mineshaft-300">
|
||||
Assign an existing identity from your parent organization. The identity will
|
||||
continue to be managed at its original scope.
|
||||
Assign an existing machine identity from your parent organization. The machine
|
||||
identity will continue to be managed at its original scope.
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
+9
-9
@@ -152,7 +152,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully updated identity role",
|
||||
text: "Successfully updated machine identity role",
|
||||
type: "success"
|
||||
});
|
||||
};
|
||||
@@ -178,7 +178,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<IconButton
|
||||
ariaLabel="Filter Identities"
|
||||
ariaLabel="Filter Machine Identities"
|
||||
variant="plain"
|
||||
size="sm"
|
||||
className={twMerge(
|
||||
@@ -200,7 +200,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
||||
</DropdownSubMenuTrigger>
|
||||
<DropdownSubMenuContent className="max-h-80 thin-scrollbar overflow-y-auto rounded-l-none">
|
||||
<DropdownMenuLabel className="sticky top-0 bg-mineshaft-900">
|
||||
Apply Roles to Filter Identities
|
||||
Filter Organization Machine Identities by Role
|
||||
</DropdownMenuLabel>
|
||||
{roles?.map(({ id, slug, name }) => (
|
||||
<DropdownMenuItem
|
||||
@@ -229,7 +229,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||
placeholder="Search identities by name..."
|
||||
placeholder="Search machine identities by name..."
|
||||
/>
|
||||
</div>
|
||||
<TableContainer>
|
||||
@@ -258,7 +258,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
||||
</Th>
|
||||
<Th>
|
||||
<div className="flex items-center">
|
||||
Role
|
||||
Organization Role
|
||||
<IconButton
|
||||
variant="plain"
|
||||
className={`ml-2 ${orderBy === OrgIdentityOrderBy.Role ? "" : "opacity-30"}`}
|
||||
@@ -407,7 +407,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
||||
}}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Edit Identity {isSubOrgIdentity ? "" : "Membership"}
|
||||
Edit Machine Identity {isSubOrgIdentity ? "" : "Membership"}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
@@ -428,7 +428,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
||||
icon={<FontAwesomeIcon icon={faTrash} />}
|
||||
>
|
||||
{isSubOrgIdentity
|
||||
? "Delete Identity"
|
||||
? "Delete Machine Identity"
|
||||
: "Remove From Sub-Organization"}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
@@ -455,8 +455,8 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
||||
<EmptyState
|
||||
title={
|
||||
debouncedSearch.trim().length > 0 || filter.roles?.length > 0
|
||||
? "No identities match search filter"
|
||||
: "No identities have been created in this organization"
|
||||
? "No machine identities match search filter"
|
||||
: "No machine identities have been created in this organization"
|
||||
}
|
||||
icon={faServer}
|
||||
/>
|
||||
|
||||
+2
-2
@@ -78,11 +78,11 @@ export const OrgIdentityLinkForm = ({ onClose }: Props) => {
|
||||
control={control}
|
||||
name="identity"
|
||||
render={({ field: { onChange, value }, fieldState: { error } }) => (
|
||||
<FormControl label="Identity" errorText={error?.message} isError={Boolean(error)}>
|
||||
<FormControl label="Machine Identity" errorText={error?.message} isError={Boolean(error)}>
|
||||
<FilterableSelect
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
placeholder="Select identity..."
|
||||
placeholder="Select machine identity..."
|
||||
// onInputChange={setSearchValue}
|
||||
options={rootOrgIdentities}
|
||||
getOptionValue={(option) => option.id}
|
||||
|
||||
+2
-4
@@ -164,7 +164,7 @@ export const OrgIdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
}
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${popUp?.identity?.data ? "updated" : "created"} identity`,
|
||||
text: `Successfully ${popUp?.identity?.data ? "updated" : "created"} machine identity`,
|
||||
type: "success"
|
||||
});
|
||||
|
||||
@@ -255,9 +255,7 @@ export const OrgIdentityModal = ({ popUp, handlePopUpToggle }: Props) => {
|
||||
/>
|
||||
</div>
|
||||
<div className="grow">
|
||||
{i === 0 && (
|
||||
<FormLabel label="Value" className="text-xs text-mineshaft-400" isOptional />
|
||||
)}
|
||||
{i === 0 && <FormLabel label="Value" className="text-xs text-mineshaft-400" />}
|
||||
<Controller
|
||||
control={control}
|
||||
name={`metadata.${i}.value`}
|
||||
|
||||
+5
-3
@@ -159,14 +159,16 @@ export const AddOrgMemberModal = ({
|
||||
)
|
||||
);
|
||||
|
||||
setCompleteInviteLinks(data?.completeInviteLinks ?? null);
|
||||
if (data?.completeInviteLinks && data?.completeInviteLinks.length > 0) {
|
||||
setCompleteInviteLinks(data.completeInviteLinks);
|
||||
}
|
||||
|
||||
// only show this notification when email is configured.
|
||||
// A [completeInviteLink] will not be sent if smtp is configured
|
||||
|
||||
if (!data.completeInviteLinks) {
|
||||
if (!data.completeInviteLinks?.length) {
|
||||
createNotification({
|
||||
text: "Successfully invited user to the organization.",
|
||||
text: `Successfully invited user${usernames.length > 1 ? "s" : ""} to the organization.`,
|
||||
type: "success"
|
||||
});
|
||||
}
|
||||
|
||||
+5
-3
@@ -205,13 +205,13 @@ export const OrgMembersSection = () => {
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="mb-4 flex flex-wrap items-center justify-between gap-2">
|
||||
<div className="flex items-center gap-x-2">
|
||||
<p className="text-xl font-medium text-mineshaft-100">Users</p>
|
||||
<p className="text-xl font-medium text-mineshaft-100">Organization Users</p>
|
||||
<DocumentationLinkBadge href="https://infisical.com/docs/documentation/platform/identities/user-identities" />
|
||||
</div>
|
||||
<OrgPermissionCan I={OrgPermissionActions.Create} a={OrgPermissionSubjects.Member}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
leftIcon={<UserPlusIcon size={16} />}
|
||||
onClick={() =>
|
||||
@@ -219,7 +219,9 @@ export const OrgMembersSection = () => {
|
||||
}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
{isSubOrganization ? "Add Members" : "Invite Members"}
|
||||
{isSubOrganization
|
||||
? "Add Users to Sub-Organization"
|
||||
: "Invite Users to Organization"}
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
|
||||
+5
-5
@@ -336,7 +336,7 @@ export const OrgMembersTable = ({
|
||||
</DropdownSubMenuTrigger>
|
||||
<DropdownSubMenuContent className="max-h-80 thin-scrollbar overflow-y-auto rounded-l-none">
|
||||
<DropdownMenuLabel className="sticky top-0 bg-mineshaft-900">
|
||||
Apply Roles to Filter Users
|
||||
Filter Organization Users by Role
|
||||
</DropdownMenuLabel>
|
||||
{roles?.map(({ id, slug, name }) => (
|
||||
<DropdownMenuItem
|
||||
@@ -365,7 +365,7 @@ export const OrgMembersTable = ({
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||
placeholder="Search members..."
|
||||
placeholder="Search organization users..."
|
||||
/>
|
||||
</div>
|
||||
<TableContainer className="mt-4">
|
||||
@@ -434,7 +434,7 @@ export const OrgMembersTable = ({
|
||||
</Th>
|
||||
<Th className="w-1/3">
|
||||
<div className="flex items-center">
|
||||
Role
|
||||
Organization Role
|
||||
<IconButton
|
||||
variant="plain"
|
||||
className={`ml-2 ${orderBy === OrgMembersOrderBy.Role ? "" : "opacity-30"}`}
|
||||
@@ -727,8 +727,8 @@ export const OrgMembersTable = ({
|
||||
<EmptyState
|
||||
title={
|
||||
members.length
|
||||
? "No organization members match search..."
|
||||
: "No organization members found"
|
||||
? "No organization users match search..."
|
||||
: "No organization users found"
|
||||
}
|
||||
icon={members.length ? faSearch : faUsers}
|
||||
/>
|
||||
|
||||
+4
-4
@@ -199,7 +199,7 @@ export const OrgRoleTable = () => {
|
||||
<OrgPermissionCan I={OrgPermissionActions.Create} a={OrgPermissionSubjects.Role}>
|
||||
{(isAllowed) => (
|
||||
<Button
|
||||
colorSchema="secondary"
|
||||
variant="outline_bg"
|
||||
type="submit"
|
||||
leftIcon={<FontAwesomeIcon icon={faPlus} />}
|
||||
onClick={() => {
|
||||
@@ -207,7 +207,7 @@ export const OrgRoleTable = () => {
|
||||
}}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Add Role
|
||||
Add Organization Role
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
@@ -216,7 +216,7 @@ export const OrgRoleTable = () => {
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||
placeholder="Search roles..."
|
||||
placeholder="Search organization roles..."
|
||||
className="flex-1"
|
||||
containerClassName="mb-4"
|
||||
/>
|
||||
@@ -441,7 +441,7 @@ export const OrgRoleTable = () => {
|
||||
<EmptyState
|
||||
title={
|
||||
roles?.length
|
||||
? "No roles match search..."
|
||||
? "No organization roles match search..."
|
||||
: "This organization does not have any roles"
|
||||
}
|
||||
icon={roles?.length ? faSearch : undefined}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ export const AppConnectionsPage = withPermission(
|
||||
<PageHeader
|
||||
scope={isSubOrganization ? "namespace" : "org"}
|
||||
className="w-full"
|
||||
title="App Connections"
|
||||
title={`${isSubOrganization ? "Sub-Organization" : "Organization"} App Connections`}
|
||||
description="Manage organization App Connections"
|
||||
/>
|
||||
<div className="mb-4 flex w-full flex-col rounded-md border border-blue-500/50 bg-blue-500/30 px-4 py-2 text-sm text-blue-200">
|
||||
|
||||
+5
@@ -24,6 +24,7 @@ import { ChefConnectionForm } from "./ChefConnectionForm";
|
||||
import { CloudflareConnectionForm } from "./CloudflareConnectionForm";
|
||||
import { DatabricksConnectionForm } from "./DatabricksConnectionForm";
|
||||
import { DigitalOceanConnectionForm } from "./DigitalOceanConnectionForm";
|
||||
import { DNSMadeEasyConnectionForm } from "./DNSMadeEasyConnectionForm";
|
||||
import { FlyioConnectionForm } from "./FlyioConnectionForm";
|
||||
import { GcpConnectionForm } from "./GcpConnectionForm";
|
||||
import { GitHubConnectionForm } from "./GitHubConnectionForm";
|
||||
@@ -148,6 +149,8 @@ const CreateForm = ({ app, onComplete, projectId }: CreateFormProps) => {
|
||||
return <GitLabConnectionForm onSubmit={onSubmit} projectId={projectId} />;
|
||||
case AppConnection.Cloudflare:
|
||||
return <CloudflareConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.DNSMadeEasy:
|
||||
return <DNSMadeEasyConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.Bitbucket:
|
||||
return <BitbucketConnectionForm onSubmit={onSubmit} />;
|
||||
case AppConnection.Zabbix:
|
||||
@@ -306,6 +309,8 @@ const UpdateForm = ({ appConnection, onComplete }: UpdateFormProps) => {
|
||||
);
|
||||
case AppConnection.Cloudflare:
|
||||
return <CloudflareConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||
case AppConnection.DNSMadeEasy:
|
||||
return <DNSMadeEasyConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||
case AppConnection.Bitbucket:
|
||||
return <BitbucketConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
|
||||
case AppConnection.Zabbix:
|
||||
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
Input,
|
||||
ModalClose,
|
||||
SecretInput,
|
||||
Select,
|
||||
SelectItem
|
||||
} from "@app/components/v2";
|
||||
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
|
||||
import { TDNSMadeEasyConnection } from "@app/hooks/api/appConnections";
|
||||
import { AppConnection } from "@app/hooks/api/appConnections/enums";
|
||||
import { DNSMadeEasyConnectionMethod } from "@app/hooks/api/appConnections/types/dns-made-easy-connection";
|
||||
|
||||
import {
|
||||
genericAppConnectionFieldsSchema,
|
||||
GenericAppConnectionsFields
|
||||
} from "./GenericAppConnectionFields";
|
||||
|
||||
type Props = {
|
||||
appConnection?: TDNSMadeEasyConnection;
|
||||
onSubmit: (formData: FormData) => Promise<void>;
|
||||
};
|
||||
|
||||
const rootSchema = genericAppConnectionFieldsSchema.extend({
|
||||
app: z.literal(AppConnection.DNSMadeEasy)
|
||||
});
|
||||
|
||||
const formSchema = z.discriminatedUnion("method", [
|
||||
rootSchema.extend({
|
||||
method: z.literal(DNSMadeEasyConnectionMethod.APIKeySecret),
|
||||
credentials: z.object({
|
||||
apiKey: z.string().trim().min(1, "API Key required"),
|
||||
secretKey: z.string().trim().min(1, "Secret Key required")
|
||||
})
|
||||
})
|
||||
]);
|
||||
|
||||
type FormData = z.infer<typeof formSchema>;
|
||||
|
||||
export const DNSMadeEasyConnectionForm = ({ appConnection, onSubmit }: Props) => {
|
||||
const isUpdate = Boolean(appConnection);
|
||||
|
||||
const form = useForm<FormData>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: appConnection ?? {
|
||||
app: AppConnection.DNSMadeEasy,
|
||||
method: DNSMadeEasyConnectionMethod.APIKeySecret,
|
||||
credentials: {
|
||||
apiKey: "",
|
||||
secretKey: ""
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
formState: { isSubmitting, isDirty }
|
||||
} = form;
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
{!isUpdate && <GenericAppConnectionsFields />}
|
||||
<Controller
|
||||
name="method"
|
||||
control={control}
|
||||
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
tooltipText={`The method you would like to use to connect with ${
|
||||
APP_CONNECTION_MAP[AppConnection.DNSMadeEasy].name
|
||||
}. This field cannot be changed after creation.`}
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error?.message)}
|
||||
label="Method"
|
||||
>
|
||||
<Select
|
||||
isDisabled={isUpdate}
|
||||
value={value}
|
||||
onValueChange={(val) => onChange(val)}
|
||||
className="w-full border border-mineshaft-500"
|
||||
position="popper"
|
||||
dropdownContainerClassName="max-w-none"
|
||||
>
|
||||
{Object.values(DNSMadeEasyConnectionMethod).map((method) => {
|
||||
return (
|
||||
<SelectItem value={method} key={method}>
|
||||
{getAppConnectionMethodDetails(method).name}{" "}
|
||||
</SelectItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="credentials.apiKey"
|
||||
control={control}
|
||||
shouldUnregister
|
||||
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error?.message)}
|
||||
label="API Key"
|
||||
>
|
||||
<Input
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
placeholder="af1b628f-3272-46aa-9cde-837d0c59155d"
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
name="credentials.secretKey"
|
||||
control={control}
|
||||
shouldUnregister
|
||||
render={({ field: { value, onChange }, fieldState: { error } }) => (
|
||||
<FormControl
|
||||
errorText={error?.message}
|
||||
isError={Boolean(error?.message)}
|
||||
label="Secret Key"
|
||||
>
|
||||
<SecretInput
|
||||
containerClassName="text-gray-400 group-focus-within:border-primary-400/50! border border-mineshaft-500 bg-mineshaft-900 px-2.5 py-1.5"
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
<div className="mt-8 flex items-center">
|
||||
<Button
|
||||
className="mr-4"
|
||||
size="sm"
|
||||
type="submit"
|
||||
colorSchema="secondary"
|
||||
isLoading={isSubmitting}
|
||||
isDisabled={isSubmitting || !isDirty}
|
||||
>
|
||||
{isUpdate ? "Update Credentials" : "Connect to DNS Made Easy"}
|
||||
</Button>
|
||||
<ModalClose asChild>
|
||||
<Button colorSchema="secondary" variant="plain">
|
||||
Cancel
|
||||
</Button>
|
||||
</ModalClose>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
);
|
||||
};
|
||||
@@ -19,7 +19,7 @@ export const AuditLogsPage = () => {
|
||||
<div className="w-full max-w-8xl">
|
||||
<PageHeader
|
||||
scope={isSubOrganization ? "namespace" : "org"}
|
||||
title="Audit Logs"
|
||||
title={`${isSubOrganization ? "Sub-Organization" : "Organization"} Audit Logs`}
|
||||
description="Audit logs for security and compliance teams to monitor information access."
|
||||
/>
|
||||
<LogsSection pageView />
|
||||
|
||||
@@ -88,7 +88,7 @@ const Page = () => {
|
||||
className="mb-4 flex items-center gap-x-2 text-sm text-mineshaft-400"
|
||||
>
|
||||
<FontAwesomeIcon icon={faChevronLeft} />
|
||||
Groups
|
||||
Organization Groups
|
||||
</Link>
|
||||
<PageHeader
|
||||
scope={isSubOrganization ? "namespace" : "org"}
|
||||
|
||||
@@ -55,7 +55,7 @@ const Page = () => {
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully deleted identity",
|
||||
text: "Successfully deleted machine identity",
|
||||
type: "success"
|
||||
});
|
||||
|
||||
@@ -82,11 +82,11 @@ const Page = () => {
|
||||
className="mb-4 flex items-center gap-x-2 text-sm text-mineshaft-400"
|
||||
>
|
||||
<FontAwesomeIcon icon={faChevronLeft} />
|
||||
Identities
|
||||
Organization Machine Identities
|
||||
</Link>
|
||||
<PageHeader
|
||||
scope={isSubOrganization ? "namespace" : "org"}
|
||||
description={`${isSubOrganization ? "Sub-" : ""}Organization Identity`}
|
||||
description={`${isSubOrganization ? "Sub-" : ""}Organization Machine Identity`}
|
||||
title={data.identity.name}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -111,7 +111,7 @@ const Page = () => {
|
||||
})
|
||||
}
|
||||
>
|
||||
Unlink Identity
|
||||
Unlink Machine Identity
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
@@ -142,7 +142,7 @@ const Page = () => {
|
||||
>
|
||||
<ModalContent
|
||||
bodyClassName="overflow-visible"
|
||||
title={`${popUp?.identity?.data ? "Update" : "Create"} Identity`}
|
||||
title={`${popUp?.identity?.data ? "Update" : "Create"} Machine Identity`}
|
||||
>
|
||||
<OrgIdentityModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||
</ModalContent>
|
||||
|
||||
+4
-4
@@ -45,7 +45,7 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen, isOrgIdent
|
||||
return data ? (
|
||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
||||
<h3 className="text-lg font-medium text-mineshaft-100">Identity Details</h3>
|
||||
<h3 className="text-lg font-medium text-mineshaft-100">Details</h3>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
@@ -86,7 +86,7 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen, isOrgIdent
|
||||
}}
|
||||
disabled={!isAllowed}
|
||||
>
|
||||
{isOrgIdentity ? "Edit Identity" : "Edit Identity Role"}
|
||||
{isOrgIdentity ? "Edit Machine Identity" : "Edit Machine Identity Role"}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
@@ -110,7 +110,7 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen, isOrgIdent
|
||||
icon={<FontAwesomeIcon icon={faTrash} />}
|
||||
disabled={!isAllowed}
|
||||
>
|
||||
{!isOrgIdentity ? "Remove From Sub-Organization" : "Delete Identity"}
|
||||
{!isOrgIdentity ? "Remove From Sub-Organization" : "Delete Machine Identity"}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
@@ -119,7 +119,7 @@ export const IdentityDetailsSection = ({ identityId, handlePopUpOpen, isOrgIdent
|
||||
</div>
|
||||
<div className="pt-4">
|
||||
<div className="mb-4">
|
||||
<p className="text-sm font-medium text-mineshaft-300">Identity ID</p>
|
||||
<p className="text-sm font-medium text-mineshaft-300">Machine Identity ID</p>
|
||||
<div className="group flex align-top">
|
||||
<p className="text-sm text-mineshaft-300">{data.identity.id}</p>
|
||||
<div className="opacity-0 transition-opacity duration-300 group-hover:opacity-100">
|
||||
|
||||
+1
-1
@@ -167,7 +167,7 @@ export const IdentityAddToProjectModal = ({ identityId, popUp, handlePopUpToggle
|
||||
handlePopUpToggle("addIdentityToProject", isOpen);
|
||||
}}
|
||||
>
|
||||
<ModalContent bodyClassName="overflow-visible" title="Add Identity to Project">
|
||||
<ModalContent bodyClassName="overflow-visible" title="Add Machine Identity to Project">
|
||||
<Content identityId={identityId} handlePopUpToggle={handlePopUpToggle} />
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
||||
+1
-1
@@ -151,7 +151,7 @@ export const IdentityProjectsTable = ({ identityId, handlePopUpOpen }: Props) =>
|
||||
title={
|
||||
projectMemberships.length
|
||||
? "No projects match search..."
|
||||
: "This identity has not been assigned to any projects"
|
||||
: "This machine identity has not been assigned to any projects"
|
||||
}
|
||||
icon={projectMemberships.length ? faSearch : faFolder}
|
||||
/>
|
||||
|
||||
+13
-13
@@ -55,10 +55,10 @@ const formSchemaWithIdentity = baseFormSchema.extend({
|
||||
id: z.string(),
|
||||
name: z.string()
|
||||
},
|
||||
{ required_error: "Identity is required" }
|
||||
{ required_error: "Machine identity is required" }
|
||||
)
|
||||
.nullable()
|
||||
.refine((val) => val !== null, { message: "Identity is required" })
|
||||
.refine((val) => val !== null, { message: "Machine identity is required" })
|
||||
});
|
||||
|
||||
const formSchemaWithToken = baseFormSchema.extend({
|
||||
@@ -275,8 +275,8 @@ export const GatewayCliDeploymentMethod = () => {
|
||||
{canCreateToken && autogenerateToken ? (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity"
|
||||
tooltipText="The identity that your gateway will use for authentication."
|
||||
label="Machine Identity"
|
||||
tooltipText="The machine identity that your gateway will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<FilterableSelect
|
||||
@@ -290,7 +290,7 @@ export const GatewayCliDeploymentMethod = () => {
|
||||
)
|
||||
}
|
||||
isLoading={isIdentitiesLoading}
|
||||
placeholder="Select identity..."
|
||||
placeholder="Select machine identity..."
|
||||
options={identityMembershipOrgs.map((membership) => membership.identity)}
|
||||
getOptionValue={(option) => option.id}
|
||||
getOptionLabel={(option) => option.name}
|
||||
@@ -300,14 +300,14 @@ export const GatewayCliDeploymentMethod = () => {
|
||||
) : (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity Token"
|
||||
tooltipText="The identity token that your gateway will use for authentication."
|
||||
label="Machine Identity Token"
|
||||
tooltipText="The machine identity token that your gateway will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<Input
|
||||
value={identityToken}
|
||||
onChange={(e) => setIdentityToken(e.target.value)}
|
||||
placeholder="Enter identity token..."
|
||||
placeholder="Enter machine identity token..."
|
||||
isError={Boolean(errors.identityToken)}
|
||||
/>
|
||||
{errors.identityToken && <p className="mt-1 text-sm text-red">{errors.identityToken}</p>}
|
||||
@@ -325,15 +325,15 @@ export const GatewayCliDeploymentMethod = () => {
|
||||
className="mr-2"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<span>Automatically enable token auth and generate a token for identity</span>
|
||||
<span>Automatically enable token auth and generate a token for machine identity</span>
|
||||
<Tooltip
|
||||
className="max-w-md"
|
||||
content={
|
||||
<>
|
||||
Token authentication will be automatically enabled for the selected identity if
|
||||
it isn't already configured. By default, it will be configured to allow all
|
||||
IP addresses with a token TTL of 30 days. You can manage these settings in
|
||||
Access Control.
|
||||
Token authentication will be automatically enabled for the selected machine
|
||||
identity if it isn't already configured. By default, it will be configured
|
||||
to allow all IP addresses with a token TTL of 30 days. You can manage these
|
||||
settings in Access Control.
|
||||
<br />
|
||||
<br />A token will automatically be generated to be used with the CLI command.
|
||||
</>
|
||||
|
||||
+13
-13
@@ -55,10 +55,10 @@ const formSchemaWithIdentity = baseFormSchema.extend({
|
||||
id: z.string(),
|
||||
name: z.string()
|
||||
},
|
||||
{ required_error: "Identity is required" }
|
||||
{ required_error: "Machine identity is required" }
|
||||
)
|
||||
.nullable()
|
||||
.refine((val) => val !== null, { message: "Identity is required" })
|
||||
.refine((val) => val !== null, { message: "Machine identity is required" })
|
||||
});
|
||||
|
||||
const formSchemaWithToken = baseFormSchema.extend({
|
||||
@@ -297,8 +297,8 @@ export const GatewayCliSystemdDeploymentMethod = () => {
|
||||
{canCreateToken && autogenerateToken ? (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity"
|
||||
tooltipText="The identity that your gateway will use for authentication."
|
||||
label="Machine Identity"
|
||||
tooltipText="The machine identity that your gateway will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<FilterableSelect
|
||||
@@ -312,7 +312,7 @@ export const GatewayCliSystemdDeploymentMethod = () => {
|
||||
)
|
||||
}
|
||||
isLoading={isIdentitiesLoading}
|
||||
placeholder="Select identity..."
|
||||
placeholder="Select machine identity..."
|
||||
options={identityMembershipOrgs.map((membership) => membership.identity)}
|
||||
getOptionValue={(option) => option.id}
|
||||
getOptionLabel={(option) => option.name}
|
||||
@@ -322,14 +322,14 @@ export const GatewayCliSystemdDeploymentMethod = () => {
|
||||
) : (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity Token"
|
||||
tooltipText="The identity token that your gateway will use for authentication."
|
||||
label="Machine Identity Token"
|
||||
tooltipText="The machine identity token that your gateway will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<Input
|
||||
value={identityToken}
|
||||
onChange={(e) => setIdentityToken(e.target.value)}
|
||||
placeholder="Enter identity token..."
|
||||
placeholder="Enter machine identity token..."
|
||||
isError={Boolean(errors.identityToken)}
|
||||
/>
|
||||
{errors.identityToken && <p className="mt-1 text-sm text-red">{errors.identityToken}</p>}
|
||||
@@ -347,15 +347,15 @@ export const GatewayCliSystemdDeploymentMethod = () => {
|
||||
className="mr-2"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<span>Automatically enable token auth and generate a token for identity</span>
|
||||
<span>Automatically enable token auth and generate a token for machine identity</span>
|
||||
<Tooltip
|
||||
className="max-w-md"
|
||||
content={
|
||||
<>
|
||||
Token authentication will be automatically enabled for the selected identity if
|
||||
it isn't already configured. By default, it will be configured to allow all
|
||||
IP addresses with a token TTL of 30 days. You can manage these settings in
|
||||
Access Control.
|
||||
Token authentication will be automatically enabled for the selected machine
|
||||
identity if it isn't already configured. By default, it will be configured
|
||||
to allow all IP addresses with a token TTL of 30 days. You can manage these
|
||||
settings in Access Control.
|
||||
<br />
|
||||
<br />A token will automatically be generated to be used with the CLI command.
|
||||
</>
|
||||
|
||||
+13
-13
@@ -41,10 +41,10 @@ const formSchemaWithIdentity = baseFormSchema.extend({
|
||||
id: z.string(),
|
||||
name: z.string()
|
||||
},
|
||||
{ required_error: "Identity is required" }
|
||||
{ required_error: "Machine identity is required" }
|
||||
)
|
||||
.nullable()
|
||||
.refine((val) => val !== null, { message: "Identity is required" })
|
||||
.refine((val) => val !== null, { message: "Machine identity is required" })
|
||||
});
|
||||
|
||||
const formSchemaWithToken = baseFormSchema.extend({
|
||||
@@ -229,8 +229,8 @@ export const RelayCliDeploymentMethod = () => {
|
||||
{canCreateToken && autogenerateToken ? (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity"
|
||||
tooltipText="The identity that your relay will use for authentication."
|
||||
label="Machine Identity"
|
||||
tooltipText="The machine identity that your relay will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<FilterableSelect
|
||||
@@ -244,7 +244,7 @@ export const RelayCliDeploymentMethod = () => {
|
||||
)
|
||||
}
|
||||
isLoading={isIdentitiesLoading}
|
||||
placeholder="Select identity..."
|
||||
placeholder="Select machine identity..."
|
||||
options={identityMembershipOrgs.map((membership) => membership.identity)}
|
||||
getOptionValue={(option) => option.id}
|
||||
getOptionLabel={(option) => option.name}
|
||||
@@ -254,14 +254,14 @@ export const RelayCliDeploymentMethod = () => {
|
||||
) : (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity Token"
|
||||
tooltipText="The identity token that your relay will use for authentication."
|
||||
label="Machine Identity Token"
|
||||
tooltipText="The machine identity token that your relay will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<Input
|
||||
value={identityToken}
|
||||
onChange={(e) => setIdentityToken(e.target.value)}
|
||||
placeholder="Enter identity token..."
|
||||
placeholder="Enter machine identity token..."
|
||||
isError={Boolean(errors.identityToken)}
|
||||
/>
|
||||
{errors.identityToken && <p className="mt-1 text-sm text-red">{errors.identityToken}</p>}
|
||||
@@ -279,15 +279,15 @@ export const RelayCliDeploymentMethod = () => {
|
||||
className="mr-2"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<span>Automatically enable token auth and generate a token for identity</span>
|
||||
<span>Automatically enable token auth and generate a token for machine identity</span>
|
||||
<Tooltip
|
||||
className="max-w-md"
|
||||
content={
|
||||
<>
|
||||
Token authentication will be automatically enabled for the selected identity if
|
||||
it isn't already configured. By default, it will be configured to allow all
|
||||
IP addresses with a token TTL of 30 days. You can manage these settings in
|
||||
Access Control.
|
||||
Token authentication will be automatically enabled for the selected machine
|
||||
identity if it isn't already configured. By default, it will be configured
|
||||
to allow all IP addresses with a token TTL of 30 days. You can manage these
|
||||
settings in Access Control.
|
||||
<br />
|
||||
<br />A token will automatically be generated to be used with the CLI command.
|
||||
</>
|
||||
|
||||
+13
-13
@@ -41,10 +41,10 @@ const formSchemaWithIdentity = baseFormSchema.extend({
|
||||
id: z.string(),
|
||||
name: z.string()
|
||||
},
|
||||
{ required_error: "Identity is required" }
|
||||
{ required_error: "Machine identity is required" }
|
||||
)
|
||||
.nullable()
|
||||
.refine((val) => val !== null, { message: "Identity is required" })
|
||||
.refine((val) => val !== null, { message: "Machine identity is required" })
|
||||
});
|
||||
|
||||
const formSchemaWithToken = baseFormSchema.extend({
|
||||
@@ -270,8 +270,8 @@ export const RelayCliSystemdDeploymentMethod = () => {
|
||||
{canCreateToken && autogenerateToken ? (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity"
|
||||
tooltipText="The identity that your relay will use for authentication."
|
||||
label="Machine Identity"
|
||||
tooltipText="The machine identity that your relay will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<FilterableSelect
|
||||
@@ -285,7 +285,7 @@ export const RelayCliSystemdDeploymentMethod = () => {
|
||||
)
|
||||
}
|
||||
isLoading={isIdentitiesLoading}
|
||||
placeholder="Select identity..."
|
||||
placeholder="Select machine identity..."
|
||||
options={identityMembershipOrgs.map((membership) => membership.identity)}
|
||||
getOptionValue={(option) => option.id}
|
||||
getOptionLabel={(option) => option.name}
|
||||
@@ -295,14 +295,14 @@ export const RelayCliSystemdDeploymentMethod = () => {
|
||||
) : (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity Token"
|
||||
tooltipText="The identity token that your relay will use for authentication."
|
||||
label="Machine Identity Token"
|
||||
tooltipText="The machine identity token that your relay will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<Input
|
||||
value={identityToken}
|
||||
onChange={(e) => setIdentityToken(e.target.value)}
|
||||
placeholder="Enter identity token..."
|
||||
placeholder="Enter machine identity token..."
|
||||
isError={Boolean(errors.identityToken)}
|
||||
/>
|
||||
{errors.identityToken && <p className="mt-1 text-sm text-red">{errors.identityToken}</p>}
|
||||
@@ -320,15 +320,15 @@ export const RelayCliSystemdDeploymentMethod = () => {
|
||||
className="mr-2"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<span>Automatically enable token auth and generate a token for identity</span>
|
||||
<span>Automatically enable token auth and generate a token for machine identity</span>
|
||||
<Tooltip
|
||||
className="max-w-md"
|
||||
content={
|
||||
<>
|
||||
Token authentication will be automatically enabled for the selected identity if
|
||||
it isn't already configured. By default, it will be configured to allow all
|
||||
IP addresses with a token TTL of 30 days. You can manage these settings in
|
||||
Access Control.
|
||||
Token authentication will be automatically enabled for the selected machine
|
||||
identity if it isn't already configured. By default, it will be configured
|
||||
to allow all IP addresses with a token TTL of 30 days. You can manage these
|
||||
settings in Access Control.
|
||||
<br />
|
||||
<br />A token will automatically be generated to be used with the CLI command.
|
||||
</>
|
||||
|
||||
+13
-13
@@ -42,10 +42,10 @@ const formSchemaWithIdentity = baseFormSchema.extend({
|
||||
id: z.string(),
|
||||
name: z.string()
|
||||
},
|
||||
{ required_error: "Identity is required" }
|
||||
{ required_error: "Machine identity is required" }
|
||||
)
|
||||
.nullable()
|
||||
.refine((val) => val !== null, { message: "Identity is required" })
|
||||
.refine((val) => val !== null, { message: "Machine identity is required" })
|
||||
});
|
||||
|
||||
const formSchemaWithToken = baseFormSchema.extend({
|
||||
@@ -349,8 +349,8 @@ resource "aws_eip_association" "eip_assoc" {
|
||||
{canCreateToken && autogenerateToken ? (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity"
|
||||
tooltipText="The identity that your relay will use for authentication."
|
||||
label="Machine Identity"
|
||||
tooltipText="The machine identity that your relay will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<FilterableSelect
|
||||
@@ -364,7 +364,7 @@ resource "aws_eip_association" "eip_assoc" {
|
||||
)
|
||||
}
|
||||
isLoading={isIdentitiesLoading}
|
||||
placeholder="Select identity..."
|
||||
placeholder="Select machine identity..."
|
||||
options={identityMembershipOrgs.map((membership) => membership.identity)}
|
||||
getOptionValue={(option) => option.id}
|
||||
getOptionLabel={(option) => option.name}
|
||||
@@ -374,14 +374,14 @@ resource "aws_eip_association" "eip_assoc" {
|
||||
) : (
|
||||
<>
|
||||
<FormLabel
|
||||
label="Identity Token"
|
||||
tooltipText="The identity token that your relay will use for authentication."
|
||||
label="Machine Identity Token"
|
||||
tooltipText="The machine identity token that your relay will use for authentication."
|
||||
className="mt-4"
|
||||
/>
|
||||
<Input
|
||||
value={identityToken}
|
||||
onChange={(e) => setIdentityToken(e.target.value)}
|
||||
placeholder="Enter identity token..."
|
||||
placeholder="Enter machine identity token..."
|
||||
isError={Boolean(errors.identityToken)}
|
||||
/>
|
||||
{errors.identityToken && <p className="mt-1 text-sm text-red">{errors.identityToken}</p>}
|
||||
@@ -399,15 +399,15 @@ resource "aws_eip_association" "eip_assoc" {
|
||||
className="mr-2"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<span>Automatically enable token auth and generate a token for identity</span>
|
||||
<span>Automatically enable token auth and generate a token for machine identity</span>
|
||||
<Tooltip
|
||||
className="max-w-md"
|
||||
content={
|
||||
<>
|
||||
Token authentication will be automatically enabled for the selected identity if
|
||||
it isn't already configured. By default, it will be configured to allow all
|
||||
IP addresses with a token TTL of 30 days. You can manage these settings in
|
||||
Access Control.
|
||||
Token authentication will be automatically enabled for the selected machine
|
||||
identity if it isn't already configured. By default, it will be configured
|
||||
to allow all IP addresses with a token TTL of 30 days. You can manage these
|
||||
settings in Access Control.
|
||||
<br />
|
||||
<br />A token will automatically be generated to be used with the CLI command.
|
||||
</>
|
||||
|
||||
@@ -81,7 +81,7 @@ export const ProjectsPage = () => {
|
||||
</Helmet>
|
||||
<PageHeader
|
||||
scope={isSubOrganization ? "namespace" : "org"}
|
||||
title="Overview"
|
||||
title={`${isSubOrganization ? "Sub-Organization" : "Organization"} Overview`}
|
||||
description="Your team's complete security toolkit - organized and ready when you need them."
|
||||
/>
|
||||
{projectListView === ProjectListView.MyProjects ? (
|
||||
|
||||
@@ -20,7 +20,7 @@ export const SettingsPage = () => {
|
||||
<PageHeader
|
||||
scope={isSubOrganization ? "namespace" : "org"}
|
||||
description="Configure organization-wide settings"
|
||||
title={t("settings.org.title")}
|
||||
title={isSubOrganization ? "Sub-Organization Settings" : "Organization Settings"}
|
||||
/>
|
||||
<OrgTabGroup />
|
||||
</div>
|
||||
|
||||
@@ -112,7 +112,7 @@ const Page = withPermission(
|
||||
className="mb-4 flex items-center gap-x-2 text-sm text-mineshaft-400"
|
||||
>
|
||||
<FontAwesomeIcon icon={faChevronLeft} />
|
||||
Users
|
||||
Organization Users
|
||||
</Link>
|
||||
<PageHeader
|
||||
scope={isSubOrganization ? "namespace" : "org"}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user