diff --git a/backend/src/ee/routes/v1/group-router.ts b/backend/src/ee/routes/v1/group-router.ts index e17f4795b..a386f8380 100644 --- a/backend/src/ee/routes/v1/group-router.ts +++ b/backend/src/ee/routes/v1/group-router.ts @@ -1,3 +1,4 @@ +import slugify from "@sindresorhus/slugify"; import { z } from "zod"; import { GroupsSchema, OrgMembershipRole, UsersSchema } from "@app/db/schemas"; @@ -13,8 +14,15 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => { body: z.object({ organizationId: z.string().trim(), name: z.string().trim().min(1), - slug: z.string().trim().min(1), - role: z.string().trim().min(1).default(OrgMembershipRole.NoAccess) // TODO: add describe + slug: z + .string() + .min(5) + .max(36) + .refine((v) => slugify(v) === v, { + message: "Slug must be a valid slug" + }) + .optional(), + role: z.string().trim().min(1).default(OrgMembershipRole.NoAccess) }), response: { 200: GroupsSchema @@ -45,7 +53,13 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => { body: z .object({ name: z.string().trim().min(1), - slug: z.string().trim().min(1), + slug: z + .string() + .min(5) + .max(36) + .refine((v) => slugify(v) === v, { + message: "Slug must be a valid slug" + }), role: z.string().trim().min(1) }) .partial(), diff --git a/backend/src/ee/services/group/group-service.ts b/backend/src/ee/services/group/group-service.ts index a2e0b517c..919e0404e 100644 --- a/backend/src/ee/services/group/group-service.ts +++ b/backend/src/ee/services/group/group-service.ts @@ -1,8 +1,10 @@ import { ForbiddenError } from "@casl/ability"; +import slugify from "@sindresorhus/slugify"; import { OrgMembershipRole, TOrgRoles } from "@app/db/schemas"; import { isAtLeastAsPrivileged } from "@app/lib/casl"; import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors"; +import { alphaNumericNanoId } from "@app/lib/nanoid"; import { TOrgDALFactory } from "../../../services/org/org-dal"; import { TUserDALFactory } from "../../../services/user/user-dal"; @@ -21,11 +23,10 @@ import { import { TUserGroupMembershipDALFactory } from "./user-group-membership-dal"; type TGroupServiceFactoryDep = { - // TODO: Pick - userDAL: TUserDALFactory; - groupDAL: TGroupDALFactory; - orgDAL: TOrgDALFactory; - userGroupMembershipDAL: TUserGroupMembershipDALFactory; + userDAL: Pick; + groupDAL: Pick; + orgDAL: Pick; + userGroupMembershipDAL: Pick; permissionService: Pick; licenseService: Pick; }; @@ -69,7 +70,7 @@ export const groupServiceFactory = ({ const group = await groupDAL.create({ name, - slug, // TODO: slugify + slug: slug || slugify(`${name}-${alphaNumericNanoId(4)}`), orgId, role: isCustomRole ? OrgMembershipRole.Custom : role, roleId: customRole?.id @@ -122,7 +123,7 @@ export const groupServiceFactory = ({ }, { name, - slug, // TODO: slugify + slug: slug ? slugify(slug) : undefined, ...(role ? { role: customRole ? OrgMembershipRole.Custom : role, diff --git a/backend/src/ee/services/group/group-types.ts b/backend/src/ee/services/group/group-types.ts index 36f47a4ac..02486e014 100644 --- a/backend/src/ee/services/group/group-types.ts +++ b/backend/src/ee/services/group/group-types.ts @@ -2,7 +2,7 @@ import { TOrgPermission } from "@app/lib/types"; export type TCreateGroupDTO = { name: string; - slug: string; + slug?: string; role: string; } & TOrgPermission; diff --git a/backend/src/services/group-project/group-project-service.ts b/backend/src/services/group-project/group-project-service.ts index 22db3af9e..0bb9c1c4d 100644 --- a/backend/src/services/group-project/group-project-service.ts +++ b/backend/src/services/group-project/group-project-service.ts @@ -22,12 +22,12 @@ import { } from "./group-project-types"; type TGroupProjectServiceFactoryDep = { - groupProjectDAL: TGroupProjectDALFactory; + groupProjectDAL: Pick; groupProjectMembershipRoleDAL: Pick< TGroupProjectMembershipRoleDALFactory, "create" | "transaction" | "insertMany" | "delete" >; - projectDAL: TProjectDALFactory; + projectDAL: Pick; projectRoleDAL: Pick; groupDAL: Pick; permissionService: Pick;