Merge branch 'main' of https://github.com/Infisical/infisical into feat/adds-group-access-token-support-in-gitlab

This commit is contained in:
Piyush Gupta
2025-10-28 17:51:55 +05:30
66 changed files with 525 additions and 313 deletions
@@ -24,6 +24,8 @@ jobs:
- name: Set up chart-testing - name: Set up chart-testing
uses: helm/[email protected] uses: helm/[email protected]
with:
yamale_version: "6.0.0"
- name: Run chart-testing (lint) - name: Run chart-testing (lint)
run: ct lint --config ct.yaml --charts helm-charts/infisical-gateway run: ct lint --config ct.yaml --charts helm-charts/infisical-gateway
@@ -27,6 +27,8 @@ jobs:
- name: Set up chart-testing - name: Set up chart-testing
uses: helm/[email protected] uses: helm/[email protected]
with:
yamale_version: "6.0.0"
- name: Run chart-testing (lint) - name: Run chart-testing (lint)
run: ct lint --config ct.yaml --charts helm-charts/infisical-gateway run: ct lint --config ct.yaml --charts helm-charts/infisical-gateway
@@ -0,0 +1,27 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
const hasOrgBlockDuplicateColumn = await knex.schema.hasColumn(
TableName.Organization,
"blockDuplicateSecretSyncDestinations"
);
if (!hasOrgBlockDuplicateColumn) {
await knex.schema.table(TableName.Organization, (table) => {
table.boolean("blockDuplicateSecretSyncDestinations").notNullable().defaultTo(false);
});
}
}
export async function down(knex: Knex): Promise<void> {
const hasOrgBlockDuplicateColumn = await knex.schema.hasColumn(
TableName.Organization,
"blockDuplicateSecretSyncDestinations"
);
if (hasOrgBlockDuplicateColumn) {
await knex.schema.table(TableName.Organization, (table) => {
table.dropColumn("blockDuplicateSecretSyncDestinations");
});
}
}
+2 -1
View File
@@ -40,7 +40,8 @@ export const OrganizationsSchema = z.object({
googleSsoAuthEnforced: z.boolean().default(false), googleSsoAuthEnforced: z.boolean().default(false),
googleSsoAuthLastUsed: z.date().nullable().optional(), googleSsoAuthLastUsed: z.date().nullable().optional(),
parentOrgId: z.string().uuid().nullable().optional(), parentOrgId: z.string().uuid().nullable().optional(),
rootOrgId: z.string().uuid().nullable().optional() rootOrgId: z.string().uuid().nullable().optional(),
blockDuplicateSecretSyncDestinations: z.boolean().default(false)
}); });
export type TOrganizations = z.infer<typeof OrganizationsSchema>; export type TOrganizations = z.infer<typeof OrganizationsSchema>;
@@ -2,7 +2,6 @@ import { z } from "zod";
import { DynamicSecretLeasesSchema } from "@app/db/schemas"; import { DynamicSecretLeasesSchema } from "@app/db/schemas";
import { ApiDocsTags, DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs"; import { ApiDocsTags, DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs";
import { daysToMillisecond } from "@app/lib/dates";
import { removeTrailingSlash } from "@app/lib/fn"; import { removeTrailingSlash } from "@app/lib/fn";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { readLimit, writeLimit } from "@app/server/config/rateLimiter"; import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
@@ -32,8 +31,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > daysToMillisecond(1)) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRET_LEASES.CREATE.path), path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRET_LEASES.CREATE.path),
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.environmentSlug), environmentSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.environmentSlug),
@@ -127,8 +126,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > daysToMillisecond(1)) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.projectSlug), projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.projectSlug),
path: z path: z
@@ -2,7 +2,6 @@ import { z } from "zod";
import { DynamicSecretLeasesSchema } from "@app/db/schemas"; import { DynamicSecretLeasesSchema } from "@app/db/schemas";
import { ApiDocsTags, DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs"; import { ApiDocsTags, DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs";
import { daysToMillisecond } from "@app/lib/dates";
import { removeTrailingSlash } from "@app/lib/fn"; import { removeTrailingSlash } from "@app/lib/fn";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { writeLimit } from "@app/server/config/rateLimiter"; import { writeLimit } from "@app/server/config/rateLimiter";
@@ -32,8 +31,8 @@ export const registerKubernetesDynamicSecretLeaseRouter = async (server: Fastify
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be greater than 1min" });
if (valMs > daysToMillisecond(1)) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRET_LEASES.CREATE.path), path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRET_LEASES.CREATE.path),
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.environmentSlug), environmentSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.environmentSlug),
@@ -3,7 +3,6 @@ import { z } from "zod";
import { DynamicSecretLeasesSchema } from "@app/db/schemas"; import { DynamicSecretLeasesSchema } from "@app/db/schemas";
import { DynamicSecretProviderSchema } from "@app/ee/services/dynamic-secret/providers/models"; import { DynamicSecretProviderSchema } from "@app/ee/services/dynamic-secret/providers/models";
import { ApiDocsTags, DYNAMIC_SECRETS } from "@app/lib/api-docs"; import { ApiDocsTags, DYNAMIC_SECRETS } from "@app/lib/api-docs";
import { daysToMillisecond } from "@app/lib/dates";
import { removeTrailingSlash } from "@app/lib/fn"; import { removeTrailingSlash } from "@app/lib/fn";
import { ms } from "@app/lib/ms"; import { ms } from "@app/lib/ms";
import { isValidHandleBarTemplate } from "@app/lib/template/validate-handlebars"; import { isValidHandleBarTemplate } from "@app/lib/template/validate-handlebars";
@@ -60,8 +59,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > daysToMillisecond(1)) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -72,8 +71,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > daysToMillisecond(1)) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}) })
.nullable(), .nullable(),
path: z.string().describe(DYNAMIC_SECRETS.CREATE.path).trim().default("/").transform(removeTrailingSlash), path: z.string().describe(DYNAMIC_SECRETS.CREATE.path).trim().default("/").transform(removeTrailingSlash),
@@ -130,8 +129,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > daysToMillisecond(1)) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -142,8 +141,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > daysToMillisecond(1)) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}) })
.nullable(), .nullable(),
newName: z.string().describe(DYNAMIC_SECRETS.UPDATE.newName).optional(), newName: z.string().describe(DYNAMIC_SECRETS.UPDATE.newName).optional(),
+5 -1
View File
@@ -7,6 +7,7 @@ import https from "https";
import { verifyHostInputValidity } from "@app/ee/services/dynamic-secret/dynamic-secret-fns"; import { verifyHostInputValidity } from "@app/ee/services/dynamic-secret/dynamic-secret-fns";
import { splitPemChain } from "@app/services/certificate/certificate-fns"; import { splitPemChain } from "@app/services/certificate/certificate-fns";
import { getConfig } from "../config/env";
import { BadRequestError } from "../errors"; import { BadRequestError } from "../errors";
import { GatewayProxyProtocol } from "../gateway/types"; import { GatewayProxyProtocol } from "../gateway/types";
import { logger } from "../logger"; import { logger } from "../logger";
@@ -80,6 +81,8 @@ const createGatewayConnection = async (
gateway: { clientCertificate: string; clientPrivateKey: string; serverCertificateChain: string }, gateway: { clientCertificate: string; clientPrivateKey: string; serverCertificateChain: string },
protocol: GatewayProxyProtocol protocol: GatewayProxyProtocol
): Promise<net.Socket> => { ): Promise<net.Socket> => {
const appCfg = getConfig();
const protocolToAlpn = { const protocolToAlpn = {
[GatewayProxyProtocol.Http]: "infisical-http-proxy", [GatewayProxyProtocol.Http]: "infisical-http-proxy",
[GatewayProxyProtocol.Tcp]: "infisical-tcp-proxy", [GatewayProxyProtocol.Tcp]: "infisical-tcp-proxy",
@@ -94,7 +97,8 @@ const createGatewayConnection = async (
minVersion: "TLSv1.2", minVersion: "TLSv1.2",
maxVersion: "TLSv1.3", maxVersion: "TLSv1.3",
rejectUnauthorized: true, rejectUnauthorized: true,
ALPNProtocols: [protocolToAlpn[protocol]] ALPNProtocols: [protocolToAlpn[protocol]],
checkServerIdentity: appCfg.isDevelopmentMode ? () => undefined : tls.checkServerIdentity
}; };
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -138,6 +138,11 @@ export const injectIdentity = fp(
return; return;
} }
// Authentication is handled on a route-level
if (req.url === "/api/v1/relays/heartbeat-instance-relay") {
return;
}
// Authentication is handled on a route-level here. // Authentication is handled on a route-level here.
if (req.url.includes("/api/v1/workflow-integrations/microsoft-teams/message-endpoint")) { if (req.url.includes("/api/v1/workflow-integrations/microsoft-teams/message-endpoint")) {
return; return;
+2
View File
@@ -1958,6 +1958,8 @@ export const registerRoutes = async (
secretImportDAL, secretImportDAL,
permissionService, permissionService,
appConnectionService, appConnectionService,
projectDAL,
orgDAL,
folderDAL, folderDAL,
secretSyncQueue, secretSyncQueue,
projectBotService, projectBotService,
@@ -323,7 +323,11 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
.min(1, "Max Shared Secret view count cannot be lower than 1") .min(1, "Max Shared Secret view count cannot be lower than 1")
.max(1000, "Max Shared Secret view count cannot exceed 1000") .max(1000, "Max Shared Secret view count cannot exceed 1000")
.nullable() .nullable()
.optional(),
blockDuplicateSecretSyncDestinations: z
.boolean()
.optional() .optional()
.describe("Block duplicate secret sync destinations across the organization")
}), }),
response: { response: {
200: z.object({ 200: z.object({
@@ -719,7 +719,8 @@ export const identityKubernetesAuthServiceFactory = ({
); );
} }
const shouldUpdateGatewayId = Boolean(gatewayId); // Strict check to see if gateway ID is undefined. It should update the gateway ID to null if its strictly set to null.
const shouldUpdateGatewayId = Boolean(gatewayId !== undefined);
const gatewayIdValue = isGatewayV1 ? gatewayId : null; const gatewayIdValue = isGatewayV1 ? gatewayId : null;
const gatewayV2IdValue = isGatewayV1 ? null : gatewayId; const gatewayV2IdValue = isGatewayV1 ? null : gatewayId;
+2 -1
View File
@@ -27,5 +27,6 @@ export const sanitizedOrganizationSchema = OrganizationsSchema.pick({
scannerProductEnabled: true, scannerProductEnabled: true,
shareSecretsProductEnabled: true, shareSecretsProductEnabled: true,
maxSharedSecretLifetime: true, maxSharedSecretLifetime: true,
maxSharedSecretViewLimit: true maxSharedSecretViewLimit: true,
blockDuplicateSecretSyncDestinations: true
}); });
+4 -2
View File
@@ -405,7 +405,8 @@ export const orgServiceFactory = ({
scannerProductEnabled, scannerProductEnabled,
shareSecretsProductEnabled, shareSecretsProductEnabled,
maxSharedSecretLifetime, maxSharedSecretLifetime,
maxSharedSecretViewLimit maxSharedSecretViewLimit,
blockDuplicateSecretSyncDestinations
} }
}: TUpdateOrgDTO) => { }: TUpdateOrgDTO) => {
const appCfg = getConfig(); const appCfg = getConfig();
@@ -589,7 +590,8 @@ export const orgServiceFactory = ({
scannerProductEnabled, scannerProductEnabled,
shareSecretsProductEnabled, shareSecretsProductEnabled,
maxSharedSecretLifetime, maxSharedSecretLifetime,
maxSharedSecretViewLimit maxSharedSecretViewLimit,
blockDuplicateSecretSyncDestinations
}); });
if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` }); if (!org) throw new NotFoundError({ message: `Organization with ID '${orgId}' not found` });
return org; return org;
+1
View File
@@ -90,6 +90,7 @@ export type TUpdateOrgDTO = {
shareSecretsProductEnabled: boolean; shareSecretsProductEnabled: boolean;
maxSharedSecretLifetime: number; maxSharedSecretLifetime: number;
maxSharedSecretViewLimit: number | null; maxSharedSecretViewLimit: number | null;
blockDuplicateSecretSyncDestinations: boolean;
}>; }>;
} & TOrgPermission; } & TOrgPermission;
@@ -15,6 +15,8 @@ import { BadRequestError, DatabaseError, NotFoundError } from "@app/lib/errors";
import { deepEqualSkipFields } from "@app/lib/fn/object"; import { deepEqualSkipFields } from "@app/lib/fn/object";
import { OrgServiceActor } from "@app/lib/types"; import { OrgServiceActor } from "@app/lib/types";
import { TAppConnectionServiceFactory } from "@app/services/app-connection/app-connection-service"; import { TAppConnectionServiceFactory } from "@app/services/app-connection/app-connection-service";
import { TOrgDALFactory } from "@app/services/org/org-dal";
import { TProjectDALFactory } from "@app/services/project/project-dal";
import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service"; import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service";
import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal"; import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums"; import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
@@ -50,6 +52,8 @@ type TSecretSyncServiceFactoryDep = {
secretImportDAL: TSecretImportDALFactory; secretImportDAL: TSecretImportDALFactory;
appConnectionService: Pick<TAppConnectionServiceFactory, "validateAppConnectionUsageById">; appConnectionService: Pick<TAppConnectionServiceFactory, "validateAppConnectionUsageById">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getOrgPermission">; permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getOrgPermission">;
projectDAL: Pick<TProjectDALFactory, "findById">;
orgDAL: Pick<TOrgDALFactory, "findById">;
projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">; projectBotService: Pick<TProjectBotServiceFactory, "getBotKey">;
folderDAL: Pick<TSecretFolderDALFactory, "findByProjectId" | "findById" | "findBySecretPath">; folderDAL: Pick<TSecretFolderDALFactory, "findByProjectId" | "findById" | "findBySecretPath">;
keyStore: Pick<TKeyStoreFactory, "getItem">; keyStore: Pick<TKeyStoreFactory, "getItem">;
@@ -68,6 +72,8 @@ export const secretSyncServiceFactory = ({
secretImportDAL, secretImportDAL,
permissionService, permissionService,
appConnectionService, appConnectionService,
projectDAL,
orgDAL,
projectBotService, projectBotService,
secretSyncQueue, secretSyncQueue,
keyStore, keyStore,
@@ -225,6 +231,61 @@ export const secretSyncServiceFactory = ({
return secretSync as TSecretSync; return secretSync as TSecretSync;
}; };
const checkDuplicateDestination = async (
{ destination, destinationConfig, excludeSyncId, projectId }: TCheckDuplicateDestinationDTO,
actor: OrgServiceActor
) => {
const skipFields = SECRET_SYNC_SKIP_FIELDS_MAP[destination];
const { permission } = await permissionService.getProjectPermission({
actor: actor.type,
actorId: actor.id,
actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretSyncActions.Read,
ProjectPermissionSub.SecretSyncs
);
if (!destinationConfig || Object.keys(destinationConfig).length === 0) {
return { hasDuplicate: false, duplicateProjectId: undefined };
}
try {
const existingSyncs = await secretSyncDAL.findByDestinationAndOrgId(destination, actor.orgId);
const duplicates = existingSyncs.filter((sync) => {
if (sync.id === excludeSyncId) {
return false;
}
try {
const baseFieldsMatch = deepEqualSkipFields(sync.destinationConfig, destinationConfig, skipFields);
if (baseFieldsMatch) {
return DESTINATION_DUPLICATE_CHECK_MAP[destination](
sync.destinationConfig as Record<string, unknown>,
destinationConfig
);
}
return false;
} catch {
return false;
}
});
const hasDuplicate = duplicates.length > 0;
return {
hasDuplicate,
duplicateProjectId: hasDuplicate ? duplicates[0].projectId : undefined
};
} catch (error) {
return { hasDuplicate: false, duplicateProjectId: undefined };
}
};
const createSecretSync = async ( const createSecretSync = async (
{ projectId, secretPath, environment, ...params }: TCreateSecretSyncDTO, { projectId, secretPath, environment, ...params }: TCreateSecretSyncDTO,
actor: OrgServiceActor actor: OrgServiceActor
@@ -271,6 +332,30 @@ export const secretSyncServiceFactory = ({
message: `Could not find folder with path "${secretPath}" in environment "${environment}" for project with ID "${projectId}"` message: `Could not find folder with path "${secretPath}" in environment "${environment}" for project with ID "${projectId}"`
}); });
const project = await projectDAL.findById(projectId);
if (!project) {
throw new NotFoundError({ message: "Project not found" });
}
const organization = await orgDAL.findById(project.orgId);
if (organization?.blockDuplicateSecretSyncDestinations) {
const duplicateCheck = await checkDuplicateDestination(
{
destination: params.destination,
destinationConfig: params.destinationConfig,
projectId
},
actor
);
if (duplicateCheck.hasDuplicate) {
throw new BadRequestError({
message: `A secret sync with this destination already exists${
duplicateCheck.duplicateProjectId ? ` in project ${duplicateCheck.duplicateProjectId}` : ""
}.`
});
}
}
const destinationApp = SECRET_SYNC_CONNECTION_MAP[params.destination]; const destinationApp = SECRET_SYNC_CONNECTION_MAP[params.destination];
// validates permission to connect and app is valid for sync destination // validates permission to connect and app is valid for sync destination
@@ -369,6 +454,33 @@ export const secretSyncServiceFactory = ({
let { folderId } = secretSync; let { folderId } = secretSync;
if (params.destinationConfig) {
const project = await projectDAL.findById(secretSync.projectId);
if (!project) {
throw new NotFoundError({ message: "Project not found" });
}
const organization = await orgDAL.findById(project.orgId);
if (organization?.blockDuplicateSecretSyncDestinations) {
const duplicateCheck = await checkDuplicateDestination(
{
destination,
destinationConfig: params.destinationConfig,
projectId: secretSync.projectId,
excludeSyncId: secretSync.id
},
actor
);
if (duplicateCheck.hasDuplicate) {
throw new BadRequestError({
message: `A secret sync with this destination already exists${
duplicateCheck.duplicateProjectId ? ` in project ${duplicateCheck.duplicateProjectId}` : ""
}.`
});
}
}
}
if (params.connectionId) { if (params.connectionId) {
const destinationApp = SECRET_SYNC_CONNECTION_MAP[secretSync.destination as SecretSync]; const destinationApp = SECRET_SYNC_CONNECTION_MAP[secretSync.destination as SecretSync];
@@ -703,61 +815,6 @@ export const secretSyncServiceFactory = ({
return updatedSecretSync as TSecretSync; return updatedSecretSync as TSecretSync;
}; };
const checkDuplicateDestination = async (
{ destination, destinationConfig, excludeSyncId, projectId }: TCheckDuplicateDestinationDTO,
actor: OrgServiceActor
) => {
const skipFields = SECRET_SYNC_SKIP_FIELDS_MAP[destination];
const { permission } = await permissionService.getProjectPermission({
actor: actor.type,
actorId: actor.id,
actorAuthMethod: actor.authMethod,
actorOrgId: actor.orgId,
actionProjectType: ActionProjectType.SecretManager,
projectId
});
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretSyncActions.Read,
ProjectPermissionSub.SecretSyncs
);
if (!destinationConfig || Object.keys(destinationConfig).length === 0) {
return { hasDuplicate: false, duplicateProjectId: undefined };
}
try {
const existingSyncs = await secretSyncDAL.findByDestinationAndOrgId(destination, actor.orgId);
const duplicates = existingSyncs.filter((sync) => {
if (sync.id === excludeSyncId) {
return false;
}
try {
const baseFieldsMatch = deepEqualSkipFields(sync.destinationConfig, destinationConfig, skipFields);
if (baseFieldsMatch) {
return DESTINATION_DUPLICATE_CHECK_MAP[destination](
sync.destinationConfig as Record<string, unknown>,
destinationConfig
);
}
return false;
} catch {
return false;
}
});
const hasDuplicate = duplicates.length > 0;
return {
hasDuplicate,
duplicateProjectId: hasDuplicate ? duplicates[0].projectId : undefined
};
} catch (error) {
return { hasDuplicate: false, duplicateProjectId: undefined };
}
};
return { return {
listSecretSyncOptions, listSecretSyncOptions,
listSecretSyncsByProjectId, listSecretSyncsByProjectId,
+7 -1
View File
@@ -7,4 +7,10 @@ Infisical's Public (REST) API provides users an alternative way to programmatica
secrets via HTTPS requests. This can be useful for automating tasks, such as secrets via HTTPS requests. This can be useful for automating tasks, such as
rotating credentials, or for integrating secret management into a larger system. rotating credentials, or for integrating secret management into a larger system.
With the Public API, you can create, read, update, and delete secrets, as well as manage access control, query audit logs, and more. With the Public API, you can create, read, update, and delete secrets, as well as manage access control, query audit logs, and more.
## API Versioning
The API is versioned on a per-resource basis. A resource's version is only incremented for breaking changes, so different endpoints may have different version numbers (e.g., `/api/v4/secrets` vs. `/api/v1/secret-syncs`).
As a best practice, always use the latest available version for each endpoint to ensure access to the most recent features and improvements.
@@ -8,13 +8,14 @@ import { twMerge } from "tailwind-merge";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { Button, FormControl, Switch } from "@app/components/v2"; import { Button, FormControl, Switch } from "@app/components/v2";
import { useProject } from "@app/context"; import { useOrganization, useProject } from "@app/context";
import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs"; import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
import { import {
SecretSync, SecretSync,
SecretSyncInitialSyncBehavior, SecretSyncInitialSyncBehavior,
TSecretSync, TSecretSync,
useCreateSecretSync, useCreateSecretSync,
useDuplicateDestinationCheck,
useSecretSyncOption useSecretSyncOption
} from "@app/hooks/api/secretSyncs"; } from "@app/hooks/api/secretSyncs";
@@ -48,6 +49,7 @@ export const CreateSecretSyncForm = ({
}: Props) => { }: Props) => {
const createSecretSync = useCreateSecretSync(); const createSecretSync = useCreateSecretSync();
const { currentProject } = useProject(); const { currentProject } = useProject();
const { currentOrg } = useOrganization();
const { name: destinationName } = SECRET_SYNC_MAP[destination]; const { name: destinationName } = SECRET_SYNC_MAP[destination];
const [showConfirmation, setShowConfirmation] = useState(false); const [showConfirmation, setShowConfirmation] = useState(false);
@@ -106,11 +108,20 @@ export const CreateSecretSyncForm = ({
setSelectedTabIndex((prev) => prev - 1); setSelectedTabIndex((prev) => prev - 1);
}; };
const { handleSubmit, trigger, control } = formMethods; const { handleSubmit, trigger, control, watch } = formMethods;
const { hasDuplicate } = useDuplicateDestinationCheck({
destination,
projectId: currentProject?.id || "",
enabled: true,
destinationConfig: watch("destinationConfig")
});
const isStepValid = async (index: number) => trigger(FORM_TABS[index].fields); const isStepValid = async (index: number) => trigger(FORM_TABS[index].fields);
const isFinalStep = selectedTabIndex === FORM_TABS.length - 1; const isFinalStep = selectedTabIndex === FORM_TABS.length - 1;
const isCreateButtonDisabled =
isFinalStep && hasDuplicate && currentOrg?.blockDuplicateSecretSyncDestinations;
const handleNext = async () => { const handleNext = async () => {
if (isFinalStep) { if (isFinalStep) {
@@ -245,7 +256,7 @@ export const CreateSecretSyncForm = ({
</FormProvider> </FormProvider>
<div className="flex w-full flex-row-reverse justify-between gap-4 pt-4"> <div className="flex w-full flex-row-reverse justify-between gap-4 pt-4">
<Button onClick={handleNext} colorSchema="secondary"> <Button onClick={handleNext} colorSchema="secondary" isDisabled={isCreateButtonDisabled}>
{isFinalStep ? "Create Sync" : "Next"} {isFinalStep ? "Create Sync" : "Next"}
</Button> </Button>
{selectedTabIndex > 0 && ( {selectedTabIndex > 0 && (
@@ -6,6 +6,7 @@ type Props = {
onConfirm: () => void; onConfirm: () => void;
isLoading?: boolean; isLoading?: boolean;
duplicateProjectId?: string; duplicateProjectId?: string;
isDisabled?: boolean;
}; };
export const DuplicateDestinationConfirmationModal = ({ export const DuplicateDestinationConfirmationModal = ({
@@ -13,7 +14,8 @@ export const DuplicateDestinationConfirmationModal = ({
onOpenChange, onOpenChange,
onConfirm, onConfirm,
isLoading, isLoading,
duplicateProjectId duplicateProjectId,
isDisabled
}: Props) => { }: Props) => {
return ( return (
<Modal isOpen={isOpen} onOpenChange={onOpenChange}> <Modal isOpen={isOpen} onOpenChange={onOpenChange}>
@@ -21,7 +23,12 @@ export const DuplicateDestinationConfirmationModal = ({
<div className="mb-4 text-sm"> <div className="mb-4 text-sm">
<p> <p>
Another secret sync in your organization is already configured with the same Another secret sync in your organization is already configured with the same
destination. Proceeding may cause conflicts or overwrite existing data. destination.{" "}
<span className={isDisabled ? "text-red-400" : ""}>
{isDisabled
? "Your organization does not allow duplicate destination configurations."
: "Proceeding may cause conflicts or overwrite existing data."}
</span>
</p> </p>
{duplicateProjectId && ( {duplicateProjectId && (
<p className="mt-2 text-xs text-mineshaft-400"> <p className="mt-2 text-xs text-mineshaft-400">
@@ -31,26 +38,28 @@ export const DuplicateDestinationConfirmationModal = ({
</code> </code>
</p> </p>
)} )}
<p className="mt-2">Are you sure you want to continue?</p> {!isDisabled && <p className="mt-2">Are you sure you want to continue?</p>}
</div> </div>
<div className="flex items-center gap-4 pt-4"> {!isDisabled && (
<ModalClose asChild> <div className="flex items-center gap-4 pt-4">
<Button <ModalClose asChild>
onClick={onConfirm} <Button
colorSchema="danger" onClick={onConfirm}
isLoading={isLoading} colorSchema="danger"
isDisabled={isLoading} isLoading={isLoading}
> isDisabled={isLoading}
Continue >
</Button> Continue
</ModalClose> </Button>
<ModalClose asChild> </ModalClose>
<Button colorSchema="secondary" variant="plain" isDisabled={isLoading}> <ModalClose asChild>
Cancel <Button colorSchema="secondary" variant="plain" isDisabled={isLoading}>
</Button> Cancel
</ModalClose> </Button>
</div> </ModalClose>
</div>
)}
</ModalContent> </ModalContent>
</Modal> </Modal>
); );
@@ -5,6 +5,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { createNotification } from "@app/components/notifications"; import { createNotification } from "@app/components/notifications";
import { SecretSyncEditFields } from "@app/components/secret-syncs/types"; import { SecretSyncEditFields } from "@app/components/secret-syncs/types";
import { Button, ModalClose } from "@app/components/v2"; import { Button, ModalClose } from "@app/components/v2";
import { useOrganization } from "@app/context";
import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs"; import { SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
import { import {
TSecretSync, TSecretSync,
@@ -30,6 +31,7 @@ export const EditSecretSyncForm = ({ secretSync, fields, onComplete }: Props) =>
const { name: destinationName } = SECRET_SYNC_MAP[secretSync.destination]; const { name: destinationName } = SECRET_SYNC_MAP[secretSync.destination];
const [showDuplicateConfirmation, setShowDuplicateConfirmation] = useState(false); const [showDuplicateConfirmation, setShowDuplicateConfirmation] = useState(false);
const [pendingFormData, setPendingFormData] = useState<TSecretSyncForm | null>(null); const [pendingFormData, setPendingFormData] = useState<TSecretSyncForm | null>(null);
const { currentOrg } = useOrganization();
const formMethods = useForm<TSecretSyncForm>({ const formMethods = useForm<TSecretSyncForm>({
resolver: zodResolver(UpdateSecretSyncFormSchema), resolver: zodResolver(UpdateSecretSyncFormSchema),
@@ -209,6 +211,7 @@ export const EditSecretSyncForm = ({ secretSync, fields, onComplete }: Props) =>
onConfirm={handleConfirmDuplicate} onConfirm={handleConfirmDuplicate}
isLoading={updateSecretSync.isPending} isLoading={updateSecretSync.isPending}
duplicateProjectId={storedDuplicateProjectId} duplicateProjectId={storedDuplicateProjectId}
isDisabled={currentOrg?.blockDuplicateSecretSyncDestinations}
/> />
</> </>
); );
@@ -6,7 +6,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { GenericFieldLabel } from "@app/components/secret-syncs"; import { GenericFieldLabel } from "@app/components/secret-syncs";
import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas"; import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas";
import { Badge } from "@app/components/v2"; import { Badge } from "@app/components/v2";
import { useProject } from "@app/context"; import { useOrganization, useProject } from "@app/context";
import { SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP, SECRET_SYNC_MAP } from "@app/helpers/secretSyncs"; import { SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP, SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
import { SecretSync, useDuplicateDestinationCheck } from "@app/hooks/api/secretSyncs"; import { SecretSync, useDuplicateDestinationCheck } from "@app/hooks/api/secretSyncs";
@@ -51,6 +51,7 @@ import { ZabbixSyncReviewFields } from "./ZabbixSyncReviewFields";
export const SecretSyncReviewFields = () => { export const SecretSyncReviewFields = () => {
const { watch } = useFormContext<TSecretSyncForm>(); const { watch } = useFormContext<TSecretSyncForm>();
const { currentProject } = useProject(); const { currentProject } = useProject();
const { currentOrg } = useOrganization();
let DestinationFieldsComponent: ReactNode; let DestinationFieldsComponent: ReactNode;
let AdditionalSyncOptionsFieldsComponent: ReactNode; let AdditionalSyncOptionsFieldsComponent: ReactNode;
@@ -193,18 +194,50 @@ export const SecretSyncReviewFields = () => {
{isChecking && <span className="text-xs text-mineshaft-400">Checking...</span>} {isChecking && <span className="text-xs text-mineshaft-400">Checking...</span>}
</div> </div>
{hasDuplicate && ( {hasDuplicate && (
<div className="mb-2 flex items-start rounded-md border border-yellow-600 bg-yellow-900/20 px-3 py-2"> <div
<div className="flex text-sm text-yellow-100"> className={`mb-2 flex items-start rounded-md border px-3 py-2 ${
<FontAwesomeIcon icon={faWarning} className="mt-1 mr-2 text-yellow-600" /> currentOrg?.blockDuplicateSecretSyncDestinations
? "border-red-600 bg-red-900/20"
: "border-yellow-600 bg-yellow-900/20"
}`}
>
<div
className={`flex text-sm ${
currentOrg?.blockDuplicateSecretSyncDestinations
? "text-red-100"
: "text-yellow-100"
}`}
>
<FontAwesomeIcon
icon={faWarning}
className={`mt-1 mr-2 ${
currentOrg?.blockDuplicateSecretSyncDestinations
? "text-red-600"
: "text-yellow-600"
}`}
/>
<div> <div>
<p> <p>
Another secret sync in your organization is already configured with the same {currentOrg?.blockDuplicateSecretSyncDestinations
destination. This may lead to conflicts or unexpected behavior. ? "Another secret sync in your organization is already configured with the same destination. Your organization does not allow duplicate destination configurations."
: "Another secret sync in your organization is already configured with the same destination. This may lead to conflicts or unexpected behavior."}
</p> </p>
{duplicateProjectId && ( {duplicateProjectId && (
<p className="mt-1 text-xs text-yellow-200"> <p
className={`mt-1 text-xs ${
currentOrg?.blockDuplicateSecretSyncDestinations
? "text-red-200"
: "text-yellow-200"
}`}
>
Duplicate found in project ID:{" "} Duplicate found in project ID:{" "}
<code className="rounded-sm bg-yellow-800/50 px-1 py-0.5"> <code
className={`rounded-sm px-1 py-0.5 ${
currentOrg?.blockDuplicateSecretSyncDestinations
? "bg-red-800/50"
: "bg-yellow-800/50"
}`}
>
{duplicateProjectId} {duplicateProjectId}
</code> </code>
</p> </p>
@@ -125,7 +125,8 @@ export const useUpdateOrg = () => {
scannerProductEnabled, scannerProductEnabled,
shareSecretsProductEnabled, shareSecretsProductEnabled,
maxSharedSecretLifetime, maxSharedSecretLifetime,
maxSharedSecretViewLimit maxSharedSecretViewLimit,
blockDuplicateSecretSyncDestinations
}) => { }) => {
return apiRequest.patch(`/api/v1/organization/${orgId}`, { return apiRequest.patch(`/api/v1/organization/${orgId}`, {
name, name,
@@ -146,7 +147,8 @@ export const useUpdateOrg = () => {
scannerProductEnabled, scannerProductEnabled,
shareSecretsProductEnabled, shareSecretsProductEnabled,
maxSharedSecretLifetime, maxSharedSecretLifetime,
maxSharedSecretViewLimit maxSharedSecretViewLimit,
blockDuplicateSecretSyncDestinations
}); });
}, },
onSuccess: () => { onSuccess: () => {
@@ -29,6 +29,7 @@ export type Organization = {
shareSecretsProductEnabled: boolean; shareSecretsProductEnabled: boolean;
maxSharedSecretLifetime: number; maxSharedSecretLifetime: number;
maxSharedSecretViewLimit: number | null; maxSharedSecretViewLimit: number | null;
blockDuplicateSecretSyncDestinations: boolean;
}; };
export type UpdateOrgDTO = { export type UpdateOrgDTO = {
@@ -52,6 +53,7 @@ export type UpdateOrgDTO = {
shareSecretsProductEnabled?: boolean; shareSecretsProductEnabled?: boolean;
maxSharedSecretViewLimit?: number | null; maxSharedSecretViewLimit?: number | null;
maxSharedSecretLifetime?: number; maxSharedSecretLifetime?: number;
blockDuplicateSecretSyncDestinations?: boolean;
}; };
export type BillingDetails = { export type BillingDetails = {
@@ -0,0 +1,72 @@
import { useState } from "react";
import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import { Switch } from "@app/components/v2";
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
import { useUpdateOrg } from "@app/hooks/api/organization/queries";
export const OrgProductSettingsTab = () => {
const { currentOrg } = useOrganization();
const { mutateAsync: updateOrg } = useUpdateOrg();
const [isLoading, setIsLoading] = useState(false);
const handleToggle = async (state: boolean) => {
setIsLoading(true);
try {
if (!currentOrg?.id) {
setIsLoading(false);
return;
}
await updateOrg({
orgId: currentOrg.id,
blockDuplicateSecretSyncDestinations: state
});
createNotification({
text: `Successfully ${state ? "enabled" : "disabled"} blocking duplicate secret sync destinations for this organization`,
type: "success"
});
} catch (err) {
console.error(err);
createNotification({
text: "Failed to update blocking duplicate secret sync destinations setting for this organization",
type: "error"
});
} finally {
setIsLoading(false);
}
};
return (
<div className="mb-6 rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-6">
<div className="mb-6">
<h2 className="text-xl font-medium text-mineshaft-100">Secrets Management</h2>
</div>
<div className="flex items-center justify-between">
<div>
<h3 className="mb-2 text-lg font-medium text-mineshaft-100">
Unique Secret Sync Destination Policy
</h3>
<p className="text-sm text-mineshaft-400">
When enabled, ensures each destination can only be used by one secret sync
configuration, preventing potential conflicts or overwrites.
</p>
</div>
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Settings}>
{(isAllowed) => (
<Switch
id="blockDuplicateSecretSyncDestinations"
isDisabled={!isAllowed || isLoading}
isChecked={currentOrg?.blockDuplicateSecretSyncDestinations ?? false}
onCheckedChange={(state) => handleToggle(state as boolean)}
/>
)}
</OrgPermissionCan>
</div>
</div>
);
};
@@ -0,0 +1 @@
export { OrgProductSettingsTab } from "./OrgProductSettingsTab";
@@ -10,6 +10,7 @@ import { ExternalMigrationsTab } from "../ExternalMigrationsTab";
import { KmipTab } from "../KmipTab/OrgKmipTab"; import { KmipTab } from "../KmipTab/OrgKmipTab";
import { OrgEncryptionTab } from "../OrgEncryptionTab"; import { OrgEncryptionTab } from "../OrgEncryptionTab";
import { OrgGeneralTab } from "../OrgGeneralTab"; import { OrgGeneralTab } from "../OrgGeneralTab";
import { OrgProductSettingsTab } from "../OrgProductSettingsTab";
import { OrgProvisioningTab } from "../OrgProvisioningTab"; import { OrgProvisioningTab } from "../OrgProvisioningTab";
import { OrgSecurityTab } from "../OrgSecurityTab"; import { OrgSecurityTab } from "../OrgSecurityTab";
import { OrgSsoTab } from "../OrgSsoTab"; import { OrgSsoTab } from "../OrgSsoTab";
@@ -63,7 +64,12 @@ export const OrgTabGroup = () => {
key: "project-templates", key: "project-templates",
component: ProjectTemplatesTab component: ProjectTemplatesTab
}, },
{ name: "KMIP", key: "kmip", component: KmipTab } { name: "KMIP", key: "kmip", component: KmipTab },
{
name: "Product Enforcements",
key: "product-enforcements",
component: OrgProductSettingsTab
}
]; ];
const [selectedTab, setSelectedTab] = useState(search.selectedTab || tabs[0].key); const [selectedTab, setSelectedTab] = useState(search.selectedTab || tabs[0].key);
@@ -1 +1,2 @@
export { OrgProductSettingsTab } from "./OrgProductSettingsTab";
export { OrgTabGroup } from "./OrgTabGroup"; export { OrgTabGroup } from "./OrgTabGroup";
@@ -36,9 +36,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -48,9 +47,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: z.string().refine((val) => val.toLowerCase() === val, "Must be lowercase"), name: z.string().refine((val) => val.toLowerCase() === val, "Must be lowercase"),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -95,9 +95,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -107,9 +106,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: z.string().refine((val) => val.toLowerCase() === val, "Must be lowercase"), name: z.string().refine((val) => val.toLowerCase() === val, "Must be lowercase"),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -37,9 +37,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -49,9 +48,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: z name: z
.string() .string()
@@ -75,8 +75,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -86,8 +86,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -39,9 +39,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -51,9 +50,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -240,8 +240,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -251,8 +251,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -60,9 +60,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -72,9 +71,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -99,8 +99,8 @@ const formSchema = z
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -110,8 +110,8 @@ const formSchema = z
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -61,9 +61,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -73,9 +72,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -50,9 +50,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -62,9 +61,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -40,9 +40,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -52,9 +51,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -44,9 +44,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -56,9 +55,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -37,9 +37,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -49,9 +48,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -35,9 +35,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -47,9 +46,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -37,9 +37,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -49,9 +48,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -35,9 +35,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -47,9 +46,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -75,9 +75,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -87,9 +86,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
name: slugSchema(), name: slugSchema(),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -66,8 +66,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -77,8 +77,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
name: z.string().refine((val) => val.toLowerCase() === val, "Must be lowercase"), name: z.string().refine((val) => val.toLowerCase() === val, "Must be lowercase"),
environment: z.object({ name: z.string(), slug: z.string() }), environment: z.object({ name: z.string(), slug: z.string() }),
@@ -37,9 +37,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -49,9 +48,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}) })
.nullable(), .nullable(),
newName: slugSchema().optional(), newName: slugSchema().optional(),
@@ -71,9 +71,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -83,9 +82,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}) })
.nullable(), .nullable(),
newName: slugSchema().optional(), newName: slugSchema().optional(),
@@ -22,9 +22,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -34,9 +33,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
newName: slugSchema().optional() newName: slugSchema().optional()
}); });
@@ -73,8 +73,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -84,8 +84,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
newName: slugSchema().optional(), newName: slugSchema().optional(),
metadata: z metadata: z
@@ -39,9 +39,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -51,9 +50,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}) })
.nullable(), .nullable(),
newName: slugSchema().optional(), newName: slugSchema().optional(),
@@ -241,8 +241,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -252,8 +252,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}) })
.nullable(), .nullable(),
newName: slugSchema().optional(), newName: slugSchema().optional(),
@@ -58,9 +58,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -70,9 +69,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
newName: slugSchema().optional(), newName: slugSchema().optional(),
usernameTemplate: z.string().trim().nullable().optional() usernameTemplate: z.string().trim().nullable().optional()
@@ -97,8 +97,8 @@ const formSchema = z
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -108,8 +108,8 @@ const formSchema = z
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
newName: slugSchema().optional(), newName: slugSchema().optional(),
usernameTemplate: z.string().trim().optional() usernameTemplate: z.string().trim().optional()
@@ -51,9 +51,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -63,9 +62,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}) })
.nullable(), .nullable(),
newName: slugSchema().optional(), newName: slugSchema().optional(),
@@ -50,9 +50,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -62,9 +61,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}) })
.nullable(), .nullable(),
newName: slugSchema().optional(), newName: slugSchema().optional(),
@@ -33,9 +33,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -45,9 +44,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}) })
.nullable(), .nullable(),
newName: slugSchema().optional(), newName: slugSchema().optional(),
@@ -35,9 +35,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -47,9 +46,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
newName: slugSchema().optional(), newName: slugSchema().optional(),
usernameTemplate: z.string().trim().nullable().optional() usernameTemplate: z.string().trim().nullable().optional()
@@ -38,9 +38,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -50,9 +49,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}) })
.nullable(), .nullable(),
newName: slugSchema().optional(), newName: slugSchema().optional(),
@@ -37,9 +37,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
usernameTemplate: z.string().trim().nullable().optional(), usernameTemplate: z.string().trim().nullable().optional(),
maxTTL: z maxTTL: z
@@ -50,9 +49,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
newName: slugSchema().optional() newName: slugSchema().optional()
}); });
@@ -37,9 +37,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -49,9 +48,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
newName: slugSchema().optional(), newName: slugSchema().optional(),
usernameTemplate: z.string().trim().nullable().optional() usernameTemplate: z.string().trim().nullable().optional()
@@ -35,9 +35,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -47,9 +46,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
newName: slugSchema().optional(), newName: slugSchema().optional(),
usernameTemplate: z.string().trim().nullable().optional() usernameTemplate: z.string().trim().nullable().optional()
@@ -73,9 +73,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}), }),
maxTTL: z maxTTL: z
.string() .string()
@@ -85,9 +84,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
// a day if (valMs > ms("10y"))
if (valMs > 24 * 60 * 60 * 1000) ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}) })
.nullable(), .nullable(),
newName: slugSchema().optional(), newName: slugSchema().optional(),
@@ -64,8 +64,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
usernameTemplate: z.string().trim().nullable().optional(), usernameTemplate: z.string().trim().nullable().optional(),
maxTTL: z maxTTL: z
@@ -76,8 +76,8 @@ const formSchema = z.object({
const valMs = ms(val); const valMs = ms(val);
if (valMs < 60 * 1000) if (valMs < 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be a greater than 1min" });
if (valMs > 24 * 60 * 60 * 1000) if (valMs > ms("10y"))
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" }); ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than 10 years" });
}), }),
newName: z.string().refine((val) => val.toLowerCase() === val, "Must be lowercase") newName: z.string().refine((val) => val.toLowerCase() === val, "Must be lowercase")
}); });
@@ -0,0 +1,14 @@
{{- if and .Values.serviceAccount.createAsAuthDelegator .Values.serviceAccount.create -}}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "infisical-gateway.serviceAccountName" . }}-system-auth-delegator-cluster-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: {{ include "infisical-gateway.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -2,6 +2,7 @@
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
namespace: {{ .Release.Namespace }}
name: {{ include "infisical-gateway.serviceAccountName" . }} name: {{ include "infisical-gateway.serviceAccountName" . }}
labels: labels:
{{- include "infisical-gateway.labels" . | nindent 4 }} {{- include "infisical-gateway.labels" . | nindent 4 }}
@@ -21,6 +21,7 @@ fullnameOverride: ""
serviceAccount: serviceAccount:
create: true create: true
automount: true automount: true
createAsAuthDelegator: true
annotations: {} annotations: {}
name: "" name: ""