Skip to content

Commit 5bca163

Browse files
further fixes
1 parent 29160dc commit 5bca163

8 files changed

Lines changed: 59 additions & 28 deletions

File tree

apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) {
3636
} as const;
3737

3838
// Use centralized validation logic to avoid duplication
39-
const hashedLinkService = new HashedLinkService(prisma);
39+
const hashedLinkService = new HashedLinkService();
4040
const hashedLinkRepository = new HashedLinkRepository(prisma);
4141
try {
4242
await hashedLinkService.validate(link);

packages/features/bookings/lib/handleNewBooking.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2118,7 +2118,7 @@ async function handler(
21182118
}
21192119

21202120
try {
2121-
const hashedLinkService = new HashedLinkService(prisma);
2121+
const hashedLinkService = new HashedLinkService();
21222122
if (hasHashedBookingLink && reqBody.hashedLink && !isDryRun) {
21232123
await hashedLinkService.validateAndIncrementUsage(reqBody.hashedLink as string);
21242124
}

packages/lib/server/repository/hashedLinkRepository.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { prisma, type PrismaClient } from "@calcom/prisma";
1+
import type { PrismaClient } from "@calcom/prisma";
2+
import { prisma } from "@calcom/prisma";
23
import type { Prisma } from "@calcom/prisma/client";
34

45
export type HashedLinkInputType = {
@@ -80,7 +81,11 @@ export const hashedLinkSelect = {
8081
} satisfies Prisma.HashedLinkSelect;
8182

8283
export class HashedLinkRepository {
83-
constructor(private readonly prismaClient: PrismaClient = prisma) {}
84+
constructor(private readonly prismaClient: PrismaClient) {}
85+
86+
static create() {
87+
return new HashedLinkRepository(prisma);
88+
}
8489

8590
async deleteLinks(eventTypeId: number, linksToDelete: string[]) {
8691
if (linksToDelete.length === 0) return;

packages/lib/server/service/hashedLinkService.ts

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { ErrorCode } from "@calcom/lib/errorCodes";
22
import { validateHashedLinkData } from "@calcom/lib/hashedLinksUtils";
3-
import { prisma, type PrismaClient } from "@calcom/prisma";
43

54
import { HashedLinkRepository, type HashedLinkInputType } from "../repository/hashedLinkRepository";
5+
import { MembershipService } from "./membershipService";
66

77
type NormalizedLink = {
88
link: string;
@@ -11,11 +11,10 @@ type NormalizedLink = {
1111
};
1212

1313
export class HashedLinkService {
14-
private hashedLinkRepository: HashedLinkRepository;
15-
16-
constructor(private readonly prismaClient: PrismaClient = prisma) {
17-
this.hashedLinkRepository = new HashedLinkRepository(this.prismaClient);
18-
}
14+
constructor(
15+
private readonly hashedLinkRepository: HashedLinkRepository = HashedLinkRepository.create(),
16+
private readonly membershipService: MembershipService = new MembershipService()
17+
) {}
1918

2019
/**
2120
* Normalizes link input to a consistent format
@@ -145,18 +144,7 @@ export class HashedLinkService {
145144
return true;
146145
}
147146

148-
// Check team membership
149-
const membership = await this.prismaClient.membership.findFirst({
150-
where: {
151-
teamId: link.eventType.teamId,
152-
userId,
153-
accepted: true,
154-
},
155-
select: {
156-
id: true,
157-
},
158-
});
159-
147+
const membership = await this.membershipService.checkMembership(link.eventType.teamId, userId);
160148
return !!membership;
161149
}
162150
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { MembershipRole } from "@calcom/prisma/enums";
2+
3+
import { MembershipRepository } from "../repository/membership";
4+
5+
export type MembershipCheckResult = {
6+
isMember: boolean;
7+
isAdmin: boolean;
8+
isOwner: boolean;
9+
role?: MembershipRole;
10+
};
11+
12+
export class MembershipService {
13+
constructor(private readonly membershipRepository: MembershipRepository = new MembershipRepository()) {}
14+
15+
/**
16+
* Check if a user is a member of a team
17+
*/
18+
async checkMembership(teamId: number, userId: number): Promise<MembershipCheckResult> {
19+
const membership = await MembershipRepository.findUniqueByUserIdAndTeamId({ userId, teamId });
20+
21+
if (!membership || !membership.accepted) {
22+
return {
23+
isMember: false,
24+
isAdmin: false,
25+
isOwner: false,
26+
};
27+
}
28+
29+
return {
30+
isMember: true,
31+
isAdmin: membership.role === MembershipRole.ADMIN || membership.role === MembershipRole.OWNER,
32+
isOwner: membership.role === MembershipRole.OWNER,
33+
role: membership.role,
34+
};
35+
}
36+
}

packages/trpc/server/routers/viewer/eventTypes/getHashedLink.handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const getHashedLinkHandler = async ({ ctx, input }: GetHashedLinkOptions)
2525
});
2626
}
2727

28-
const hashedLinkRepository = new HashedLinkRepository(ctx.prisma);
28+
const hashedLinkRepository = HashedLinkRepository.create();
2929
// Get the hashed link with usage data
3030
const hashedLink = await hashedLinkRepository.findLinkWithEventTypeDetails(linkId);
3131

@@ -37,7 +37,7 @@ export const getHashedLinkHandler = async ({ ctx, input }: GetHashedLinkOptions)
3737
}
3838

3939
// Check if the user has permission to access this hashed link
40-
const hashedLinkService = new HashedLinkService(ctx.prisma);
40+
const hashedLinkService = new HashedLinkService();
4141
const hasPermission = await hashedLinkService.checkUserPermissionForLink(hashedLink, ctx.user.id);
4242

4343
if (!hasPermission) {

packages/trpc/server/routers/viewer/eventTypes/getHashedLinks.handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ export const getHashedLinksHandler = async ({ ctx, input }: GetHashedLinksOption
2121
}
2222

2323
// Get all hashed links with usage data
24-
const privateLinksRepo = new HashedLinkRepository(ctx.prisma);
24+
const privateLinksRepo = HashedLinkRepository.create();
2525
const hashedLinks = await privateLinksRepo.findLinksWithEventTypeDetails(linkIds);
2626

2727
// Check if the user has permission to access these hashed links
28-
const privateLinkService = new HashedLinkService(ctx.prisma);
28+
const privateLinkService = new HashedLinkService();
2929
const validLinks = await Promise.all(
3030
hashedLinks.map(async (link) => {
3131
const hasPermission = await privateLinkService.checkUserPermissionForLink(link, ctx.user.id);

packages/trpc/server/routers/viewer/eventTypes/update.handler.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,12 +494,14 @@ export const updateHandler = async ({ ctx, input }: UpdateOptions) => {
494494
break;
495495
}
496496
}
497+
console.log("multiplePrivateLinks", multiplePrivateLinks);
497498
// Handle multiple private links using the service
498-
const privateLinksRepo = new HashedLinkRepository(ctx.prisma);
499+
const privateLinksRepo = HashedLinkRepository.create();
499500
const connectedLinks = await privateLinksRepo.findLinksByEventTypeId(input.id);
501+
console.log("connectedLinks", connectedLinks);
500502
const connectedMultiplePrivateLinks = connectedLinks.map((link) => link.link);
501503

502-
const privateLinksService = new HashedLinkService(ctx.prisma);
504+
const privateLinksService = new HashedLinkService();
503505
await privateLinksService.handleMultiplePrivateLinks({
504506
eventTypeId: input.id,
505507
multiplePrivateLinks,

0 commit comments

Comments
 (0)