mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 09:26:37 +00:00
fix: allow rotation account credentials to be removed from resources
This commit is contained in:
@@ -3,13 +3,13 @@ import { z } from "zod";
|
|||||||
import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
import { THsmServiceFactory } from "@app/ee/services/hsm/hsm-service";
|
||||||
import { crypto } from "@app/lib/crypto/cryptography";
|
import { crypto } from "@app/lib/crypto/cryptography";
|
||||||
import { QueueWorkerProfile } from "@app/lib/types";
|
import { QueueWorkerProfile } from "@app/lib/types";
|
||||||
|
import { TKmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
||||||
import { TSuperAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
import { TSuperAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
|
||||||
|
|
||||||
import { BadRequestError } from "../errors";
|
import { BadRequestError } from "../errors";
|
||||||
import { removeTrailingSlash } from "../fn";
|
import { removeTrailingSlash } from "../fn";
|
||||||
import { CustomLogger } from "../logger/logger";
|
import { CustomLogger } from "../logger/logger";
|
||||||
import { zpStr } from "../zod";
|
import { zpStr } from "../zod";
|
||||||
import { TKmsRootConfigDALFactory } from "@app/services/kms/kms-root-config-dal";
|
|
||||||
|
|
||||||
export const GITLAB_URL = "https://gitlab.com";
|
export const GITLAB_URL = "https://gitlab.com";
|
||||||
|
|
||||||
|
|||||||
+28
@@ -12,3 +12,31 @@ export const BaseSqlAccountSchema = z.object({
|
|||||||
.min(1, "Password required")
|
.min(1, "Password required")
|
||||||
.max(256, "Password must be 256 characters or less")
|
.max(256, "Password must be 256 characters or less")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const BaseSqlRotationAccountSchema = z
|
||||||
|
.object({
|
||||||
|
username: z.string().trim().max(63, "Username must be 63 characters or less"),
|
||||||
|
password: z.string().trim().max(256, "Password must be 256 characters or less")
|
||||||
|
})
|
||||||
|
.superRefine((data, ctx) => {
|
||||||
|
if (data.username && !data.password) {
|
||||||
|
ctx.addIssue({
|
||||||
|
path: ["password"],
|
||||||
|
message: "Password is required",
|
||||||
|
code: z.ZodIssueCode.custom
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (data.password && !data.username) {
|
||||||
|
ctx.addIssue({
|
||||||
|
path: ["username"],
|
||||||
|
message: "Username is required",
|
||||||
|
code: z.ZodIssueCode.custom
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.transform((val) => {
|
||||||
|
if (!val.username && !val.password) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
});
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ import { z } from "zod";
|
|||||||
import { Button, ModalClose } from "@app/components/v2";
|
import { Button, ModalClose } from "@app/components/v2";
|
||||||
import { PamResourceType, TPostgresResource } from "@app/hooks/api/pam";
|
import { PamResourceType, TPostgresResource } from "@app/hooks/api/pam";
|
||||||
import { UNCHANGED_PASSWORD_SENTINEL } from "@app/hooks/api/pam/constants";
|
import { UNCHANGED_PASSWORD_SENTINEL } from "@app/hooks/api/pam/constants";
|
||||||
import { BaseSqlAccountSchema } from "@app/pages/pam/PamAccountsPage/components/PamAccountForm/shared/sql-account-schemas";
|
import { BaseSqlRotationAccountSchema } from "@app/pages/pam/PamAccountsPage/components/PamAccountForm/shared/sql-account-schemas";
|
||||||
|
|
||||||
import { BaseSqlResourceSchema } from "./shared/sql-resource-schemas";
|
import { BaseSqlResourceSchema } from "./shared/sql-resource-schemas";
|
||||||
import { SqlResourceFields } from "./shared/SqlResourceFields";
|
import { SqlResourceFields } from "./shared/SqlResourceFields";
|
||||||
@@ -21,7 +21,7 @@ type Props = {
|
|||||||
const formSchema = genericResourceFieldsSchema.extend({
|
const formSchema = genericResourceFieldsSchema.extend({
|
||||||
resourceType: z.literal(PamResourceType.Postgres),
|
resourceType: z.literal(PamResourceType.Postgres),
|
||||||
connectionDetails: BaseSqlResourceSchema,
|
connectionDetails: BaseSqlResourceSchema,
|
||||||
rotationAccountCredentials: BaseSqlAccountSchema.nullable().optional()
|
rotationAccountCredentials: BaseSqlRotationAccountSchema.nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
type FormData = z.infer<typeof formSchema>;
|
type FormData = z.infer<typeof formSchema>;
|
||||||
|
|||||||
+42
-18
@@ -1,5 +1,7 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
||||||
|
import { faTimes } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
@@ -44,7 +46,18 @@ export const SqlRotateAccountFields = ({ isUpdate }: { isUpdate: boolean }) => {
|
|||||||
isError={Boolean(error?.message)}
|
isError={Boolean(error?.message)}
|
||||||
label="Username"
|
label="Username"
|
||||||
>
|
>
|
||||||
<Input {...field} autoComplete="off" />
|
<div className="relative">
|
||||||
|
<Input {...field} autoComplete="off" />
|
||||||
|
{field.value && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="absolute inset-y-0 right-0 flex cursor-pointer items-center pr-3"
|
||||||
|
onClick={() => field.onChange("")}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faTimes} className="text-gray-500" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@@ -58,23 +71,34 @@ export const SqlRotateAccountFields = ({ isUpdate }: { isUpdate: boolean }) => {
|
|||||||
isError={Boolean(error?.message)}
|
isError={Boolean(error?.message)}
|
||||||
label="Password"
|
label="Password"
|
||||||
>
|
>
|
||||||
<Input
|
<div className="relative">
|
||||||
{...field}
|
<Input
|
||||||
type={showPassword ? "text" : "password"}
|
{...field}
|
||||||
autoComplete="new-password"
|
type={showPassword ? "text" : "password"}
|
||||||
onFocus={() => {
|
autoComplete="new-password"
|
||||||
if (isUpdate && field.value === UNCHANGED_PASSWORD_SENTINEL) {
|
onFocus={() => {
|
||||||
field.onChange("");
|
if (isUpdate && field.value === UNCHANGED_PASSWORD_SENTINEL) {
|
||||||
}
|
field.onChange("");
|
||||||
setShowPassword(true);
|
}
|
||||||
}}
|
setShowPassword(true);
|
||||||
onBlur={() => {
|
}}
|
||||||
if (isUpdate && field.value === "") {
|
onBlur={() => {
|
||||||
field.onChange(UNCHANGED_PASSWORD_SENTINEL);
|
if (isUpdate && field.value === "") {
|
||||||
}
|
field.onChange(UNCHANGED_PASSWORD_SENTINEL);
|
||||||
setShowPassword(false);
|
}
|
||||||
}}
|
setShowPassword(false);
|
||||||
/>
|
}}
|
||||||
|
/>
|
||||||
|
{field.value && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="absolute inset-y-0 right-0 flex cursor-pointer items-center pr-3"
|
||||||
|
onClick={() => field.onChange("")}
|
||||||
|
>
|
||||||
|
<FontAwesomeIcon icon={faTimes} className="text-gray-500" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user