mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-09 16:28:19 +00:00
Merge remote-tracking branch 'origin/main' into misc/revamp-pki-apis
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 |
@@ -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 = (
|
||||
|
||||
@@ -57,6 +57,7 @@ import { OCIConnectionMethod } from "@app/hooks/api/appConnections/types/oci-con
|
||||
import { RailwayConnectionMethod } from "@app/hooks/api/appConnections/types/railway-connection";
|
||||
import { RenderConnectionMethod } from "@app/hooks/api/appConnections/types/render-connection";
|
||||
import { SupabaseConnectionMethod } from "@app/hooks/api/appConnections/types/supabase-connection";
|
||||
import { DNSMadeEasyConnectionMethod } from "@app/hooks/api/appConnections/types/dns-made-easy-connection";
|
||||
|
||||
export const APP_CONNECTION_MAP: Record<
|
||||
AppConnection,
|
||||
@@ -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}`);
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
@@ -56,6 +57,7 @@ export * from "./camunda-connection";
|
||||
export * from "./checkly-connection";
|
||||
export * from "./chef-connection";
|
||||
export * from "./cloudflare-connection";
|
||||
export * from "./dns-made-easy-connection";
|
||||
export * from "./databricks-connection";
|
||||
export * from "./flyio-connection";
|
||||
export * from "./gcp-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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
+50
-2
@@ -27,6 +27,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,
|
||||
@@ -210,6 +214,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
|
||||
@@ -219,16 +228,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
|
||||
@@ -240,6 +257,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) {
|
||||
@@ -499,6 +521,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=""
|
||||
|
||||
+1
-1
@@ -577,7 +577,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>
|
||||
)}
|
||||
|
||||
@@ -58,7 +58,7 @@ export const AccessManagementPage = () => {
|
||||
},
|
||||
{
|
||||
key: OrgAccessControlTabSections.Identities,
|
||||
label: "Identities",
|
||||
label: "Machine Identities",
|
||||
isHidden: permission.cannot(
|
||||
OrgPermissionIdentityActions.Read,
|
||||
OrgPermissionSubjects.Identity
|
||||
@@ -84,7 +84,7 @@ export const AccessManagementPage = () => {
|
||||
<PageHeader
|
||||
scope={isSubOrganization ? "namespace" : "org"}
|
||||
title="Access Control"
|
||||
description="Manage fine-grained access for users, groups, roles, and identities within your organization resources."
|
||||
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
-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"
|
||||
}
|
||||
|
||||
+18
-14
@@ -73,7 +73,7 @@ export const IdentitySection = withPermission(
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully deleted identity",
|
||||
text: "Successfully deleted machine identity",
|
||||
type: "success"
|
||||
});
|
||||
|
||||
@@ -99,7 +99,7 @@ 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">Machine Identities</p>
|
||||
<DocumentationLinkBadge href="https://infisical.com/docs/documentation/platform/identities/machine-identities" />
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
@@ -116,7 +116,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 +129,7 @@ export const IdentitySection = withPermission(
|
||||
}}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Create Identity
|
||||
Add Machine Identity
|
||||
</Button>
|
||||
)}
|
||||
</OrgPermissionCan>
|
||||
@@ -141,7 +141,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 +152,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 +199,11 @@ export const IdentitySection = withPermission(
|
||||
>
|
||||
<ModalContent
|
||||
bodyClassName="overflow-visible"
|
||||
title="Add Identity"
|
||||
title="Add 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 +228,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 +248,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>
|
||||
|
||||
+8
-8
@@ -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 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>
|
||||
@@ -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}
|
||||
|
||||
+1
-1
@@ -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"
|
||||
});
|
||||
|
||||
|
||||
+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
@@ -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 { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Controller, FormProvider, useForm } from "react-hook-form";
|
||||
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>
|
||||
);
|
||||
};
|
||||
@@ -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
|
||||
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.
|
||||
</>
|
||||
|
||||
@@ -44,7 +44,7 @@ const Page = () => {
|
||||
<PageHeader
|
||||
scope={currentProject.type}
|
||||
title="Access Control"
|
||||
description="Manage fine-grained access for users, groups, roles, and identities within your project resources."
|
||||
description="Manage fine-grained access for users, groups, roles, and machine identities within your project resources."
|
||||
/>
|
||||
<Tabs orientation="vertical" value={selectedTab} onValueChange={updateSelectedTab}>
|
||||
<TabList>
|
||||
@@ -55,7 +55,7 @@ const Page = () => {
|
||||
Groups
|
||||
</Tab>
|
||||
<Tab variant="project" value={ProjectAccessControlTabs.Identities}>
|
||||
Identities
|
||||
Machine Identities
|
||||
</Tab>
|
||||
{isSecretManager && (
|
||||
<Tab variant="project" value={ProjectAccessControlTabs.ServiceTokens}>
|
||||
|
||||
+19
-17
@@ -158,7 +158,7 @@ export const IdentityTab = withProjectPermission(
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully deleted project identity",
|
||||
text: "Successfully deleted project machine identity",
|
||||
type: "success"
|
||||
});
|
||||
} else {
|
||||
@@ -168,7 +168,7 @@ export const IdentityTab = withProjectPermission(
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully removed identity from project",
|
||||
text: "Successfully removed machine identity from project",
|
||||
type: "success"
|
||||
});
|
||||
}
|
||||
@@ -197,7 +197,7 @@ export const IdentityTab = withProjectPermission(
|
||||
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<div className="flex 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">Machine Identities</p>
|
||||
<DocumentationLinkBadge href="https://infisical.com/docs/documentation/platform/identities/machine-identities" />
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
@@ -212,7 +212,7 @@ export const IdentityTab = withProjectPermission(
|
||||
onClick={() => handlePopUpOpen("createIdentity")}
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
Create Identity
|
||||
Add Machine Identity
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
@@ -223,7 +223,7 @@ export const IdentityTab = withProjectPermission(
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||
placeholder="Search identities by name..."
|
||||
placeholder="Search machine identities by name..."
|
||||
/>
|
||||
<TableContainer>
|
||||
<Table>
|
||||
@@ -454,7 +454,9 @@ export const IdentityTab = withProjectPermission(
|
||||
});
|
||||
}}
|
||||
>
|
||||
{identityProjectId ? "Delete Identity" : "Remove From Project"}
|
||||
{identityProjectId
|
||||
? "Delete Machine Identity"
|
||||
: "Remove From Project"}
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
@@ -474,7 +476,7 @@ export const IdentityTab = withProjectPermission(
|
||||
<Td colSpan={3}>
|
||||
<Blur
|
||||
className="w-min"
|
||||
tooltipText="You do not have permission to read this identity."
|
||||
tooltipText="You do not have permission to view this machine identity."
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
@@ -497,8 +499,8 @@ export const IdentityTab = withProjectPermission(
|
||||
<EmptyState
|
||||
title={
|
||||
debouncedSearch.trim().length > 0
|
||||
? "No identities match search filter"
|
||||
: "No identities have been added to this project"
|
||||
? "No machine identities match search filter"
|
||||
: "No machine identities have been added to this project"
|
||||
}
|
||||
icon={faServer}
|
||||
/>
|
||||
@@ -513,8 +515,8 @@ export const IdentityTab = withProjectPermission(
|
||||
>
|
||||
<ModalContent
|
||||
bodyClassName="overflow-visible"
|
||||
title="Add Project Identity"
|
||||
subTitle="Create a new identity or assign an existing identity"
|
||||
title="Add Project Machine Identity"
|
||||
subTitle="Create a new machine identity or assign an existing one"
|
||||
>
|
||||
<AnimatePresence mode="wait">
|
||||
{wizardStep === WizardSteps.SelectAction && (
|
||||
@@ -538,11 +540,11 @@ export const IdentityTab = withProjectPermission(
|
||||
>
|
||||
<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 project. This identity
|
||||
will be managed at the project-level.
|
||||
Create a new machine identity specifically for this project. This machine
|
||||
identity will be managed at the project-level.
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -558,11 +560,11 @@ export const IdentityTab = withProjectPermission(
|
||||
>
|
||||
<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 organization. The identity will continue
|
||||
to be managed at its original scope.
|
||||
Assign an existing machine identity from your organization. The machine
|
||||
identity will continue to be managed at its original scope.
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
+2
-2
@@ -138,7 +138,7 @@ export const ProjectIdentityModal = ({ onClose, identity }: ContentProps) => {
|
||||
}
|
||||
|
||||
createNotification({
|
||||
text: `Successfully ${isUpdate ? "updated" : "created"} project identity`,
|
||||
text: `Successfully ${isUpdate ? "updated" : "created"} project machine identity`,
|
||||
type: "success"
|
||||
});
|
||||
|
||||
@@ -148,7 +148,7 @@ export const ProjectIdentityModal = ({ onClose, identity }: ContentProps) => {
|
||||
const error = err as any;
|
||||
const text =
|
||||
error?.response?.data?.message ??
|
||||
`Failed to ${isUpdate ? "update" : "create"} project identity`;
|
||||
`Failed to ${isUpdate ? "update" : "create"} project machine identity`;
|
||||
|
||||
createNotification({
|
||||
text,
|
||||
|
||||
+3
-3
@@ -83,7 +83,7 @@ export const ProjectLinkIdentityModal = ({ handlePopUpToggle }: Props) => {
|
||||
});
|
||||
|
||||
createNotification({
|
||||
text: "Successfully added identity to project",
|
||||
text: "Successfully added machine identity to project",
|
||||
type: "success"
|
||||
});
|
||||
|
||||
@@ -114,11 +114,11 @@ export const ProjectLinkIdentityModal = ({ handlePopUpToggle }: 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={filteredIdentityMembershipOrgs.map((membership) => ({
|
||||
name: membership.name,
|
||||
|
||||
@@ -92,7 +92,7 @@ const Page = () => {
|
||||
onSuccess: () => {
|
||||
createNotification({
|
||||
type: "success",
|
||||
text: "Identity privilege assumption has started"
|
||||
text: "Machine identity privilege assumption has started"
|
||||
});
|
||||
const url = `${getProjectHomePage(currentProject.type, currentProject.environments)}${isSubOrganization && isNonScopedIdentity ? `?subOrganization=${currentOrg.slug}` : ""}`;
|
||||
window.location.assign(
|
||||
@@ -109,7 +109,7 @@ const Page = () => {
|
||||
projectId
|
||||
});
|
||||
createNotification({
|
||||
text: "Successfully removed identity from project",
|
||||
text: "Successfully removed machine identity from project",
|
||||
type: "success"
|
||||
});
|
||||
handlePopUpClose("deleteIdentity");
|
||||
@@ -149,12 +149,12 @@ const Page = () => {
|
||||
className="mb-4 flex items-center gap-x-2 text-sm text-mineshaft-400"
|
||||
>
|
||||
<FontAwesomeIcon icon={faChevronLeft} />
|
||||
Identities
|
||||
Machine Identities
|
||||
</Link>
|
||||
<PageHeader
|
||||
scope={currentProject.type}
|
||||
title={identityMembershipDetails?.identity?.name}
|
||||
description={`Identity ${isProjectIdentity ? "created" : "added"} on ${identityMembershipDetails?.createdAt && formatRelative(new Date(identityMembershipDetails?.createdAt || ""), new Date())}`}
|
||||
description={`Machine identity ${isProjectIdentity ? "created" : "added"} on ${identityMembershipDetails?.createdAt && formatRelative(new Date(identityMembershipDetails?.createdAt || ""), new Date())}`}
|
||||
className={!isProjectIdentity ? "mb-4" : undefined}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
@@ -177,7 +177,7 @@ const Page = () => {
|
||||
identityId: identityMembershipDetails?.identity.id
|
||||
})}
|
||||
renderTooltip
|
||||
allowedLabel="Assume privileges of the user"
|
||||
allowedLabel="Assume privileges of the machine identity"
|
||||
passThrough={false}
|
||||
>
|
||||
{(isAllowed) => (
|
||||
@@ -209,7 +209,7 @@ const Page = () => {
|
||||
isLoading={isDeletingIdentity}
|
||||
onClick={() => handlePopUpOpen("deleteIdentity")}
|
||||
>
|
||||
Remove Identity
|
||||
Remove Machine Identity
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
@@ -219,7 +219,7 @@ const Page = () => {
|
||||
{!isProjectIdentity && (
|
||||
<Alert hideTitle iconClassName="text-info" className="mb-4 border-info/50 bg-info/10">
|
||||
<AlertDescription>
|
||||
This identity is managed by your organization.{" "}
|
||||
This machine identity is managed by your organization.{" "}
|
||||
<OrgPermissionCan
|
||||
I={OrgPermissionIdentityActions.Read}
|
||||
an={OrgPermissionSubjects.Identity}
|
||||
@@ -234,7 +234,7 @@ const Page = () => {
|
||||
}}
|
||||
>
|
||||
<span className="cursor-pointer text-info underline underline-offset-2">
|
||||
Click here to manage identity.
|
||||
Click here to manage machine identity.
|
||||
</span>
|
||||
</Link>
|
||||
) : null
|
||||
@@ -286,15 +286,15 @@ const Page = () => {
|
||||
<ConfirmActionModal
|
||||
isOpen={popUp.assumePrivileges.isOpen}
|
||||
confirmKey="assume"
|
||||
title="Do you want to assume privileges of this identity?"
|
||||
subTitle="This will set your privileges to those of the identity for the next hour."
|
||||
title="Do you want to assume privileges of this machine identity?"
|
||||
subTitle="This will set your privileges to those of the machine identity for the next hour."
|
||||
onChange={(isOpen) => handlePopUpToggle("assumePrivileges", isOpen)}
|
||||
onConfirmed={handleAssumePrivileges}
|
||||
buttonText="Confirm"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<EmptyState title="Error: Unable to find the identity." className="py-12" />
|
||||
<EmptyState title="Error: Unable to find the machine identity." className="py-12" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
+4
-1
@@ -235,7 +235,10 @@ export const IdentityProjectAdditionalPrivilegeSection = ({ identityMembershipDe
|
||||
</TBody>
|
||||
</Table>
|
||||
{!isPending && !identityProjectPrivileges?.length && (
|
||||
<EmptyState title="This identity has no additional privileges" icon={faFolder} />
|
||||
<EmptyState
|
||||
title="This machine identity has no additional privileges"
|
||||
icon={faFolder}
|
||||
/>
|
||||
)}
|
||||
</TableContainer>
|
||||
</div>
|
||||
|
||||
+5
-5
@@ -69,7 +69,7 @@ export const ProjectIdentityDetailsSection = ({ identity, isOrgIdentity, members
|
||||
} catch {
|
||||
createNotification({
|
||||
type: "error",
|
||||
text: "Failed to delete project identity"
|
||||
text: "Failed to delete project machine identity"
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -77,7 +77,7 @@ export const ProjectIdentityDetailsSection = ({ identity, isOrgIdentity, members
|
||||
return (
|
||||
<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>
|
||||
{!isOrgIdentity && (
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -114,7 +114,7 @@ export const ProjectIdentityDetailsSection = ({ identity, isOrgIdentity, members
|
||||
}}
|
||||
disabled={!isAllowed}
|
||||
>
|
||||
Edit Identity
|
||||
Edit Machine Identity
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
@@ -137,7 +137,7 @@ export const ProjectIdentityDetailsSection = ({ identity, isOrgIdentity, members
|
||||
icon={<FontAwesomeIcon icon={faTrash} />}
|
||||
disabled={!isAllowed}
|
||||
>
|
||||
Delete Identity
|
||||
Delete Machine Identity
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
@@ -146,7 +146,7 @@ export const ProjectIdentityDetailsSection = ({ identity, isOrgIdentity, members
|
||||
</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 break-all text-mineshaft-300">{identity.id}</p>
|
||||
<div className="opacity-0 transition-opacity duration-300 group-hover:opacity-100">
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
faArrowRight,
|
||||
faArrowRightToBracket,
|
||||
faArrowUp,
|
||||
faCheck,
|
||||
faCopy,
|
||||
faFilter,
|
||||
faFingerprint,
|
||||
faFolder,
|
||||
@@ -79,6 +81,7 @@ import {
|
||||
usePopUp,
|
||||
useResetPageHelper,
|
||||
useResizableHeaderHeight,
|
||||
useTimedReset,
|
||||
useToggle
|
||||
} from "@app/hooks";
|
||||
import {
|
||||
@@ -194,6 +197,15 @@ export const OverviewPage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const [copiedSlug, , setCopiedSlug] = useTimedReset<string>({
|
||||
initialState: ""
|
||||
});
|
||||
|
||||
const copyToClipboard = (value: string, slug: string) => {
|
||||
navigator.clipboard.writeText(value);
|
||||
setCopiedSlug(slug);
|
||||
};
|
||||
|
||||
const [filter, setFilter] = useState<Filter>(DEFAULT_FILTER_STATE);
|
||||
const [filterHistory, setFilterHistory] = useState<
|
||||
Map<string, { filter: Filter; searchFilter: string }>
|
||||
@@ -1324,19 +1336,33 @@ export const OverviewPage = () => {
|
||||
>
|
||||
<Tooltip
|
||||
content={
|
||||
collapseEnvironments ? (
|
||||
<p className="whitespace-break-spaces">{name}</p>
|
||||
) : (
|
||||
""
|
||||
)
|
||||
<div className="flex flex-col gap-2">
|
||||
{collapseEnvironments ? (
|
||||
<p className="whitespace-break-spaces text-mineshaft-300">{name}</p>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
<div className="flex items-center gap-2">
|
||||
<p className="text-xs text-mineshaft-300">{slug}</p>
|
||||
<IconButton
|
||||
variant="plain"
|
||||
colorSchema="secondary"
|
||||
ariaLabel="Copy environment slug"
|
||||
onClick={() => copyToClipboard(slug, slug)}
|
||||
>
|
||||
<FontAwesomeIcon icon={copiedSlug === slug ? faCheck : faCopy} />
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
side="bottom"
|
||||
sideOffset={-1}
|
||||
align="end"
|
||||
sideOffset={5}
|
||||
align="center"
|
||||
className="max-w-xl text-xs normal-case"
|
||||
rootProps={{
|
||||
disableHoverableContent: true
|
||||
disableHoverableContent: false
|
||||
}}
|
||||
key={`tooltip-${name}-${index + 1}`}
|
||||
>
|
||||
<div
|
||||
className={twMerge(
|
||||
|
||||
+23
-3
@@ -1,5 +1,6 @@
|
||||
import { Controller, useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import slugify from "@sindresorhus/slugify";
|
||||
import { z } from "zod";
|
||||
|
||||
import { createNotification } from "@app/components/notifications";
|
||||
@@ -31,7 +32,13 @@ type ContentProps = {
|
||||
const Content = ({ onComplete }: ContentProps) => {
|
||||
const { currentProject } = useProject();
|
||||
const { mutateAsync, isPending } = useCreateWsEnvironment();
|
||||
const { control, handleSubmit } = useForm<FormData>({
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
setValue,
|
||||
getValues,
|
||||
formState: { dirtyFields }
|
||||
} = useForm<FormData>({
|
||||
resolver: zodResolver(schema)
|
||||
});
|
||||
|
||||
@@ -52,15 +59,28 @@ const Content = ({ onComplete }: ContentProps) => {
|
||||
onComplete(env);
|
||||
};
|
||||
|
||||
const handleEnvironmentNameChange = () => {
|
||||
if (dirtyFields.environmentSlug) return;
|
||||
|
||||
const value = getValues("environmentName");
|
||||
setValue("environmentSlug", slugify(value, { lowercase: true }));
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onFormSubmit)}>
|
||||
<Controller
|
||||
control={control}
|
||||
defaultValue=""
|
||||
name="environmentName"
|
||||
render={({ field, fieldState: { error } }) => (
|
||||
render={({ field: { onChange, ...field }, fieldState: { error } }) => (
|
||||
<FormControl label="Environment Name" isError={Boolean(error)} errorText={error?.message}>
|
||||
<Input {...field} />
|
||||
<Input
|
||||
{...field}
|
||||
onChange={(e) => {
|
||||
onChange(e);
|
||||
handleEnvironmentNameChange();
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user