mirror of
https://github.com/Infisical/infisical.git
synced 2025-06-29 04:31:59 +00:00
Compare commits
2 Commits
doc/add-ab
...
testing-me
Author | SHA1 | Date | |
---|---|---|---|
0b1f4f0e2a | |||
b4485a2a57 |
@ -1,4 +1,3 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
@ -8,6 +7,7 @@ import { DYNAMIC_SECRETS } from "@app/lib/api-docs";
|
|||||||
import { daysToMillisecond } from "@app/lib/dates";
|
import { daysToMillisecond } from "@app/lib/dates";
|
||||||
import { removeTrailingSlash } from "@app/lib/fn";
|
import { removeTrailingSlash } from "@app/lib/fn";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { SanitizedDynamicSecretSchema } from "@app/server/routes/sanitizedSchemas";
|
import { SanitizedDynamicSecretSchema } from "@app/server/routes/sanitizedSchemas";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -48,15 +48,7 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
.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),
|
||||||
environmentSlug: z.string().describe(DYNAMIC_SECRETS.CREATE.environmentSlug).min(1),
|
environmentSlug: z.string().describe(DYNAMIC_SECRETS.CREATE.environmentSlug).min(1),
|
||||||
name: z
|
name: slugSchema({ min: 1, max: 64, field: "Name" }).describe(DYNAMIC_SECRETS.CREATE.name)
|
||||||
.string()
|
|
||||||
.describe(DYNAMIC_SECRETS.CREATE.name)
|
|
||||||
.min(1)
|
|
||||||
.toLowerCase()
|
|
||||||
.max(64)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid"
|
|
||||||
})
|
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { GroupsSchema, OrgMembershipRole, UsersSchema } from "@app/db/schemas";
|
import { GroupsSchema, OrgMembershipRole, UsersSchema } from "@app/db/schemas";
|
||||||
import { GROUPS } from "@app/lib/api-docs";
|
import { GROUPS } from "@app/lib/api-docs";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@ -14,15 +14,7 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: z.string().trim().min(1).max(50).describe(GROUPS.CREATE.name),
|
name: z.string().trim().min(1).max(50).describe(GROUPS.CREATE.name),
|
||||||
slug: z
|
slug: slugSchema({ min: 5, max: 36 }).optional().describe(GROUPS.CREATE.slug),
|
||||||
.string()
|
|
||||||
.min(5)
|
|
||||||
.max(36)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(GROUPS.CREATE.slug),
|
|
||||||
role: z.string().trim().min(1).default(OrgMembershipRole.NoAccess).describe(GROUPS.CREATE.role)
|
role: z.string().trim().min(1).default(OrgMembershipRole.NoAccess).describe(GROUPS.CREATE.role)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
@ -100,14 +92,7 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().trim().min(1).describe(GROUPS.UPDATE.name),
|
name: z.string().trim().min(1).describe(GROUPS.UPDATE.name),
|
||||||
slug: z
|
slug: slugSchema({ min: 5, max: 36 }).describe(GROUPS.UPDATE.slug),
|
||||||
.string()
|
|
||||||
.min(5)
|
|
||||||
.max(36)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.describe(GROUPS.UPDATE.slug),
|
|
||||||
role: z.string().trim().min(1).describe(GROUPS.UPDATE.role)
|
role: z.string().trim().min(1).describe(GROUPS.UPDATE.role)
|
||||||
})
|
})
|
||||||
.partial(),
|
.partial(),
|
||||||
|
@ -8,6 +8,7 @@ import { IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
|||||||
import { UnauthorizedError } from "@app/lib/errors";
|
import { UnauthorizedError } from "@app/lib/errors";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import {
|
import {
|
||||||
ProjectPermissionSchema,
|
ProjectPermissionSchema,
|
||||||
@ -33,17 +34,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
body: z.object({
|
body: z.object({
|
||||||
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.identityId),
|
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.identityId),
|
||||||
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.projectSlug),
|
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.projectSlug),
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).optional().describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
|
||||||
permissions: ProjectPermissionSchema.array()
|
permissions: ProjectPermissionSchema.array()
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.permissions)
|
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.permissions)
|
||||||
.optional(),
|
.optional(),
|
||||||
@ -77,7 +68,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
...req.body,
|
...req.body,
|
||||||
slug: req.body.slug ? slugify(req.body.slug) : slugify(alphaNumericNanoId(12)),
|
slug: req.body.slug ?? slugify(alphaNumericNanoId(12)),
|
||||||
isTemporary: false,
|
isTemporary: false,
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore-error this is valid ts
|
// @ts-ignore-error this is valid ts
|
||||||
@ -103,17 +94,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
body: z.object({
|
body: z.object({
|
||||||
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.identityId),
|
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.identityId),
|
||||||
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.projectSlug),
|
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.projectSlug),
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).optional().describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
|
||||||
permissions: ProjectPermissionSchema.array()
|
permissions: ProjectPermissionSchema.array()
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.permissions)
|
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.permissions)
|
||||||
.optional(),
|
.optional(),
|
||||||
@ -159,7 +140,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
...req.body,
|
...req.body,
|
||||||
slug: req.body.slug ? slugify(req.body.slug) : slugify(alphaNumericNanoId(12)),
|
slug: req.body.slug ?? slugify(alphaNumericNanoId(12)),
|
||||||
isTemporary: true,
|
isTemporary: true,
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-ignore-error this is valid ts
|
// @ts-ignore-error this is valid ts
|
||||||
@ -189,16 +170,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.projectSlug),
|
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.projectSlug),
|
||||||
privilegeDetails: z
|
privilegeDetails: z
|
||||||
.object({
|
.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.newSlug),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.newSlug),
|
|
||||||
permissions: ProjectPermissionSchema.array().describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.permissions),
|
permissions: ProjectPermissionSchema.array().describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.permissions),
|
||||||
privilegePermission: ProjectSpecificPrivilegePermissionSchema.describe(
|
privilegePermission: ProjectSpecificPrivilegePermissionSchema.describe(
|
||||||
IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.privilegePermission
|
IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.privilegePermission
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { OrgMembershipRole, OrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas";
|
import { OrgMembershipRole, OrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@ -18,17 +18,10 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
organizationId: z.string().trim()
|
organizationId: z.string().trim()
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 64 }).refine(
|
||||||
.string()
|
(val) => !Object.values(OrgMembershipRole).includes(val as OrgMembershipRole),
|
||||||
.min(1)
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
.trim()
|
),
|
||||||
.refine(
|
|
||||||
(val) => !Object.values(OrgMembershipRole).includes(val as OrgMembershipRole),
|
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
|
||||||
)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid"
|
|
||||||
}),
|
|
||||||
name: z.string().trim(),
|
name: z.string().trim(),
|
||||||
description: z.string().trim().optional(),
|
description: z.string().trim().optional(),
|
||||||
permissions: z.any().array()
|
permissions: z.any().array()
|
||||||
@ -94,17 +87,13 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
roleId: z.string().trim()
|
roleId: z.string().trim()
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
// TODO: Switch to slugSchema after verifying correct methods with Akhil - Omar 11/24
|
||||||
.string()
|
slug: slugSchema({ min: 1, max: 64 })
|
||||||
.trim()
|
|
||||||
.optional()
|
|
||||||
.refine(
|
.refine(
|
||||||
(val) => typeof val !== "undefined" && !Object.keys(OrgMembershipRole).includes(val),
|
(val) => !Object.keys(OrgMembershipRole).includes(val),
|
||||||
"Please choose a different slug, the slug you have entered is reserved."
|
"Please choose a different slug, the slug you have entered is reserved."
|
||||||
)
|
)
|
||||||
.refine((val) => typeof val === "undefined" || slugify(val) === val, {
|
.optional(),
|
||||||
message: "Slug must be a valid"
|
|
||||||
}),
|
|
||||||
name: z.string().trim().optional(),
|
name: z.string().trim().optional(),
|
||||||
description: z.string().trim().optional(),
|
description: z.string().trim().optional(),
|
||||||
permissions: z.any().array().optional()
|
permissions: z.any().array().optional()
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { packRules } from "@casl/ability/extra";
|
import { packRules } from "@casl/ability/extra";
|
||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { ProjectMembershipRole, ProjectMembershipsSchema, ProjectRolesSchema } from "@app/db/schemas";
|
import { ProjectMembershipRole, ProjectMembershipsSchema, ProjectRolesSchema } from "@app/db/schemas";
|
||||||
@ -9,6 +8,7 @@ import {
|
|||||||
} from "@app/ee/services/permission/project-permission";
|
} from "@app/ee/services/permission/project-permission";
|
||||||
import { PROJECT_ROLE } from "@app/lib/api-docs";
|
import { PROJECT_ROLE } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { SanitizedRoleSchemaV1 } from "@app/server/routes/sanitizedSchemas";
|
import { SanitizedRoleSchemaV1 } from "@app/server/routes/sanitizedSchemas";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -32,18 +32,11 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
projectSlug: z.string().trim().describe(PROJECT_ROLE.CREATE.projectSlug)
|
projectSlug: z.string().trim().describe(PROJECT_ROLE.CREATE.projectSlug)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ max: 64 })
|
||||||
.string()
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.refine(
|
.refine(
|
||||||
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
)
|
)
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid"
|
|
||||||
})
|
|
||||||
.describe(PROJECT_ROLE.CREATE.slug),
|
.describe(PROJECT_ROLE.CREATE.slug),
|
||||||
name: z.string().min(1).trim().describe(PROJECT_ROLE.CREATE.name),
|
name: z.string().min(1).trim().describe(PROJECT_ROLE.CREATE.name),
|
||||||
description: z.string().trim().optional().describe(PROJECT_ROLE.CREATE.description),
|
description: z.string().trim().optional().describe(PROJECT_ROLE.CREATE.description),
|
||||||
@ -94,21 +87,13 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
roleId: z.string().trim().describe(PROJECT_ROLE.UPDATE.roleId)
|
roleId: z.string().trim().describe(PROJECT_ROLE.UPDATE.roleId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema()
|
||||||
.string()
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
.optional()
|
|
||||||
.describe(PROJECT_ROLE.UPDATE.slug)
|
|
||||||
.refine(
|
.refine(
|
||||||
(val) =>
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
typeof val === "undefined" ||
|
|
||||||
!Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
)
|
)
|
||||||
.refine((val) => typeof val === "undefined" || slugify(val) === val, {
|
.describe(PROJECT_ROLE.UPDATE.slug)
|
||||||
message: "Slug must be a valid"
|
.optional(),
|
||||||
}),
|
|
||||||
name: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.name),
|
name: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.name),
|
||||||
description: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.description),
|
description: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.description),
|
||||||
permissions: ProjectPermissionV1Schema.array().describe(PROJECT_ROLE.UPDATE.permissions).optional()
|
permissions: ProjectPermissionV1Schema.array().describe(PROJECT_ROLE.UPDATE.permissions).optional()
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { ProjectMembershipRole, ProjectTemplatesSchema } from "@app/db/schemas";
|
import { ProjectMembershipRole, ProjectTemplatesSchema } from "@app/db/schemas";
|
||||||
@ -8,22 +7,13 @@ import { ProjectTemplateDefaultEnvironments } from "@app/ee/services/project-tem
|
|||||||
import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns";
|
import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns";
|
||||||
import { ProjectTemplates } from "@app/lib/api-docs";
|
import { ProjectTemplates } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { UnpackedPermissionSchema } from "@app/server/routes/santizedSchemas/permission";
|
import { UnpackedPermissionSchema } from "@app/server/routes/santizedSchemas/permission";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
const MAX_JSON_SIZE_LIMIT_IN_BYTES = 32_768;
|
const MAX_JSON_SIZE_LIMIT_IN_BYTES = 32_768;
|
||||||
|
|
||||||
const SlugSchema = z
|
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.max(32)
|
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Must be valid slug format"
|
|
||||||
});
|
|
||||||
|
|
||||||
const isReservedRoleSlug = (slug: string) =>
|
const isReservedRoleSlug = (slug: string) =>
|
||||||
Object.values(ProjectMembershipRole).includes(slug as ProjectMembershipRole);
|
Object.values(ProjectMembershipRole).includes(slug as ProjectMembershipRole);
|
||||||
|
|
||||||
@ -34,14 +24,14 @@ const SanitizedProjectTemplateSchema = ProjectTemplatesSchema.extend({
|
|||||||
roles: z
|
roles: z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().trim().min(1),
|
name: z.string().trim().min(1),
|
||||||
slug: SlugSchema,
|
slug: slugSchema(),
|
||||||
permissions: UnpackedPermissionSchema.array()
|
permissions: UnpackedPermissionSchema.array()
|
||||||
})
|
})
|
||||||
.array(),
|
.array(),
|
||||||
environments: z
|
environments: z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().trim().min(1),
|
name: z.string().trim().min(1),
|
||||||
slug: SlugSchema,
|
slug: slugSchema(),
|
||||||
position: z.number().min(1)
|
position: z.number().min(1)
|
||||||
})
|
})
|
||||||
.array()
|
.array()
|
||||||
@ -50,7 +40,7 @@ const SanitizedProjectTemplateSchema = ProjectTemplatesSchema.extend({
|
|||||||
const ProjectTemplateRolesSchema = z
|
const ProjectTemplateRolesSchema = z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().trim().min(1),
|
name: z.string().trim().min(1),
|
||||||
slug: SlugSchema,
|
slug: slugSchema(),
|
||||||
permissions: ProjectPermissionV2Schema.array()
|
permissions: ProjectPermissionV2Schema.array()
|
||||||
})
|
})
|
||||||
.array()
|
.array()
|
||||||
@ -78,7 +68,7 @@ const ProjectTemplateRolesSchema = z
|
|||||||
const ProjectTemplateEnvironmentsSchema = z
|
const ProjectTemplateEnvironmentsSchema = z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().trim().min(1),
|
name: z.string().trim().min(1),
|
||||||
slug: SlugSchema,
|
slug: slugSchema(),
|
||||||
position: z.number().min(1)
|
position: z.number().min(1)
|
||||||
})
|
})
|
||||||
.array()
|
.array()
|
||||||
@ -188,9 +178,11 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
|||||||
schema: {
|
schema: {
|
||||||
description: "Create a project template.",
|
description: "Create a project template.",
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: SlugSchema.refine((val) => !isInfisicalProjectTemplate(val), {
|
name: slugSchema({ field: "name" })
|
||||||
message: `The requested project template name is reserved.`
|
.refine((val) => !isInfisicalProjectTemplate(val), {
|
||||||
}).describe(ProjectTemplates.CREATE.name),
|
message: `The requested project template name is reserved.`
|
||||||
|
})
|
||||||
|
.describe(ProjectTemplates.CREATE.name),
|
||||||
description: z.string().max(256).trim().optional().describe(ProjectTemplates.CREATE.description),
|
description: z.string().max(256).trim().optional().describe(ProjectTemplates.CREATE.description),
|
||||||
roles: ProjectTemplateRolesSchema.default([]).describe(ProjectTemplates.CREATE.roles),
|
roles: ProjectTemplateRolesSchema.default([]).describe(ProjectTemplates.CREATE.roles),
|
||||||
environments: ProjectTemplateEnvironmentsSchema.default(ProjectTemplateDefaultEnvironments).describe(
|
environments: ProjectTemplateEnvironmentsSchema.default(ProjectTemplateDefaultEnvironments).describe(
|
||||||
@ -230,9 +222,10 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
|||||||
description: "Update a project template.",
|
description: "Update a project template.",
|
||||||
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.UPDATE.templateId) }),
|
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.UPDATE.templateId) }),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: SlugSchema.refine((val) => !isInfisicalProjectTemplate(val), {
|
name: slugSchema({ field: "name" })
|
||||||
message: `The requested project template name is reserved.`
|
.refine((val) => !isInfisicalProjectTemplate(val), {
|
||||||
})
|
message: `The requested project template name is reserved.`
|
||||||
|
})
|
||||||
.optional()
|
.optional()
|
||||||
.describe(ProjectTemplates.UPDATE.name),
|
.describe(ProjectTemplates.UPDATE.name),
|
||||||
description: z.string().max(256).trim().optional().describe(ProjectTemplates.UPDATE.description),
|
description: z.string().max(256).trim().optional().describe(ProjectTemplates.UPDATE.description),
|
||||||
|
@ -7,6 +7,7 @@ import { ProjectUserAdditionalPrivilegeTemporaryMode } from "@app/ee/services/pr
|
|||||||
import { PROJECT_USER_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
import { PROJECT_USER_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { SanitizedUserProjectAdditionalPrivilegeSchema } from "@app/server/routes/santizedSchemas/user-additional-privilege";
|
import { SanitizedUserProjectAdditionalPrivilegeSchema } from "@app/server/routes/santizedSchemas/user-additional-privilege";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -21,17 +22,7 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
|
|||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z.object({
|
||||||
projectMembershipId: z.string().min(1).describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.CREATE.projectMembershipId),
|
projectMembershipId: z.string().min(1).describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.CREATE.projectMembershipId),
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).optional().describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((v) => v.toLowerCase() === v, "Slug must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
|
||||||
permissions: ProjectPermissionV2Schema.array().describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.CREATE.permissions),
|
permissions: ProjectPermissionV2Schema.array().describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.CREATE.permissions),
|
||||||
type: z.discriminatedUnion("isTemporary", [
|
type: z.discriminatedUnion("isTemporary", [
|
||||||
z.object({
|
z.object({
|
||||||
@ -87,15 +78,7 @@ export const registerUserAdditionalPrivilegeRouter = async (server: FastifyZodPr
|
|||||||
}),
|
}),
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.UPDATE.slug),
|
||||||
.string()
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((v) => v.toLowerCase() === v, "Slug must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.UPDATE.slug),
|
|
||||||
permissions: ProjectPermissionV2Schema.array()
|
permissions: ProjectPermissionV2Schema.array()
|
||||||
.optional()
|
.optional()
|
||||||
.describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.UPDATE.permissions),
|
.describe(PROJECT_USER_ADDITIONAL_PRIVILEGE.UPDATE.permissions),
|
||||||
|
@ -7,6 +7,7 @@ import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-p
|
|||||||
import { IDENTITY_ADDITIONAL_PRIVILEGE_V2 } from "@app/lib/api-docs";
|
import { IDENTITY_ADDITIONAL_PRIVILEGE_V2 } from "@app/lib/api-docs";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { SanitizedIdentityPrivilegeSchema } from "@app/server/routes/santizedSchemas/identitiy-additional-privilege";
|
import { SanitizedIdentityPrivilegeSchema } from "@app/server/routes/santizedSchemas/identitiy-additional-privilege";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -28,17 +29,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
body: z.object({
|
body: z.object({
|
||||||
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.CREATE.identityId),
|
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.CREATE.identityId),
|
||||||
projectId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.CREATE.projectId),
|
projectId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.CREATE.projectId),
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).optional().describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.CREATE.slug),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.CREATE.slug),
|
|
||||||
permissions: ProjectPermissionV2Schema.array().describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.CREATE.permission),
|
permissions: ProjectPermissionV2Schema.array().describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.CREATE.permission),
|
||||||
type: z.discriminatedUnion("isTemporary", [
|
type: z.discriminatedUnion("isTemporary", [
|
||||||
z.object({
|
z.object({
|
||||||
@ -100,16 +91,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
id: z.string().trim().describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.UPDATE.id)
|
id: z.string().trim().describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.UPDATE.id)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.UPDATE.slug),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.UPDATE.slug),
|
|
||||||
permissions: ProjectPermissionV2Schema.array()
|
permissions: ProjectPermissionV2Schema.array()
|
||||||
.optional()
|
.optional()
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.UPDATE.privilegePermission),
|
.describe(IDENTITY_ADDITIONAL_PRIVILEGE_V2.UPDATE.privilegePermission),
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { packRules } from "@casl/ability/extra";
|
import { packRules } from "@casl/ability/extra";
|
||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
|
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
|
||||||
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
||||||
import { PROJECT_ROLE } from "@app/lib/api-docs";
|
import { PROJECT_ROLE } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { SanitizedRoleSchema } from "@app/server/routes/sanitizedSchemas";
|
import { SanitizedRoleSchema } from "@app/server/routes/sanitizedSchemas";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -29,18 +29,11 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
projectId: z.string().trim().describe(PROJECT_ROLE.CREATE.projectId)
|
projectId: z.string().trim().describe(PROJECT_ROLE.CREATE.projectId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 64 })
|
||||||
.string()
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.refine(
|
.refine(
|
||||||
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
)
|
)
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid"
|
|
||||||
})
|
|
||||||
.describe(PROJECT_ROLE.CREATE.slug),
|
.describe(PROJECT_ROLE.CREATE.slug),
|
||||||
name: z.string().min(1).trim().describe(PROJECT_ROLE.CREATE.name),
|
name: z.string().min(1).trim().describe(PROJECT_ROLE.CREATE.name),
|
||||||
description: z.string().trim().optional().describe(PROJECT_ROLE.CREATE.description),
|
description: z.string().trim().optional().describe(PROJECT_ROLE.CREATE.description),
|
||||||
@ -90,21 +83,13 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
roleId: z.string().trim().describe(PROJECT_ROLE.UPDATE.roleId)
|
roleId: z.string().trim().describe(PROJECT_ROLE.UPDATE.roleId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 64 })
|
||||||
.string()
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
.optional()
|
|
||||||
.describe(PROJECT_ROLE.UPDATE.slug)
|
|
||||||
.refine(
|
.refine(
|
||||||
(val) =>
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
typeof val === "undefined" ||
|
|
||||||
!Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
)
|
)
|
||||||
.refine((val) => typeof val === "undefined" || slugify(val) === val, {
|
.optional()
|
||||||
message: "Slug must be a valid"
|
.describe(PROJECT_ROLE.UPDATE.slug),
|
||||||
}),
|
|
||||||
name: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.name),
|
name: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.name),
|
||||||
description: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.description),
|
description: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.description),
|
||||||
permissions: ProjectPermissionV2Schema.array().describe(PROJECT_ROLE.UPDATE.permissions).optional()
|
permissions: ProjectPermissionV2Schema.array().describe(PROJECT_ROLE.UPDATE.permissions).optional()
|
||||||
|
24
backend/src/server/lib/schemas.ts
Normal file
24
backend/src/server/lib/schemas.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import slugify from "@sindresorhus/slugify";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
interface SlugSchemaInputs {
|
||||||
|
min?: number;
|
||||||
|
max?: number;
|
||||||
|
field?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const slugSchema = ({ min = 1, max = 32, field = "Slug" }: SlugSchemaInputs = {}) => {
|
||||||
|
return z
|
||||||
|
.string()
|
||||||
|
.toLowerCase()
|
||||||
|
.trim()
|
||||||
|
.min(min, {
|
||||||
|
message: `${field} field must be at least ${min} character${min === 1 ? "" : "s"}`
|
||||||
|
})
|
||||||
|
.max(max, {
|
||||||
|
message: `${field} field must be at most ${max} character${max === 1 ? "" : "s"}`
|
||||||
|
})
|
||||||
|
.refine((v) => slugify(v, { lowercase: true, separator: "-" }) === v, {
|
||||||
|
message: `${field} field can only contain letters, numbers, and hyphens`
|
||||||
|
});
|
||||||
|
};
|
@ -1,4 +1,3 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { InternalKmsSchema, KmsKeysSchema } from "@app/db/schemas";
|
import { InternalKmsSchema, KmsKeysSchema } from "@app/db/schemas";
|
||||||
@ -8,19 +7,12 @@ import { getBase64SizeInBytes, isBase64 } from "@app/lib/base64";
|
|||||||
import { SymmetricEncryption } from "@app/lib/crypto/cipher";
|
import { SymmetricEncryption } from "@app/lib/crypto/cipher";
|
||||||
import { OrderByDirection } from "@app/lib/types";
|
import { OrderByDirection } from "@app/lib/types";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
import { CmekOrderBy } from "@app/services/cmek/cmek-types";
|
import { CmekOrderBy } from "@app/services/cmek/cmek-types";
|
||||||
|
|
||||||
const keyNameSchema = z
|
const keyNameSchema = slugSchema({ min: 1, max: 32, field: "Name" });
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.max(32)
|
|
||||||
.toLowerCase()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Name must be slug friendly"
|
|
||||||
});
|
|
||||||
const keyDescriptionSchema = z.string().trim().max(500).optional();
|
const keyDescriptionSchema = z.string().trim().max(500).optional();
|
||||||
|
|
||||||
const base64Schema = z.string().superRefine((val, ctx) => {
|
const base64Schema = z.string().superRefine((val, ctx) => {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { ExternalGroupOrgRoleMappingsSchema } from "@app/db/schemas/external-group-org-role-mappings";
|
import { ExternalGroupOrgRoleMappingsSchema } from "@app/db/schemas/external-group-org-role-mappings";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@ -48,13 +48,7 @@ export const registerExternalGroupOrgRoleMappingRouter = async (server: FastifyZ
|
|||||||
mappings: z
|
mappings: z
|
||||||
.object({
|
.object({
|
||||||
groupName: z.string().trim().min(1),
|
groupName: z.string().trim().min(1),
|
||||||
roleSlug: z
|
roleSlug: slugSchema({ max: 64 })
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.toLowerCase()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Role must be a valid slug"
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
.array()
|
.array()
|
||||||
}),
|
}),
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -14,6 +13,7 @@ import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-t
|
|||||||
import { AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs";
|
import { AUDIT_LOGS, ORGANIZATIONS } from "@app/lib/api-docs";
|
||||||
import { getLastMidnightDateISO } from "@app/lib/fn";
|
import { getLastMidnightDateISO } from "@app/lib/fn";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { ActorType, AuthMode, MfaMethod } from "@app/services/auth/auth-type";
|
import { ActorType, AuthMode, MfaMethod } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@ -243,22 +243,10 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
params: z.object({ organizationId: z.string().trim() }),
|
params: z.object({ organizationId: z.string().trim() }),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: z.string().trim().max(64, { message: "Name must be 64 or fewer characters" }).optional(),
|
name: z.string().trim().max(64, { message: "Name must be 64 or fewer characters" }).optional(),
|
||||||
slug: z
|
slug: slugSchema({ max: 64 }).optional(),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.max(64, { message: "Slug must be 64 or fewer characters" })
|
|
||||||
.regex(/^[a-zA-Z0-9-]+$/, "Slug must only contain alphanumeric characters or hyphens")
|
|
||||||
.optional(),
|
|
||||||
authEnforced: z.boolean().optional(),
|
authEnforced: z.boolean().optional(),
|
||||||
scimEnabled: z.boolean().optional(),
|
scimEnabled: z.boolean().optional(),
|
||||||
defaultMembershipRoleSlug: z
|
defaultMembershipRoleSlug: slugSchema({ max: 64, field: "Default Membership Role" }).optional(),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.trim()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Membership role must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
enforceMfa: z.boolean().optional(),
|
enforceMfa: z.boolean().optional(),
|
||||||
selectedMfaMethod: z.nativeEnum(MfaMethod).optional()
|
selectedMfaMethod: z.nativeEnum(MfaMethod).optional()
|
||||||
}),
|
}),
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { ProjectEnvironmentsSchema } from "@app/db/schemas";
|
import { ProjectEnvironmentsSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { ENVIRONMENTS } from "@app/lib/api-docs";
|
import { ENVIRONMENTS } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@ -124,13 +124,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
|
|||||||
body: z.object({
|
body: z.object({
|
||||||
name: z.string().trim().describe(ENVIRONMENTS.CREATE.name),
|
name: z.string().trim().describe(ENVIRONMENTS.CREATE.name),
|
||||||
position: z.number().min(1).optional().describe(ENVIRONMENTS.CREATE.position),
|
position: z.number().min(1).optional().describe(ENVIRONMENTS.CREATE.position),
|
||||||
slug: z
|
slug: slugSchema({ max: 64 }).describe(ENVIRONMENTS.CREATE.slug)
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.describe(ENVIRONMENTS.CREATE.slug)
|
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@ -188,14 +182,7 @@ export const registerProjectEnvRouter = async (server: FastifyZodProvider) => {
|
|||||||
id: z.string().trim().describe(ENVIRONMENTS.UPDATE.id)
|
id: z.string().trim().describe(ENVIRONMENTS.UPDATE.id)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ max: 64 }).optional().describe(ENVIRONMENTS.UPDATE.slug),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.optional()
|
|
||||||
.refine((v) => !v || slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.describe(ENVIRONMENTS.UPDATE.slug),
|
|
||||||
name: z.string().trim().optional().describe(ENVIRONMENTS.UPDATE.name),
|
name: z.string().trim().optional().describe(ENVIRONMENTS.UPDATE.name),
|
||||||
position: z.number().optional().describe(ENVIRONMENTS.UPDATE.position)
|
position: z.number().optional().describe(ENVIRONMENTS.UPDATE.position)
|
||||||
}),
|
}),
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { SecretTagsSchema } from "@app/db/schemas";
|
import { SecretTagsSchema } from "@app/db/schemas";
|
||||||
import { SECRET_TAGS } from "@app/lib/api-docs";
|
import { SECRET_TAGS } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@ -111,14 +111,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
|
|||||||
projectId: z.string().trim().describe(SECRET_TAGS.CREATE.projectId)
|
projectId: z.string().trim().describe(SECRET_TAGS.CREATE.projectId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ max: 64 }).describe(SECRET_TAGS.CREATE.slug),
|
||||||
.string()
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
.describe(SECRET_TAGS.CREATE.slug)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Invalid slug. Slug can only contain alphanumeric characters and hyphens."
|
|
||||||
}),
|
|
||||||
color: z.string().trim().describe(SECRET_TAGS.CREATE.color)
|
color: z.string().trim().describe(SECRET_TAGS.CREATE.color)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
@ -153,14 +146,7 @@ export const registerSecretTagRouter = async (server: FastifyZodProvider) => {
|
|||||||
tagId: z.string().trim().describe(SECRET_TAGS.UPDATE.tagId)
|
tagId: z.string().trim().describe(SECRET_TAGS.UPDATE.tagId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ max: 64 }).describe(SECRET_TAGS.UPDATE.slug),
|
||||||
.string()
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
.describe(SECRET_TAGS.UPDATE.slug)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Invalid slug. Slug can only contain alphanumeric characters and hyphens."
|
|
||||||
}),
|
|
||||||
color: z.string().trim().describe(SECRET_TAGS.UPDATE.color)
|
color: z.string().trim().describe(SECRET_TAGS.UPDATE.color)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { SlackIntegrationsSchema, WorkflowIntegrationsSchema } from "@app/db/schemas";
|
import { SlackIntegrationsSchema, WorkflowIntegrationsSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { getConfig } from "@app/lib/config/env";
|
import { getConfig } from "@app/lib/config/env";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
@ -35,12 +35,7 @@ export const registerSlackRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
slug: z
|
slug: slugSchema({ max: 64 }),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
}),
|
|
||||||
description: z.string().optional()
|
description: z.string().optional()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
@ -288,13 +283,7 @@ export const registerSlackRouter = async (server: FastifyZodProvider) => {
|
|||||||
id: z.string()
|
id: z.string()
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ max: 64 }).optional(),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
description: z.string().optional()
|
description: z.string().optional()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -12,6 +11,7 @@ import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
|||||||
import { InfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-types";
|
import { InfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-types";
|
||||||
import { PROJECTS } from "@app/lib/api-docs";
|
import { PROJECTS } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -27,14 +27,6 @@ const projectWithEnv = SanitizedProjectSchema.extend({
|
|||||||
environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array()
|
environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array()
|
||||||
});
|
});
|
||||||
|
|
||||||
const slugSchema = z
|
|
||||||
.string()
|
|
||||||
.min(5)
|
|
||||||
.max(36)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be at least 5 character but no more than 36"
|
|
||||||
});
|
|
||||||
|
|
||||||
export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
||||||
/* Get project key */
|
/* Get project key */
|
||||||
server.route({
|
server.route({
|
||||||
@ -162,21 +154,9 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
body: z.object({
|
body: z.object({
|
||||||
projectName: z.string().trim().describe(PROJECTS.CREATE.projectName),
|
projectName: z.string().trim().describe(PROJECTS.CREATE.projectName),
|
||||||
projectDescription: z.string().trim().optional().describe(PROJECTS.CREATE.projectDescription),
|
projectDescription: z.string().trim().optional().describe(PROJECTS.CREATE.projectDescription),
|
||||||
slug: z
|
slug: slugSchema({ min: 5, max: 36 }).optional().describe(PROJECTS.CREATE.slug),
|
||||||
.string()
|
|
||||||
.min(5)
|
|
||||||
.max(36)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(PROJECTS.CREATE.slug),
|
|
||||||
kmsKeyId: z.string().optional(),
|
kmsKeyId: z.string().optional(),
|
||||||
template: z
|
template: slugSchema({ field: "Template Name", max: 64 })
|
||||||
.string()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Template name must be in slug format"
|
|
||||||
})
|
|
||||||
.optional()
|
.optional()
|
||||||
.default(InfisicalProjectTemplate.Default)
|
.default(InfisicalProjectTemplate.Default)
|
||||||
.describe(PROJECTS.CREATE.template)
|
.describe(PROJECTS.CREATE.template)
|
||||||
@ -244,7 +224,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
slug: slugSchema.describe("The slug of the project to delete.")
|
slug: slugSchema({ min: 5, max: 36 }).describe("The slug of the project to delete.")
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: SanitizedProjectSchema
|
200: SanitizedProjectSchema
|
||||||
@ -278,7 +258,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
slug: slugSchema.describe("The slug of the project to get.")
|
slug: slugSchema({ min: 5, max: 36 }).describe("The slug of the project to get.")
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: projectWithEnv
|
200: projectWithEnv
|
||||||
@ -311,7 +291,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
slug: slugSchema.describe("The slug of the project to update.")
|
slug: slugSchema({ min: 5, max: 36 }).describe("The slug of the project to update.")
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: z.string().trim().optional().describe(PROJECTS.UPDATE.name),
|
name: z.string().trim().optional().describe(PROJECTS.UPDATE.name),
|
||||||
@ -354,7 +334,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
slug: slugSchema.describe(PROJECTS.LIST_CAS.slug)
|
slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CAS.slug)
|
||||||
}),
|
}),
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
status: z.enum([CaStatus.ACTIVE, CaStatus.PENDING_CERTIFICATE]).optional().describe(PROJECTS.LIST_CAS.status),
|
status: z.enum([CaStatus.ACTIVE, CaStatus.PENDING_CERTIFICATE]).optional().describe(PROJECTS.LIST_CAS.status),
|
||||||
@ -395,7 +375,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
params: z.object({
|
params: z.object({
|
||||||
slug: slugSchema.describe(PROJECTS.LIST_CERTIFICATES.slug)
|
slug: slugSchema({ min: 5, max: 36 }).describe(PROJECTS.LIST_CERTIFICATES.slug)
|
||||||
}),
|
}),
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
friendlyName: z.string().optional().describe(PROJECTS.LIST_CERTIFICATES.friendlyName),
|
friendlyName: z.string().optional().describe(PROJECTS.LIST_CERTIFICATES.friendlyName),
|
||||||
|
@ -3,7 +3,6 @@ import { Controller, useForm } from "react-hook-form";
|
|||||||
import { faCheck } from "@fortawesome/free-solid-svg-icons";
|
import { faCheck } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
@ -18,6 +17,7 @@ import {
|
|||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { useCreateWsTag } from "@app/hooks/api";
|
import { useCreateWsTag } from "@app/hooks/api";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
export const secretTagsColors = [
|
export const secretTagsColors = [
|
||||||
{
|
{
|
||||||
@ -88,13 +88,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const createTagSchema = z.object({
|
const createTagSchema = z.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, field: "Tag Slug" }),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.toLowerCase()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Invalid slug. Slug can only contain alphanumeric characters and hyphens."
|
|
||||||
}),
|
|
||||||
color: z.string().trim()
|
color: z.string().trim()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
export type Kms = {
|
export type Kms = {
|
||||||
id: string;
|
id: string;
|
||||||
description: string;
|
description: string;
|
||||||
@ -88,13 +89,7 @@ export const ExternalKmsInputSchema = z.discriminatedUnion("type", [
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
export const AddExternalKmsSchema = z.object({
|
export const AddExternalKmsSchema = z.object({
|
||||||
name: z
|
name: slugSchema({ min: 1, field: "Alias" }),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Alias must be a valid slug"
|
|
||||||
}),
|
|
||||||
description: z.string().trim().optional(),
|
description: z.string().trim().optional(),
|
||||||
provider: ExternalKmsInputSchema
|
provider: ExternalKmsInputSchema
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,23 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
import slugify from "@sindresorhus/slugify";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export const slugSchema = z
|
interface SlugSchemaInputs {
|
||||||
.string()
|
min?: number;
|
||||||
.trim()
|
max?: number;
|
||||||
.min(1)
|
field?: string;
|
||||||
.max(32)
|
}
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
export const slugSchema = ({ min = 1, max = 32, field = "Slug" }: SlugSchemaInputs = {}) => {
|
||||||
message: "Invalid slug format"
|
return z
|
||||||
});
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(min, {
|
||||||
|
message: `${field} field must be at least ${min} character${min === 1 ? "" : "s"}`
|
||||||
|
})
|
||||||
|
.max(max, {
|
||||||
|
message: `${field} field must be at most ${max} character${max === 1 ? "" : "s"}`
|
||||||
|
})
|
||||||
|
.refine((v) => slugify(v, { lowercase: true, separator: "-" }) === v, {
|
||||||
|
message: `${field} field can only contain letters, numbers, and hyphens`
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -9,12 +9,13 @@ import { Button, FormControl, Input, Modal, ModalContent } from "@app/components
|
|||||||
import { useOrganization } from "@app/context";
|
import { useOrganization } from "@app/context";
|
||||||
import { useCreateOrgRole, useGetOrgRole, useUpdateOrgRole } from "@app/hooks/api";
|
import { useCreateOrgRole, useGetOrgRole, useUpdateOrgRole } from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
const schema = z
|
const schema = z
|
||||||
.object({
|
.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
slug: z.string()
|
slug: slugSchema({ min: 1 })
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
@ -17,16 +16,10 @@ import {
|
|||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { EncryptionAlgorithm, TCmek, useCreateCmek, useUpdateCmek } from "@app/hooks/api/cmeks";
|
import { EncryptionAlgorithm, TCmek, useCreateCmek, useUpdateCmek } from "@app/hooks/api/cmeks";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
name: z
|
name: slugSchema({ min: 1, max: 32, field: "Name" }),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.toLowerCase()
|
|
||||||
.max(32)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Name must be in slug format"
|
|
||||||
}),
|
|
||||||
description: z.string().max(500).optional(),
|
description: z.string().max(500).optional(),
|
||||||
encryptionAlgorithm: z.nativeEnum(EncryptionAlgorithm)
|
encryptionAlgorithm: z.nativeEnum(EncryptionAlgorithm)
|
||||||
});
|
});
|
||||||
|
@ -13,12 +13,13 @@ import {
|
|||||||
useUpdateProjectRole
|
useUpdateProjectRole
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
const schema = z
|
const schema = z
|
||||||
.object({
|
.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
slug: z.string()
|
slug: slugSchema({ min: 1 })
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ import { useEffect } from "react";
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
@ -15,6 +14,7 @@ import {
|
|||||||
useGetSlackIntegrationById,
|
useGetSlackIntegrationById,
|
||||||
useUpdateSlackIntegration
|
useUpdateSlackIntegration
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
id?: string;
|
id?: string;
|
||||||
@ -22,13 +22,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const slackFormSchema = z.object({
|
const slackFormSchema = z.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, field: "Alias" }),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Alias must be a valid slug"
|
|
||||||
}),
|
|
||||||
description: z.string().optional()
|
description: z.string().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
slug: slugSchema,
|
slug: slugSchema(),
|
||||||
name: z.string().trim().min(1),
|
name: z.string().trim().min(1),
|
||||||
permissions: projectRoleFormSchema.shape.permissions
|
permissions: projectRoleFormSchema.shape.permissions
|
||||||
});
|
});
|
||||||
|
@ -32,7 +32,7 @@ const formSchema = z.object({
|
|||||||
environments: z
|
environments: z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().trim().min(1),
|
name: z.string().trim().min(1),
|
||||||
slug: slugSchema
|
slug: slugSchema({ min: 1, max: 32 })
|
||||||
})
|
})
|
||||||
.array()
|
.array()
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
@ -18,17 +17,10 @@ import {
|
|||||||
useCreateProjectTemplate,
|
useCreateProjectTemplate,
|
||||||
useUpdateProjectTemplate
|
useUpdateProjectTemplate
|
||||||
} from "@app/hooks/api/projectTemplates";
|
} from "@app/hooks/api/projectTemplates";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
name: z
|
name: slugSchema({ min: 1, max: 32, field: "Name" }),
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.max(32)
|
|
||||||
.toLowerCase()
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Name must be in slug format"
|
|
||||||
}),
|
|
||||||
description: z.string().max(500).optional()
|
description: z.string().max(500).optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import slugify from "@sindresorhus/slugify";
|
import { z } from "zod";
|
||||||
import * as yup from "yup";
|
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
|
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { useCreateWsEnvironment } from "@app/hooks/api";
|
import { useCreateWsEnvironment } from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
popUp: UsePopUpState<["createEnv"]>;
|
popUp: UsePopUpState<["createEnv"]>;
|
||||||
@ -15,26 +15,20 @@ type Props = {
|
|||||||
handlePopUpToggle: (popUpName: keyof UsePopUpState<["createEnv"]>, state?: boolean) => void;
|
handlePopUpToggle: (popUpName: keyof UsePopUpState<["createEnv"]>, state?: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const schema = yup.object({
|
const schema = z.object({
|
||||||
environmentName: yup.string().label("Environment Name").required(),
|
environmentName: z
|
||||||
environmentSlug: yup
|
|
||||||
.string()
|
.string()
|
||||||
.label("Environment Slug")
|
.min(1, { message: "Environment Name field must be at least 1 character" }),
|
||||||
.test({
|
environmentSlug: slugSchema()
|
||||||
test: (slug) => slugify(slug as string) === slug,
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.required()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type FormData = yup.InferType<typeof schema>;
|
export type FormData = z.infer<typeof schema>;
|
||||||
|
|
||||||
export const AddEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props) => {
|
export const AddEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props) => {
|
||||||
|
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const { mutateAsync, isLoading } = useCreateWsEnvironment();
|
const { mutateAsync, isLoading } = useCreateWsEnvironment();
|
||||||
const { control, handleSubmit, reset } = useForm<FormData>({
|
const { control, handleSubmit, reset } = useForm<FormData>({
|
||||||
resolver: yupResolver(schema)
|
resolver: zodResolver(schema)
|
||||||
});
|
});
|
||||||
|
|
||||||
const onFormSubmit = async ({ environmentName, environmentSlug }: FormData) => {
|
const onFormSubmit = async ({ environmentName, environmentSlug }: FormData) => {
|
||||||
@ -112,7 +106,11 @@ export const AddEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpToggle
|
|||||||
Create
|
Create
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button onClick={() => handlePopUpClose("createEnv")} colorSchema="secondary" variant="plain">
|
<Button
|
||||||
|
onClick={() => handlePopUpClose("createEnv")}
|
||||||
|
colorSchema="secondary"
|
||||||
|
variant="plain"
|
||||||
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { yupResolver } from "@hookform/resolvers/yup";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import slugify from "@sindresorhus/slugify";
|
import { z } from "zod";
|
||||||
import * as yup from "yup";
|
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
|
import { Button, FormControl, Input, Modal, ModalContent } from "@app/components/v2";
|
||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { useUpdateWsEnvironment } from "@app/hooks/api";
|
import { useUpdateWsEnvironment } from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
popUp: UsePopUpState<["updateEnv"]>;
|
popUp: UsePopUpState<["updateEnv"]>;
|
||||||
@ -15,25 +15,18 @@ type Props = {
|
|||||||
handlePopUpToggle: (popUpName: keyof UsePopUpState<["updateEnv"]>, state?: boolean) => void;
|
handlePopUpToggle: (popUpName: keyof UsePopUpState<["updateEnv"]>, state?: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const schema = yup.object({
|
const schema = z.object({
|
||||||
name: yup.string().label("Environment Name").required(),
|
name: z.string(),
|
||||||
slug: yup
|
slug: slugSchema({ min: 1 })
|
||||||
.string()
|
|
||||||
.label("Environment Slug")
|
|
||||||
.test({
|
|
||||||
test: (slug) => slugify(slug as string) === slug,
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.required()
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type FormData = yup.InferType<typeof schema>;
|
export type FormData = z.infer<typeof schema>;
|
||||||
|
|
||||||
export const UpdateEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props) => {
|
export const UpdateEnvironmentModal = ({ popUp, handlePopUpClose, handlePopUpToggle }: Props) => {
|
||||||
const { currentWorkspace } = useWorkspace();
|
const { currentWorkspace } = useWorkspace();
|
||||||
const { mutateAsync, isLoading } = useUpdateWsEnvironment();
|
const { mutateAsync, isLoading } = useUpdateWsEnvironment();
|
||||||
const { control, handleSubmit, reset } = useForm<FormData>({
|
const { control, handleSubmit, reset } = useForm<FormData>({
|
||||||
resolver: yupResolver(schema),
|
resolver: zodResolver(schema),
|
||||||
values: popUp.updateEnv.data as FormData
|
values: popUp.updateEnv.data as FormData
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Controller, useForm } from "react-hook-form";
|
import { Controller, useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
@ -8,11 +7,10 @@ import { Button, FormControl, Input, Modal, ModalClose, ModalContent } from "@ap
|
|||||||
import { useWorkspace } from "@app/context";
|
import { useWorkspace } from "@app/context";
|
||||||
import { useCreateWsTag } from "@app/hooks/api";
|
import { useCreateWsTag } from "@app/hooks/api";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
import { slugSchema } from "@app/lib/schemas";
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
slug: z.string().refine((v) => slugify(v) === v, {
|
slug: slugSchema({ min: 10, field: "Tag Slug" })
|
||||||
message: "Invalid slug. Slug can only contain alphanumeric characters and hyphens."
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type FormData = z.infer<typeof schema>;
|
export type FormData = z.infer<typeof schema>;
|
||||||
|
Reference in New Issue
Block a user