Skip to content

Commit 94f45b1

Browse files
committed
Use repositories and declarative installation ocode for app
1 parent 4d164ab commit 94f45b1

File tree

6 files changed

+93
-64
lines changed

6 files changed

+93
-64
lines changed
Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,19 @@
1-
import type { NextApiRequest, NextApiResponse } from "next";
2-
3-
import prisma from "@calcom/prisma";
1+
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
42

3+
import { createDefaultInstallation } from "../../_utils/installation";
54
import appConfig from "../config.json";
65

7-
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
8-
if (!req.session?.user?.id) {
9-
return res.status(401).json({ message: "You must be logged in to do this" });
10-
}
11-
try {
12-
const alreadyInstalled = await prisma.credential.findFirst({
13-
where: {
14-
type: appConfig.type,
15-
userId: req.session.user.id,
16-
},
17-
select: { id: true },
18-
});
19-
if (alreadyInstalled) {
20-
throw new Error("Already installed");
21-
}
22-
const installation = await prisma.credential.create({
23-
data: {
24-
type: appConfig.type,
25-
key: {},
26-
userId: req.session.user.id,
27-
appId: appConfig.slug,
28-
},
29-
});
30-
if (!installation) {
31-
throw new Error("Unable to create user credential for BTCPay server");
32-
}
33-
} catch (error: unknown) {
34-
if (error instanceof Error) {
35-
return res.status(500).json({ message: error.message });
36-
}
37-
return res.status(500);
38-
}
39-
return res.status(200).json({ url: "/apps/btcpayserver/setup" });
40-
}
6+
const handler: AppDeclarativeHandler = {
7+
appType: appConfig.type,
8+
variant: appConfig.variant,
9+
slug: appConfig.slug,
10+
supportsMultipleInstalls: false,
11+
handlerType: "add",
12+
redirect: {
13+
url: "/apps/btcpayserver/setup",
14+
},
15+
createCredential: ({ appType, user, slug, teamId }) =>
16+
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
17+
};
18+
19+
export default handler;

packages/app-store/btcpayserver/api/webhook.ts

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { IS_PRODUCTION } from "@calcom/lib/constants";
77
import { getErrorFromUnknown } from "@calcom/lib/errors";
88
import { HttpError as HttpCode } from "@calcom/lib/http-error";
99
import { handlePaymentSuccess } from "@calcom/lib/payment/handlePaymentSuccess";
10-
import prisma from "@calcom/prisma";
10+
import { PrismaBookingPaymentRepository as BookingPaymentRepository } from "@calcom/lib/server/repository/PrismaBookingPaymentRepository";
1111

1212
import appConfig from "../config.json";
1313
import { btcpayCredentialKeysSchema } from "../lib/btcpayCredentialKeysSchema";
@@ -46,26 +46,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
4646
if (!SUPPORTED_INVOICE_EVENTS.includes(data.type))
4747
return res.status(200).send({ message: "Webhook received but ignored" });
4848

49-
const payment = await prisma.payment.findFirst({
50-
where: {
51-
externalId: data.invoiceId,
52-
},
53-
select: {
54-
id: true,
55-
amount: true,
56-
success: true,
57-
bookingId: true,
58-
booking: {
59-
select: {
60-
user: {
61-
select: {
62-
credentials: { where: { type: appConfig.type } },
63-
},
64-
},
65-
},
66-
},
67-
},
68-
});
49+
const bookingPaymentRepository = new BookingPaymentRepository();
50+
const payment = await bookingPaymentRepository.findByExternalIdIncludeBookingUserCredentials(
51+
data.invoiceId,
52+
appConfig.type
53+
);
6954
if (!payment) throw new HttpCode({ statusCode: 404, message: "Cal.com: payment not found" });
7055
if (payment.success) return res.status(400).send({ message: "Payment already registered" });
7156
const key = payment.booking?.user?.credentials?.[0].key;

packages/app-store/btcpayserver/pages/setup/_getServerSideProps.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { GetServerSidePropsContext } from "next";
22

33
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
4-
import prisma from "@calcom/prisma";
4+
import { CredentialRepository } from "@calcom/lib/server/repository/credential";
55

66
import { btcpayCredentialKeysSchema } from "../../lib/btcpayCredentialKeysSchema";
77
import type { IBTCPaySetupProps } from "./index";
@@ -15,11 +15,9 @@ export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
1515
const session = await getServerSession({ req });
1616
if (!session?.user?.id) return { redirect: { permanent: false, destination: "/auth/login" } };
1717

18-
const credential = await prisma.credential.findFirst({
19-
where: {
20-
type: "btcpayserver_payment",
21-
userId: session?.user.id,
22-
},
18+
const credential = await CredentialRepository.findFirstByUserIdAndType({
19+
userId: session.user.id,
20+
type: "btcpayserver_payment",
2321
});
2422

2523
let props: IBTCPaySetupProps | undefined;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import type { JsonValue } from "@calcom/types/Json";
2+
3+
export interface BookingPaymentWithCredentials {
4+
id: number;
5+
amount: number;
6+
success: boolean;
7+
bookingId: number;
8+
booking: {
9+
user: {
10+
credentials: Array<{
11+
key: JsonValue;
12+
}>;
13+
} | null;
14+
} | null;
15+
}
16+
17+
export interface IBookingPaymentRepository {
18+
findByExternalIdIncludeBookingUserCredentials(
19+
externalId: string,
20+
credentialType: string
21+
): Promise<BookingPaymentWithCredentials | null>;
22+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { PrismaClient } from "@calcom/prisma";
2+
import prisma from "@calcom/prisma";
3+
4+
import type {
5+
IBookingPaymentRepository,
6+
BookingPaymentWithCredentials,
7+
} from "./BookingPaymentRepository.interface";
8+
9+
export class PrismaBookingPaymentRepository implements IBookingPaymentRepository {
10+
constructor(private readonly prismaClient: PrismaClient = prisma) {}
11+
12+
async findByExternalIdIncludeBookingUserCredentials(
13+
externalId: string,
14+
credentialType: string
15+
): Promise<BookingPaymentWithCredentials | null> {
16+
return await this.prismaClient.payment.findFirst({
17+
where: {
18+
externalId,
19+
},
20+
select: {
21+
id: true,
22+
amount: true,
23+
success: true,
24+
bookingId: true,
25+
booking: {
26+
select: {
27+
user: {
28+
select: {
29+
credentials: {
30+
where: { type: credentialType },
31+
select: { key: true },
32+
},
33+
},
34+
},
35+
},
36+
},
37+
},
38+
});
39+
}
40+
}

packages/types/Json.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export declare type JsonObject = {
2+
[Key in string]?: JsonValue;
3+
};
4+
export type JsonArray = Array<JsonValue>;
5+
export type JsonValue = string | number | boolean | JsonObject | JsonArray | null;

0 commit comments

Comments
 (0)