Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions apps/api/v1/pages/api/users/[userId]/_patch.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import type { NextApiRequest } from "next";

import { sendChangeOfEmailVerification } from "@calcom/features/auth/lib/verifyEmail";
import { FeaturesRepository } from "@calcom/features/flags/features.repository";
import { getFeatureRepository } from "@calcom/features/di/containers/FeatureRepository";
import { UserRepository } from "@calcom/features/users/repositories/UserRepository";
import { HttpError } from "@calcom/lib/http-error";
import { uploadAvatar } from "@calcom/lib/server/avatar";
import { defaultResponder } from "@calcom/lib/server/defaultResponder";
import prisma from "@calcom/prisma";
import type { Prisma } from "@calcom/prisma/client";

import type { NextApiRequest } from "next";
import { schemaQueryUserId } from "~/lib/validations/shared/queryUserId";
import { schemaUserEditBodyParams, schemaUserReadPublic } from "~/lib/validations/user";

Expand Down Expand Up @@ -140,7 +138,7 @@ export async function patchHandler(req: NextApiRequest) {
throw new HttpError({ statusCode: 404, message: "User not found" });
}

const featuresRepository = new FeaturesRepository(prisma);
const featuresRepository = getFeatureRepository();
const emailVerification = await featuresRepository.checkIfFeatureIsEnabledGlobally("email-verification");

const hasEmailBeenChanged = typeof body.email === "string" && currentUser.email !== body.email;
Expand All @@ -150,9 +148,9 @@ export async function patchHandler(req: NextApiRequest) {

if (hasEmailBeenChanged && newEmail) {
const secondaryEmail = await userRepository.findSecondaryEmailByUserIdAndEmail({
userId: query.userId,
email: newEmail,
});
userId: query.userId,
email: newEmail,
});

if (emailVerification) {
if (secondaryEmail && secondaryEmail.emailVerified) {
Expand Down
43 changes: 25 additions & 18 deletions apps/api/v1/test/lib/bookings/_post.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
// TODO: Fix tests (These test were never running due to the vitest workspace config)
import prismaMock from "@calcom/testing/lib/__mocks__/prismaMock";

import type { Request, Response } from "express";
import type { NextApiRequest, NextApiResponse } from "next";
import { createMocks } from "node-mocks-http";
import { describe, expect, test, vi, beforeEach } from "vitest";

import dayjs from "@calcom/dayjs";
import { getEventTypesFromDB } from "@calcom/features/bookings/lib/handleNewBooking/getEventTypesFromDB";
import sendPayload from "@calcom/features/webhooks/lib/sendOrSchedulePayload";
import { ErrorCode } from "@calcom/lib/errorCodes";
import { buildBooking, buildEventType, buildWebhook, buildUser } from "@calcom/lib/test/builder";
import { buildBooking, buildEventType, buildUser, buildWebhook } from "@calcom/lib/test/builder";
import { prisma } from "@calcom/prisma";
import type { Booking } from "@calcom/prisma/client";
import { CreationSource, BookingStatus } from "@calcom/prisma/enums";

import { BookingStatus, CreationSource } from "@calcom/prisma/enums";
import type { Request, Response } from "express";
import type { NextApiRequest, NextApiResponse } from "next";
import { createMocks } from "node-mocks-http";
import { beforeEach, describe, expect, test, vi } from "vitest";
import handler from "../../../pages/api/bookings/_post";

vi.mock("@calcom/features/bookings/lib/handleNewBooking/getEventTypesFromDB", () => ({
Expand Down Expand Up @@ -67,9 +64,11 @@ vi.mock("@calcom/features/webhooks/lib/sendOrSchedulePayload", () => ({

const mockFindOriginalRescheduledBooking = vi.fn();
vi.mock("@calcom/features/bookings/repositories/BookingRepository", () => ({
BookingRepository: vi.fn().mockImplementation(function() { return {
findOriginalRescheduledBooking: mockFindOriginalRescheduledBooking,
}; }),
BookingRepository: vi.fn().mockImplementation(function () {
return {
findOriginalRescheduledBooking: mockFindOriginalRescheduledBooking,
};
}),
}));

vi.mock("@calcom/features/watchlist/operations/check-if-users-are-blocked.controller", () => ({
Expand All @@ -94,7 +93,7 @@ vi.mock("@calcom/features/di/containers/QualifiedHosts", () => ({
}));

vi.mock("@calcom/features/bookings/lib/EventManager", () => ({
default: vi.fn().mockImplementation(function() {
default: vi.fn().mockImplementation(function () {
return {
reschedule: vi.fn().mockResolvedValue({
results: [],
Expand Down Expand Up @@ -154,11 +153,19 @@ vi.mock("@calcom/features/profile/repositories/ProfileRepository", () => ({
}),
},
}));
vi.mock("@calcom/features/flags/features.repository", () => ({
FeaturesRepository: vi.fn().mockImplementation(function() { return {
checkIfFeatureIsEnabledGlobally: vi.fn().mockResolvedValue(false),
checkIfTeamHasFeature: vi.fn().mockResolvedValue(false),
}; }),
const mockCheckIfFeatureIsEnabledGlobally = vi.fn().mockResolvedValue(false);
const mockCheckIfTeamHasFeature = vi.fn().mockResolvedValue(false);

vi.mock("@calcom/features/di/containers/FeatureRepository", () => ({
getFeatureRepository: () => ({
checkIfFeatureIsEnabledGlobally: mockCheckIfFeatureIsEnabledGlobally,
}),
}));

vi.mock("@calcom/features/di/containers/TeamFeatureRepository", () => ({
getTeamFeatureRepository: () => ({
checkIfTeamHasFeature: mockCheckIfTeamHasFeature,
}),
}));

vi.mock("@calcom/features/webhooks/lib/getWebhooks", () => ({
Expand Down
8 changes: 4 additions & 4 deletions apps/api/v2/src/ee/me/me.module.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { Module } from "@nestjs/common";
import { MeController } from "@/ee/me/me.controller";
import { MeService } from "@/ee/me/services/me.service";
import { SchedulesModule_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/schedules.module";
import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository";
import { PrismaWorkerModule } from "@/modules/prisma/prisma-worker.module";
import { PrismaFeatureRepository } from "@/lib/repositories/prisma-features.repository";
import { OAuthClientModule } from "@/modules/oauth-clients/oauth-client.module";
import { PrismaWorkerModule } from "@/modules/prisma/prisma-worker.module";
import { TokensModule } from "@/modules/tokens/tokens.module";
import { UsersModule } from "@/modules/users/users.module";
import { Module } from "@nestjs/common";

@Module({
imports: [PrismaWorkerModule, UsersModule, SchedulesModule_2024_04_15, TokensModule, OAuthClientModule],
providers: [PrismaFeaturesRepository, MeService],
providers: [PrismaFeatureRepository, MeService],
controllers: [MeController],
})
export class MeModule {}
44 changes: 18 additions & 26 deletions apps/api/v2/src/ee/me/services/me.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { SchedulesService_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/services/schedules.service";
import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository";
import { UpdateManagedUserInput } from "@/modules/users/inputs/update-managed-user.input";
import { UserWithProfile, UsersRepository } from "@/modules/users/users.repository";
import { Injectable } from "@nestjs/common";

import { sendChangeOfEmailVerification } from "@calcom/platform-libraries/emails";
import type { Prisma } from "@calcom/prisma/client";
import { Injectable } from "@nestjs/common";
import { SchedulesService_2024_04_15 } from "@/ee/schedules/schedules_2024_04_15/services/schedules.service";
import { PrismaFeatureRepository } from "@/lib/repositories/prisma-features.repository";
import { UpdateManagedUserInput } from "@/modules/users/inputs/update-managed-user.input";
import { UsersRepository, UserWithProfile } from "@/modules/users/users.repository";

export interface UpdateMeResult {
updatedUser: UserWithProfile;
Expand All @@ -16,7 +15,7 @@ export class MeService {
constructor(
private readonly usersRepository: UsersRepository,
private readonly schedulesService: SchedulesService_2024_04_15,
private readonly featuresRepository: PrismaFeaturesRepository
private readonly featureRepository: PrismaFeatureRepository
) {}

async updateMe(params: {
Expand All @@ -27,18 +26,14 @@ export class MeService {
const update = { ...updateData };

if (update.timeZone && user.defaultScheduleId) {
await this.schedulesService.updateUserSchedule(
user,
user.defaultScheduleId,
{
timeZone: update.timeZone,
}
);
await this.schedulesService.updateUserSchedule(user, user.defaultScheduleId, {
timeZone: update.timeZone,
});
}

const isEmailVerificationEnabled = user.isPlatformManaged
? false
: await this.featuresRepository.checkIfFeatureIsEnabledGlobally("email-verification");
: await this.featureRepository.checkIfFeatureIsEnabledGlobally("email-verification");

const hasEmailBeenChanged = update.email && user.email !== update.email;
const newEmail = update.email;
Expand All @@ -48,14 +43,13 @@ export class MeService {
const secondaryEmail = await this.usersRepository.findVerifiedSecondaryEmail(user.id, newEmail);

if (secondaryEmail && secondaryEmail.emailVerified) {
const updatedUser =
await this.usersRepository.swapPrimaryEmailWithSecondaryEmail(
user.id,
secondaryEmail.id,
user.email,
user.emailVerified,
newEmail
);
const updatedUser = await this.usersRepository.swapPrimaryEmailWithSecondaryEmail(
user.id,
secondaryEmail.id,
user.email,
user.emailVerified,
newEmail
);

return {
updatedUser,
Expand All @@ -73,9 +67,7 @@ export class MeService {
}

const updatedUser =
Object.keys(update).length > 0
? await this.usersRepository.update(user.id, update)
: user;
Object.keys(update).length > 0 ? await this.usersRepository.update(user.id, update) : user;

if (sendEmailVerification && newEmail) {
await sendChangeOfEmailVerification({
Expand Down
6 changes: 3 additions & 3 deletions apps/api/v2/src/lib/modules/available-slots.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Module } from "@nestjs/common";
import { PrismaBookingRepository } from "@/lib/repositories/prisma-booking.repository";
import { PrismaEventTypeRepository } from "@/lib/repositories/prisma-event-type.repository";
import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository";
import { PrismaTeamFeatureRepository } from "@/lib/repositories/prisma-features.repository";
import { PrismaHolidayRepository } from "@/lib/repositories/prisma-holiday.repository";
import { PrismaMembershipRepository } from "@/lib/repositories/prisma-membership.repository";
import { PrismaOOORepository } from "@/lib/repositories/prisma-ooo.repository";
Expand All @@ -19,7 +20,6 @@ import { QualifiedHostsService } from "@/lib/services/qualified-hosts.service";
import { UserAvailabilityService } from "@/lib/services/user-availability.service";
import { PrismaWorkerModule } from "@/modules/prisma/prisma-worker.module";
import { RedisService } from "@/modules/redis/redis.service";
import { Module } from "@nestjs/common";

@Module({
imports: [PrismaWorkerModule],
Expand All @@ -34,7 +34,7 @@ import { Module } from "@nestjs/common";
PrismaRoutingFormResponseRepository,
PrismaTeamRepository,
RedisService,
PrismaFeaturesRepository,
PrismaTeamFeatureRepository,
PrismaMembershipRepository,
CheckBookingLimitsService,
AvailableSlotsService,
Expand Down
6 changes: 3 additions & 3 deletions apps/api/v2/src/lib/modules/regular-booking.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Module, Scope } from "@nestjs/common";
import { Logger } from "@/lib/logger.bridge";
import { PrismaAttributeRepository } from "@/lib/repositories/prisma-attribute.repository";
import { PrismaBookingRepository } from "@/lib/repositories/prisma-booking.repository";
import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository";
import { PrismaTeamFeatureRepository } from "@/lib/repositories/prisma-features.repository";
import { PrismaHostRepository } from "@/lib/repositories/prisma-host.repository";
import { PrismaOOORepository } from "@/lib/repositories/prisma-ooo.repository";
import { PrismaUserRepository } from "@/lib/repositories/prisma-user.repository";
Expand All @@ -19,14 +20,13 @@ import { BookingEmailAndSmsTasker } from "@/lib/services/tasker/booking-emails-s
import { BookingEmailAndSmsTriggerTaskerService } from "@/lib/services/tasker/booking-emails-sms-trigger-tasker.service";
import { TaskerService } from "@/lib/services/tasker.service";
import { PrismaModule } from "@/modules/prisma/prisma.module";
import { Module, Scope } from "@nestjs/common";

@Module({
imports: [PrismaModule],
providers: [
PrismaAttributeRepository,
PrismaBookingRepository,
PrismaFeaturesRepository,
PrismaTeamFeatureRepository,
PrismaHostRepository,
PrismaOOORepository,
PrismaUserRepository,
Expand Down
25 changes: 21 additions & 4 deletions apps/api/v2/src/lib/repositories/prisma-features.repository.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import {
PrismaFeatureRepository as PrismaFeatureRepositoryLib,
PrismaTeamFeatureRepository as PrismaTeamFeatureRepositoryLib,
PrismaUserFeatureRepository as PrismaUserFeatureRepositoryLib,
} from "@calcom/platform-libraries/repositories";
import type { PrismaClient } from "@calcom/prisma";
import { Injectable } from "@nestjs/common";
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";

import { PrismaFeaturesRepository as PrismaFeaturesRepositoryLib } from "@calcom/platform-libraries/repositories";
import type { PrismaClient } from "@calcom/prisma";
@Injectable()
export class PrismaFeatureRepository extends PrismaFeatureRepositoryLib {
constructor(private readonly dbWrite: PrismaWriteService) {
super(dbWrite.prisma as unknown as PrismaClient);
}
}

@Injectable()
export class PrismaTeamFeatureRepository extends PrismaTeamFeatureRepositoryLib {
constructor(private readonly dbWrite: PrismaWriteService) {
super(dbWrite.prisma as unknown as PrismaClient);
}
}

@Injectable()
export class PrismaFeaturesRepository extends PrismaFeaturesRepositoryLib {
export class PrismaUserFeatureRepository extends PrismaUserFeatureRepositoryLib {
constructor(private readonly dbWrite: PrismaWriteService) {
super(dbWrite.prisma as unknown as PrismaClient);
}
Expand Down
14 changes: 6 additions & 8 deletions apps/api/v2/src/lib/services/available-slots.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { AvailableSlotsService as BaseAvailableSlotsService } from "@calcom/platform-libraries/slots";
import { Injectable } from "@nestjs/common";
import { UserAvailabilityService } from "./user-availability.service";
import { PrismaBookingRepository } from "@/lib/repositories/prisma-booking.repository";
import { PrismaEventTypeRepository } from "@/lib/repositories/prisma-event-type.repository";
import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository";
import { PrismaTeamFeatureRepository } from "@/lib/repositories/prisma-features.repository";
import { PrismaOOORepository } from "@/lib/repositories/prisma-ooo.repository";
import { PrismaRoutingFormResponseRepository } from "@/lib/repositories/prisma-routing-form-response.repository";
import { PrismaScheduleRepository } from "@/lib/repositories/prisma-schedule.repository";
Expand All @@ -13,11 +16,6 @@ import { NoSlotsNotificationService } from "@/lib/services/no-slots-notification
import { OrgMembershipLookupService } from "@/lib/services/org-membership-lookup.service";
import { QualifiedHostsService } from "@/lib/services/qualified-hosts.service";
import { RedisService } from "@/modules/redis/redis.service";
import { Injectable } from "@nestjs/common";

import { AvailableSlotsService as BaseAvailableSlotsService } from "@calcom/platform-libraries/slots";

import { UserAvailabilityService } from "./user-availability.service";

@Injectable()
export class AvailableSlotsService extends BaseAvailableSlotsService {
Expand All @@ -31,7 +29,7 @@ export class AvailableSlotsService extends BaseAvailableSlotsService {
eventTypeRepository: PrismaEventTypeRepository,
userRepository: PrismaUserRepository,
redisService: RedisService,
featuresRepository: PrismaFeaturesRepository,
teamFeatureRepository: PrismaTeamFeatureRepository,
qualifiedHostsService: QualifiedHostsService,
checkBookingLimitsService: CheckBookingLimitsService,
userAvailabilityService: UserAvailabilityService,
Expand All @@ -53,7 +51,7 @@ export class AvailableSlotsService extends BaseAvailableSlotsService {
userAvailabilityService,
busyTimesService,
qualifiedHostsService,
featuresRepo: featuresRepository,
teamFeatureRepository,
noSlotsNotificationService,
orgMembershipLookup: orgMembershipLookupService,
});
Expand Down
13 changes: 6 additions & 7 deletions apps/api/v2/src/lib/services/regular-booking.service.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { RegularBookingService as BaseRegularBookingService } from "@calcom/platform-libraries/bookings";
import type { PrismaClient } from "@calcom/prisma";
import { Injectable } from "@nestjs/common";
import { PrismaBookingRepository } from "@/lib/repositories/prisma-booking.repository";
import { PrismaFeaturesRepository } from "@/lib/repositories/prisma-features.repository";
import { PrismaTeamFeatureRepository } from "@/lib/repositories/prisma-features.repository";
import { PrismaUserRepository } from "@/lib/repositories/prisma-user.repository";
import { BookingEventHandlerService } from "@/lib/services/booking-event-handler.service";
import { CheckBookingAndDurationLimitsService } from "@/lib/services/check-booking-and-duration-limits.service";
import { HashedLinkService } from "@/lib/services/hashed-link.service";
import { LuckyUserService } from "@/lib/services/lucky-user.service";
import { BookingEmailAndSmsTasker } from "@/lib/services/tasker/booking-emails-sms-tasker.service";
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import { Injectable } from "@nestjs/common";

import { RegularBookingService as BaseRegularBookingService } from "@calcom/platform-libraries/bookings";
import type { PrismaClient } from "@calcom/prisma";

@Injectable()
export class RegularBookingService extends BaseRegularBookingService {
Expand All @@ -22,7 +21,7 @@ export class RegularBookingService extends BaseRegularBookingService {
luckyUserService: LuckyUserService,
userRepository: PrismaUserRepository,
bookingEmailAndSmsTasker: BookingEmailAndSmsTasker,
featuresRepository: PrismaFeaturesRepository,
teamFeatureRepository: PrismaTeamFeatureRepository,
bookingEventHandler: BookingEventHandlerService
) {
super({
Expand All @@ -33,7 +32,7 @@ export class RegularBookingService extends BaseRegularBookingService {
luckyUserService,
userRepository,
bookingEmailAndSmsTasker,
featuresRepository,
teamFeatureRepository,
bookingEventHandler,
});
}
Expand Down
Loading