From b8890c841c4c6afd9084fed797cfd7c26b326b1f Mon Sep 17 00:00:00 2001 From: Lauris Skraucis Date: Thu, 9 May 2024 15:25:14 +0200 Subject: [PATCH] fix: managed user timeZone, timeFormat and weekStart during creation (#14955) * refactor: create, update user inputs use types instead of custom validators * fix: save weekStart, timeFormat, timeZone when creating user * fix: save weekStart, timeFormat, timeZone when creating user * e2e: fix env variables and test weekStart, timeZone and timeFormat during user create --- .../oauth-client-users.controller.e2e-spec.ts | 5 ++ .../services/oauth-clients-users.service.ts | 3 ++ .../users/inputs/create-managed-user.input.ts | 22 ++++----- .../users/inputs/update-managed-user.input.ts | 20 ++++---- .../users/inputs/validators/is-time-format.ts | 12 ----- .../users/inputs/validators/is-week-start.ts | 23 ---------- .../v2/src/modules/users/users.repository.ts | 2 +- apps/api/v2/swagger/documentation.json | 46 +++++++++++++++---- apps/api/v2/test/setEnvVars.ts | 2 + .../viewer/teams/inviteMember/utils.ts | 9 ++++ 10 files changed, 80 insertions(+), 64 deletions(-) delete mode 100644 apps/api/v2/src/modules/users/inputs/validators/is-time-format.ts delete mode 100644 apps/api/v2/src/modules/users/inputs/validators/is-week-start.ts diff --git a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.e2e-spec.ts b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.e2e-spec.ts index 568dfd8db4..59cc6b2cea 100644 --- a/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.e2e-spec.ts +++ b/apps/api/v2/src/modules/oauth-clients/controllers/oauth-client-users/oauth-client-users.controller.e2e-spec.ts @@ -139,6 +139,8 @@ describe("OAuth Client Users Endpoints", () => { const requestBody: CreateManagedUserInput = { email: userEmail, timeZone: userTimeZone, + weekStart: "Monday", + timeFormat: 24, }; const response = await request(app.getHttpServer()) @@ -158,6 +160,9 @@ describe("OAuth Client Users Endpoints", () => { expect(responseBody.status).toEqual(SUCCESS_STATUS); expect(responseBody.data).toBeDefined(); expect(responseBody.data.user.email).toEqual(getOAuthUserEmail(oAuthClient.id, requestBody.email)); + expect(responseBody.data.user.timeZone).toEqual(requestBody.timeZone); + expect(responseBody.data.user.weekStart).toEqual(requestBody.weekStart); + expect(responseBody.data.user.timeFormat).toEqual(requestBody.timeFormat); expect(responseBody.data.accessToken).toBeDefined(); expect(responseBody.data.refreshToken).toBeDefined(); diff --git a/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts b/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts index 8c81aa1a1d..a595b377ff 100644 --- a/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts +++ b/apps/api/v2/src/modules/oauth-clients/services/oauth-clients-users.service.ts @@ -53,6 +53,9 @@ export class OAuthClientUsersService { }, }, isPlatformManaged, + timeFormat: body.timeFormat, + weekStart: body.weekStart, + timeZone: body.timeZone, }) )[0]; await this.userRepository.addToOAuthClient(user.id, oAuthClientId); diff --git a/apps/api/v2/src/modules/users/inputs/create-managed-user.input.ts b/apps/api/v2/src/modules/users/inputs/create-managed-user.input.ts index 7e66b9a749..8d20908957 100644 --- a/apps/api/v2/src/modules/users/inputs/create-managed-user.input.ts +++ b/apps/api/v2/src/modules/users/inputs/create-managed-user.input.ts @@ -1,8 +1,8 @@ -import { IsTimeFormat } from "@/modules/users/inputs/validators/is-time-format"; -import { IsWeekStart } from "@/modules/users/inputs/validators/is-week-start"; import { ApiProperty } from "@nestjs/swagger"; -import { IsNumber, IsOptional, IsTimeZone, IsString, Validate } from "class-validator"; +import { IsOptional, IsTimeZone, IsString } from "class-validator"; +export type WeekDay = "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday"; +export type TimeFormat = 12 | 24; export class CreateManagedUserInput { @IsString() @ApiProperty({ example: "alice@example.com" }) @@ -12,17 +12,17 @@ export class CreateManagedUserInput { @IsOptional() name?: string; - @IsNumber() @IsOptional() - @Validate(IsTimeFormat) - @ApiProperty({ example: 12 }) - timeFormat?: number; + @ApiProperty({ example: 12, enum: [12, 24], description: "Must be 12 or 24" }) + timeFormat?: TimeFormat; - @IsString() @IsOptional() - @Validate(IsWeekStart) - @ApiProperty({ example: "Sunday" }) - weekStart?: string; + @IsString() + @ApiProperty({ + example: "Monday", + enum: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + }) + weekStart?: WeekDay; @IsTimeZone() @IsOptional() diff --git a/apps/api/v2/src/modules/users/inputs/update-managed-user.input.ts b/apps/api/v2/src/modules/users/inputs/update-managed-user.input.ts index 4f3df48960..fd938c511c 100644 --- a/apps/api/v2/src/modules/users/inputs/update-managed-user.input.ts +++ b/apps/api/v2/src/modules/users/inputs/update-managed-user.input.ts @@ -1,6 +1,6 @@ -import { IsTimeFormat } from "@/modules/users/inputs/validators/is-time-format"; -import { IsWeekStart } from "@/modules/users/inputs/validators/is-week-start"; -import { IsNumber, IsOptional, IsString, IsTimeZone, Validate } from "class-validator"; +import { TimeFormat, WeekDay } from "@/modules/users/inputs/create-managed-user.input"; +import { ApiProperty } from "@nestjs/swagger"; +import { IsNumber, IsOptional, IsString, IsTimeZone } from "class-validator"; export class UpdateManagedUserInput { @IsString() @@ -11,19 +11,21 @@ export class UpdateManagedUserInput { @IsOptional() name?: string; - @IsNumber() @IsOptional() - @Validate(IsTimeFormat) - timeFormat?: number; + @ApiProperty({ example: 12, enum: [12, 24], description: "Must be 12 or 24" }) + timeFormat?: TimeFormat; @IsNumber() @IsOptional() defaultScheduleId?: number; - @IsString() @IsOptional() - @Validate(IsWeekStart) - weekStart?: string; + @IsString() + @ApiProperty({ + example: "Monday", + enum: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], + }) + weekStart?: WeekDay; @IsTimeZone() @IsOptional() diff --git a/apps/api/v2/src/modules/users/inputs/validators/is-time-format.ts b/apps/api/v2/src/modules/users/inputs/validators/is-time-format.ts deleted file mode 100644 index 2271a7e4f7..0000000000 --- a/apps/api/v2/src/modules/users/inputs/validators/is-time-format.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ValidatorConstraint, ValidatorConstraintInterface } from "class-validator"; - -@ValidatorConstraint({ name: "isTimeFormat", async: false }) -export class IsTimeFormat implements ValidatorConstraintInterface { - validate(timeFormat: number) { - return timeFormat === 12 || timeFormat === 24; - } - - defaultMessage() { - return "timeFormat must be a number either 12 or 24"; - } -} diff --git a/apps/api/v2/src/modules/users/inputs/validators/is-week-start.ts b/apps/api/v2/src/modules/users/inputs/validators/is-week-start.ts deleted file mode 100644 index d21cf12719..0000000000 --- a/apps/api/v2/src/modules/users/inputs/validators/is-week-start.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ValidatorConstraint, ValidatorConstraintInterface } from "class-validator"; - -@ValidatorConstraint({ name: "isWeekStart", async: false }) -export class IsWeekStart implements ValidatorConstraintInterface { - validate(weekStart: string) { - if (!weekStart) return false; - - const lowerCaseWeekStart = weekStart.toLowerCase(); - return ( - lowerCaseWeekStart === "monday" || - lowerCaseWeekStart === "tuesday" || - lowerCaseWeekStart === "wednesday" || - lowerCaseWeekStart === "thursday" || - lowerCaseWeekStart === "friday" || - lowerCaseWeekStart === "saturday" || - lowerCaseWeekStart === "sunday" - ); - } - - defaultMessage() { - return "weekStart must be a string either Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, or Sunday"; - } -} diff --git a/apps/api/v2/src/modules/users/users.repository.ts b/apps/api/v2/src/modules/users/users.repository.ts index e0239ed07b..e03429b192 100644 --- a/apps/api/v2/src/modules/users/users.repository.ts +++ b/apps/api/v2/src/modules/users/users.repository.ts @@ -157,7 +157,7 @@ export class UsersRepository { formatInput(userInput: CreateManagedUserInput | UpdateManagedUserInput) { if (userInput.weekStart) { - userInput.weekStart = capitalize(userInput.weekStart); + userInput.weekStart = userInput.weekStart; } if (userInput.timeZone) { diff --git a/apps/api/v2/swagger/documentation.json b/apps/api/v2/swagger/documentation.json index 7b4ff5618a..ee4d0fba91 100644 --- a/apps/api/v2/swagger/documentation.json +++ b/apps/api/v2/swagger/documentation.json @@ -1651,11 +1651,25 @@ }, "timeFormat": { "type": "number", - "example": 12 + "example": 12, + "enum": [ + 12, + 24 + ], + "description": "Must be 12 or 24" }, "weekStart": { "type": "string", - "example": "Sunday" + "example": "Monday", + "enum": [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday" + ] }, "timeZone": { "type": "string", @@ -1731,21 +1745,37 @@ "UpdateManagedUserInput": { "type": "object", "properties": { + "timeFormat": { + "type": "number", + "example": 12, + "enum": [ + 12, + 24 + ], + "description": "Must be 12 or 24" + }, + "weekStart": { + "type": "string", + "example": "Monday", + "enum": [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + "Sunday" + ] + }, "email": { "type": "string" }, "name": { "type": "string" }, - "timeFormat": { - "type": "number" - }, "defaultScheduleId": { "type": "number" }, - "weekStart": { - "type": "string" - }, "timeZone": { "type": "string" } diff --git a/apps/api/v2/test/setEnvVars.ts b/apps/api/v2/test/setEnvVars.ts index a0e9bce905..5760cb6eb1 100644 --- a/apps/api/v2/test/setEnvVars.ts +++ b/apps/api/v2/test/setEnvVars.ts @@ -8,6 +8,8 @@ const env: Partial> = { JWT_SECRET: "XF+Hws3A5g2eyWA5uGYYVJ74X+wrCWJ8oWo6kAfU6O8=", LOG_LEVEL: "trace", REDIS_URL: "redis://localhost:9199", + STRIPE_API_KEY: "sk_test_51J4", + STRIPE_WEBHOOK_SECRET: "whsec_51J4", }; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore diff --git a/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts b/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts index c77cc24b1f..2ca4f84a62 100644 --- a/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts +++ b/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts @@ -215,6 +215,9 @@ export async function createNewUsersConnectToOrgIfExists({ autoAcceptEmailDomain, connectionInfoMap, isPlatformManaged, + timeFormat, + weekStart, + timeZone, }: { usernamesOrEmails: string[]; input: InviteMemberOptions["input"]; @@ -222,6 +225,9 @@ export async function createNewUsersConnectToOrgIfExists({ autoAcceptEmailDomain?: string; connectionInfoMap: Record>; isPlatformManaged?: boolean; + timeFormat?: number; + weekStart?: string; + timeZone?: string; }) { // fail if we have invalid emails usernamesOrEmails.forEach((usernameOrEmail) => checkInputEmailIsValid(usernameOrEmail)); @@ -253,6 +259,9 @@ export async function createNewUsersConnectToOrgIfExists({ verified: true, invitedTo: input.teamId, isPlatformManaged: !!isPlatformManaged, + timeFormat, + weekStart, + timeZone, organizationId: orgId || null, // If the user is invited to a child team, they are automatically added to the parent org ...(orgId ? {