diff --git a/apps/web/pages/api/auth/setup.test.ts b/apps/web/pages/api/auth/setup.test.ts new file mode 100644 index 00000000000000..bd0a1ad43391fd --- /dev/null +++ b/apps/web/pages/api/auth/setup.test.ts @@ -0,0 +1,90 @@ +import prismock from "../../../../../tests/libs/__mocks__/prisma"; + +import type { Request, Response } from "express"; +import type { NextApiRequest, NextApiResponse } from "next"; +import { createMocks } from "node-mocks-http"; +import { describe, test, expect, vi } from "vitest"; + +import { UserPermissionRole, CreationSource, IdentityProvider } from "@calcom/prisma/enums"; + +import handler from "./setup"; + +type CustomNextApiRequest = NextApiRequest & Request; +type CustomNextApiResponse = NextApiResponse & Response; + +vi.mock("@calcom/lib/server/i18n", () => { + return { + getTranslation: (key: string) => { + return () => key; + }, + }; +}); + +describe("setup", () => { + test("should return a 400 error if users already exists", async () => { + const { req, res } = createMocks({ + method: "POST", + body: { + email: "test@example.com", + username: "test", + }, + }); + + await prismock.user.create({ + data: { + email: "test@example.com", + }, + }); + + await handler(req, res); + + expect(res.statusCode).toBe(400); + }); + + test("should return 422 if request body is invalid", async () => { + const { req, res } = createMocks({ + method: "POST", + body: { + email: "test@example.com", + }, + }); + + await handler(req, res); + + expect(res.statusCode).toBe(422); + }); + + test("should create a new admin user", async () => { + const { req, res } = createMocks({ + method: "POST", + body: { + username: "test", + full_name: "Test User", + email_address: "test@example.com", + password: "ADMINtestingpassword123!", + }, + }); + + await handler(req, res); + + expect(res.statusCode).toBe(200); + + const user = await prismock.user.findFirst({ + where: { + email: "test@example.com", + }, + }); + + expect(user).toEqual( + expect.objectContaining({ + email: "test@example.com", + username: "test", + locked: false, + organizationId: null, + identityProvider: IdentityProvider.CAL, + role: UserPermissionRole.ADMIN, + creationSource: CreationSource.SELF_SERVE_ADMIN, + }) + ); + }); +}); diff --git a/apps/web/pages/api/auth/setup.ts b/apps/web/pages/api/auth/setup.ts index f6a6222ed5b532..c3223cb7a3ba13 100644 --- a/apps/web/pages/api/auth/setup.ts +++ b/apps/web/pages/api/auth/setup.ts @@ -1,12 +1,11 @@ import type { NextApiRequest } from "next"; import z from "zod"; -import { hashPassword } from "@calcom/features/auth/lib/hashPassword"; import { isPasswordValid } from "@calcom/features/auth/lib/isPasswordValid"; import { emailRegex } from "@calcom/lib/emailSchema"; import { HttpError } from "@calcom/lib/http-error"; import { defaultHandler, defaultResponder } from "@calcom/lib/server"; -import slugify from "@calcom/lib/slugify"; +import { UserCreationService } from "@calcom/lib/server/service/userCreationService"; import prisma from "@calcom/prisma"; import { IdentityProvider } from "@calcom/prisma/enums"; import { CreationSource } from "@calcom/prisma/enums"; @@ -34,22 +33,19 @@ async function handler(req: NextApiRequest) { throw new HttpError({ statusCode: 422, message: parsedQuery.error.message }); } - const username = slugify(parsedQuery.data.username.trim()); const userEmail = parsedQuery.data.email_address.toLowerCase(); - const hashedPassword = await hashPassword(parsedQuery.data.password); - - await prisma.user.create({ + await UserCreationService.createUser({ data: { - username, + username: parsedQuery.data.username.trim(), email: userEmail, - password: { create: { hash: hashedPassword } }, + password: parsedQuery.data.password, role: "ADMIN", name: parsedQuery.data.full_name, emailVerified: new Date(), locale: "en", // TODO: We should revisit this identityProvider: IdentityProvider.CAL, - creationSource: CreationSource.WEBAPP, + creationSource: CreationSource.SELF_SERVE_ADMIN, }, }); diff --git a/packages/prisma/migrations/20250209030127_add_self_serve_admin_to_creation_source/migration.sql b/packages/prisma/migrations/20250209030127_add_self_serve_admin_to_creation_source/migration.sql new file mode 100644 index 00000000000000..e495cd8516612d --- /dev/null +++ b/packages/prisma/migrations/20250209030127_add_self_serve_admin_to_creation_source/migration.sql @@ -0,0 +1,2 @@ +-- AlterEnum +ALTER TYPE "CreationSource" ADD VALUE 'self_serve_admin'; diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma index e69f513399920b..38d02202f29d07 100644 --- a/packages/prisma/schema.prisma +++ b/packages/prisma/schema.prisma @@ -43,9 +43,10 @@ enum PeriodType { } enum CreationSource { - API_V1 @map("api_v1") - API_V2 @map("api_v2") - WEBAPP @map("webapp") + API_V1 @map("api_v1") + API_V2 @map("api_v2") + WEBAPP @map("webapp") + SELF_SERVE_ADMIN @map("self_serve_admin") } model Host {