Skip to content

Commit

Permalink
fix: dont allow adding scheduleId to event-type if user does not own …
Browse files Browse the repository at this point in the history
…schedule
  • Loading branch information
supalarry committed Jul 22, 2024
1 parent 05205d8 commit 2bdb93e
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,15 @@ describe("Event types Endpoints", () => {
let schedulesRepostoryFixture: SchedulesRepositoryFixture;

const userEmail = "event-types-test-e2e@api.com";
const falseTestEmail = "false-event-types@api.com";
const name = "bob-the-builder";
const username = name;
let eventType: EventTypeOutput_2024_06_14;
let user: User;
let falseTestUser: User;
let firstSchedule: Schedule;
let secondSchedule: Schedule;
let falseTestSchedule: Schedule;

beforeAll(async () => {
const moduleRef = await withApiAuth(
Expand Down Expand Up @@ -105,6 +108,12 @@ describe("Event types Endpoints", () => {
username,
});

falseTestUser = await userRepositoryFixture.create({
email: falseTestEmail,
name: "false-test",
username: falseTestEmail,
});

firstSchedule = await schedulesRepostoryFixture.create({
userId: user.id,
name: "work",
Expand All @@ -117,6 +126,12 @@ describe("Event types Endpoints", () => {
timeZone: "Europe/Rome",
});

falseTestSchedule = await schedulesRepostoryFixture.create({
userId: falseTestUser.id,
name: "work",
timeZone: "Europe/Rome",
});

await app.init();
});

Expand All @@ -140,6 +155,40 @@ describe("Event types Endpoints", () => {
expect(user).toBeDefined();
});

it("should not allow creating an event type with schedule user does not own", async () => {
const scheduleId = falseTestSchedule.id;

const body: CreateEventTypeInput_2024_06_14 = {
title: "Coding class",
slug: "coding-class",
description: "Let's learn how to code like a pro.",
lengthInMinutes: 60,
locations: [
{
type: "integration",
integration: "cal-video",
},
],
bookingFields: [
{
type: "select",
label: "select which language you want to learn",
slug: "select-language",
required: true,
placeholder: "select language",
options: ["javascript", "python", "cobol"],
},
],
scheduleId,
};

return request(app.getHttpServer())
.post("/api/v2/event-types")
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
.send(body)
.expect(404);
});

it("should create an event type", async () => {
const body: CreateEventTypeInput_2024_06_14 = {
title: "Coding class",
Expand Down Expand Up @@ -218,6 +267,18 @@ describe("Event types Endpoints", () => {
});
});

it("should not allow to update event type with scheduleId user does not own", async () => {
const body: UpdateEventTypeInput_2024_06_14 = {
scheduleId: falseTestSchedule.id,
};

return request(app.getHttpServer())
.patch(`/api/v2/event-types/${eventType.id}`)
.set(CAL_API_VERSION_HEADER, VERSION_2024_06_14)
.send(body)
.expect(404);
});

it(`/GET/:id`, async () => {
const response = await request(app.getHttpServer())
.get(`/api/v2/event-types/${eventType.id}`)
Expand Down Expand Up @@ -311,6 +372,11 @@ describe("Event types Endpoints", () => {
} catch (e) {
// User might have been deleted by the test
}
try {
await userRepositoryFixture.delete(falseTestUser.id);
} catch (e) {
// User might have been deleted by the test
}
await app.close();
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_20
import { EventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/event-types.service";
import { InputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/input-event-types.service";
import { OutputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/output-event-types.service";
import { SchedulesRepository_2024_06_11 } from "@/ee/schedules/schedules_2024_06_11/schedules.repository";
import { MembershipsModule } from "@/modules/memberships/memberships.module";
import { PrismaModule } from "@/modules/prisma/prisma.module";
import { SelectedCalendarsModule } from "@/modules/selected-calendars/selected-calendars.module";
Expand All @@ -20,6 +21,7 @@ import { Module } from "@nestjs/common";
OutputEventTypesService_2024_06_14,
UsersRepository,
UsersService,
SchedulesRepository_2024_06_11,
],
controllers: [EventTypesController_2024_06_14],
exports: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { DEFAULT_EVENT_TYPES } from "@/ee/event-types/event-types_2024_06_14/con
import { EventTypesRepository_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/event-types.repository";
import { InputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/input-event-types.service";
import { OutputEventTypesService_2024_06_14 } from "@/ee/event-types/event-types_2024_06_14/services/output-event-types.service";
import { SchedulesRepository_2024_06_11 } from "@/ee/schedules/schedules_2024_06_11/schedules.repository";
import { MembershipsRepository } from "@/modules/memberships/memberships.repository";
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
import { SelectedCalendarsRepository } from "@/modules/selected-calendars/selected-calendars.repository";
Expand Down Expand Up @@ -30,7 +31,8 @@ export class EventTypesService_2024_06_14 {
private readonly usersRepository: UsersRepository,
private readonly usersService: UsersService,
private readonly selectedCalendarsRepository: SelectedCalendarsRepository,
private readonly dbWrite: PrismaWriteService
private readonly dbWrite: PrismaWriteService,
private readonly schedulesRepository: SchedulesRepository_2024_06_11
) {}

async createUserEventType(user: UserWithProfile, body: CreateEventTypeInput_2024_06_14) {
Expand Down Expand Up @@ -61,6 +63,7 @@ export class EventTypesService_2024_06_14 {
if (existsWithSlug) {
throw new BadRequestException("User already has an event type with this slug.");
}
await this.checkUserOwnsSchedule(userId, body.scheduleId);
}

async getEventTypeByUsernameAndSlug(username: string, eventTypeSlug: string) {
Expand Down Expand Up @@ -203,7 +206,7 @@ export class EventTypesService_2024_06_14 {
}

async updateEventType(eventTypeId: number, body: UpdateEventTypeInput_2024_06_14, user: UserWithProfile) {
this.checkCanUpdateEventType(user.id, eventTypeId);
await this.checkCanUpdateEventType(user.id, eventTypeId, body.scheduleId);
const eventTypeUser = await this.getUserToUpdateEvent(user);
const bodyTransformed = this.inputEventTypesService.transformInputUpdateEventType(body);
await updateEventType({
Expand All @@ -225,12 +228,13 @@ export class EventTypesService_2024_06_14 {
return this.outputEventTypesService.getResponseEventType(user.id, eventType);
}

async checkCanUpdateEventType(userId: number, eventTypeId: number) {
async checkCanUpdateEventType(userId: number, eventTypeId: number, scheduleId: number | undefined) {
const existingEventType = await this.getUserEventType(userId, eventTypeId);
if (!existingEventType) {
throw new NotFoundException(`Event type with id ${eventTypeId} not found`);
}
this.checkUserOwnsEventType(userId, { id: eventTypeId, userId: existingEventType.ownerId });
await this.checkUserOwnsSchedule(userId, scheduleId);
}

async getUserToUpdateEvent(user: UserWithProfile) {
Expand All @@ -255,4 +259,16 @@ export class EventTypesService_2024_06_14 {
throw new ForbiddenException(`User with ID=${userId} does not own event type with ID=${eventType.id}`);
}
}

async checkUserOwnsSchedule(userId: number, scheduleId: number | null | undefined) {
if (!scheduleId) {
return;
}

const schedule = await this.schedulesRepository.getScheduleByIdAndUserId(scheduleId, userId);

if (!schedule) {
throw new NotFoundException(`User with ID=${userId} does not own schedule with ID=${scheduleId}`);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,17 @@ export class SchedulesRepository_2024_06_11 {
return schedule;
}

async getScheduleByIdAndUserId(scheduleId: number, userId: number) {
const schedule = await this.dbRead.prisma.schedule.findUnique({
where: {
id: scheduleId,
userId,
},
});

return schedule;
}

async updateSchedule(
userId: number,
scheduleId: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,7 @@ describe("Organizations Event Types Endpoints", () => {
await userRepositoryFixture.deleteByEmail(userAdmin.email);
await userRepositoryFixture.deleteByEmail(teammate1.email);
await userRepositoryFixture.deleteByEmail(teammate2.email);
await userRepositoryFixture.deleteByEmail(falseTestUser.email);
await teamsRepositoryFixture.delete(team.id);
await organizationsRepositoryFixture.delete(org.id);
await app.close();
Expand Down

0 comments on commit 2bdb93e

Please sign in to comment.