@@ -329,6 +439,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
eventName: true,
requiresConfirmation: true,
userId: true,
+ successRedirectUrl: true,
users: {
select: {
name: true,
diff --git a/apps/web/playwright/booking-pages.test.ts b/apps/web/playwright/booking-pages.test.ts
index d60cce0594..4fb038e4bb 100644
--- a/apps/web/playwright/booking-pages.test.ts
+++ b/apps/web/playwright/booking-pages.test.ts
@@ -151,7 +151,7 @@ test.describe("pro user", () => {
await bookFirstEvent(page);
await page.goto("/bookings/upcoming");
- await page.locator('[data-testid="cancel"]').click();
+ await page.locator('[data-testid="cancel"]').first().click();
await page.waitForNavigation({
url: (url) => {
return url.pathname.startsWith("/cancel");
diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json
index bc212f9d19..c0dac6fc2f 100644
--- a/apps/web/public/static/locales/en/common.json
+++ b/apps/web/public/static/locales/en/common.json
@@ -710,6 +710,9 @@
"time_format": "Time format",
"12_hour": "12 hour",
"24_hour": "24 hour",
+ "redirect_success_booking": "Redirect on booking ",
+ "external_redirect_url": "External Redirect URL - Starts with https://",
+ "redirect_url_upgrade_description": "In order to use this feature, you need to upgrade to a Pro account.",
"duplicate": "Duplicate",
"you_can_manage_your_schedules": "You can manage your schedules on the Availability page."
}
diff --git a/apps/web/server/routers/viewer.tsx b/apps/web/server/routers/viewer.tsx
index 58b97ff114..72c71991b8 100644
--- a/apps/web/server/routers/viewer.tsx
+++ b/apps/web/server/routers/viewer.tsx
@@ -131,6 +131,7 @@ const loggedInViewerRouter = createProtectedRouter()
price: true,
currency: true,
position: true,
+ successRedirectUrl: true,
users: {
select: {
id: true,
diff --git a/apps/web/server/routers/viewer/eventTypes.tsx b/apps/web/server/routers/viewer/eventTypes.tsx
index b7923198ed..2c84949d04 100644
--- a/apps/web/server/routers/viewer/eventTypes.tsx
+++ b/apps/web/server/routers/viewer/eventTypes.tsx
@@ -18,6 +18,22 @@ function isPeriodType(keyInput: string): keyInput is PeriodType {
return Object.keys(PeriodType).includes(keyInput);
}
+/**
+ * Ensures that it is a valid HTTP URL
+ * It automatically avoids
+ * - XSS attempts through javascript:alert('hi')
+ * - mailto: links
+ */
+function assertValidUrl(url: string | null | undefined) {
+ if (!url) {
+ return;
+ }
+
+ if (!url.startsWith("http://") && !url.startsWith("https://")) {
+ throw new TRPCError({ code: "PARSE_ERROR", message: "Invalid URL" });
+ }
+}
+
function handlePeriodType(periodType: string | undefined): PeriodType | undefined {
if (typeof periodType !== "string") return undefined;
const passedPeriodType = periodType.toUpperCase();
@@ -97,7 +113,6 @@ export const eventTypesRouter = createProtectedRouter()
input: createEventTypeInput,
async resolve({ ctx, input }) {
const { schedulingType, teamId, ...rest } = input;
-
const userId = ctx.user.id;
const data: Prisma.EventTypeCreateInput = {
@@ -181,9 +196,9 @@ export const eventTypesRouter = createProtectedRouter()
async resolve({ ctx, input }) {
const { schedule, periodType, locations, destinationCalendar, customInputs, users, id, ...rest } =
input;
+ assertValidUrl(input.successRedirectUrl);
const data: Prisma.EventTypeUpdateInput = rest;
data.locations = locations ?? undefined;
-
if (periodType) {
data.periodType = handlePeriodType(periodType);
}
@@ -211,7 +226,7 @@ export const eventTypesRouter = createProtectedRouter()
if (users) {
data.users = {
set: [],
- connect: users.map((userId) => ({ id: userId })),
+ connect: users.map((userId: number) => ({ id: userId })),
};
}
diff --git a/packages/prisma/migrations/20220404132522_redirect_url/migration.sql b/packages/prisma/migrations/20220404132522_redirect_url/migration.sql
new file mode 100644
index 0000000000..e6ebdedf52
--- /dev/null
+++ b/packages/prisma/migrations/20220404132522_redirect_url/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "EventType" ADD COLUMN "successRedirectUrl" TEXT;
diff --git a/packages/prisma/schema.prisma b/packages/prisma/schema.prisma
index 6bcf9e3087..217f9b7ee5 100644
--- a/packages/prisma/schema.prisma
+++ b/packages/prisma/schema.prisma
@@ -68,6 +68,7 @@ model EventType {
currency String @default("usd")
slotInterval Int?
metadata Json?
+ successRedirectUrl String?
@@unique([userId, slug])
}