Merge pull request #130 from calcom/feat/dynamic-prisma
Feature: custom Prisma for self-hosted deployments needed for new hosted admin consolepull/9078/head
commit
d675535cdf
12
README.md
12
README.md
|
@ -180,7 +180,15 @@ See <https://github.com/vercel/next.js/blob/canary/packages/next/server/dev/hot-
|
|||
To remove this limitation, we need to ensure that on local endpoints are requested by swagger at /api/v1 and not /v1
|
||||
|
||||
|
||||
## Deployment
|
||||
## Hosted api through cal.com
|
||||
|
||||
Go to console.com
|
||||
Add a deployment or go to an existing one.
|
||||
Activate API or Admin addon
|
||||
Provide your DATABASE-URL
|
||||
Store it safely, you'll get a customApiID, save it.
|
||||
call api.cal.com?apiKey=your_cal_instance_apiKey&customApiId=cal_datasource_key
|
||||
## How to deploy
|
||||
|
||||
We recommend deploying API in vercel.
|
||||
|
||||
|
@ -194,4 +202,4 @@ OUTPUT DIRECTORY: `apps/api/.next`
|
|||
|
||||
See `scripts/vercel-deploy.sh` for more info on how the deployment is done.
|
||||
## Environment variables
|
||||
Lastly API requires an env var for `DATABASE_URL`
|
||||
Lastly API requires an env var for `DATABASE_URL`
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export const PRISMA_CLIENT_CACHING_TIME = 1000 * 60 * 60 * 24;
|
|
@ -0,0 +1,53 @@
|
|||
import { hash } from "bcryptjs";
|
||||
import cache from "memory-cache";
|
||||
import { NextMiddleware } from "next-api-middleware";
|
||||
|
||||
import { PRISMA_CLIENT_CACHING_TIME } from "@calcom/api/lib/constants";
|
||||
// import prismaAdmin from "@calcom/console/modules/common/utils/prisma";
|
||||
import { CONSOLE_URL } from "@calcom/lib/constants";
|
||||
import { prisma, customPrisma } from "@calcom/prisma";
|
||||
|
||||
// This replaces the prisma client for the cusotm one if the key is valid
|
||||
export const customPrismaClient: NextMiddleware = async (req, res, next) => {
|
||||
const {
|
||||
query: { key },
|
||||
}: { query: { key?: string } } = req;
|
||||
// If no custom api Id is provided, attach to request the regular cal.com prisma client.
|
||||
if (!key) {
|
||||
req.prisma = prisma;
|
||||
await next();
|
||||
} else {
|
||||
// If we have a key, we check if the deployment matching the key, has a databaseUrl value set.
|
||||
const databaseUrl = await fetch(
|
||||
`${process.env.NEXT_PUBLIC_CONSOLE_URL || CONSOLE_URL}/api/deployments/database?key=${key}`
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.then((res) => res.databaseUrl);
|
||||
|
||||
if (!databaseUrl) {
|
||||
res.status(400).json({ error: "no databaseUrl set up at your instance yet" });
|
||||
return;
|
||||
}
|
||||
// FIXME: Add some checks for the databaseUrl to make sure it is valid. (e.g. not a localhost)
|
||||
const hashedUrl = await hash(databaseUrl, 12);
|
||||
|
||||
const cachedPrisma = cache.get(hashedUrl);
|
||||
/* We cache each cusotm prisma client for 24h to avoid too many requests to the database. */
|
||||
if (!cachedPrisma) {
|
||||
cache.put(
|
||||
hashedUrl,
|
||||
customPrisma({ datasources: { db: { url: databaseUrl } } }),
|
||||
PRISMA_CLIENT_CACHING_TIME // Cache the prisma client for 24 hours
|
||||
);
|
||||
}
|
||||
req.prisma = customPrisma({ datasources: { db: { url: databaseUrl } } });
|
||||
/* @note:
|
||||
In order to skip verifyApiKey for customPrisma requests,
|
||||
we pass isAdmin true, and userId 0, if we detect them later,
|
||||
we skip verifyApiKey logic and pass onto next middleware instead.
|
||||
*/
|
||||
req.isAdmin = true;
|
||||
req.userId = 0;
|
||||
}
|
||||
await next();
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
import type { IncomingMessage } from "http";
|
||||
import { NextMiddleware } from "next-api-middleware";
|
||||
|
||||
import type { PrismaClient } from "@calcom/prisma/client";
|
||||
|
||||
/** @todo figure how to use the one from `@calcom/types` */
|
||||
/** @todo: remove once `@calcom/types` is updated with it.*/
|
||||
declare module "next" {
|
||||
export interface NextApiRequest extends IncomingMessage {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
body: any;
|
||||
userId: number;
|
||||
method: string;
|
||||
prisma: PrismaClient;
|
||||
session: { user: { id: number } };
|
||||
query: { [key: string]: string | string[] };
|
||||
isAdmin: boolean;
|
||||
}
|
||||
}
|
||||
export const extendRequest: NextMiddleware = async (req, res, next) => {
|
||||
await next();
|
||||
};
|
|
@ -1,24 +1,9 @@
|
|||
import type { IncomingMessage } from "http";
|
||||
import { NextMiddleware } from "next-api-middleware";
|
||||
|
||||
import { hashAPIKey } from "@calcom/ee/lib/api/apiKeys";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { isAdminGuard } from "@lib/utils/isAdmin";
|
||||
|
||||
/** @todo figure how to use the one from `@calcom/types`fi */
|
||||
/** @todo: remove once `@calcom/types` is updated with it.*/
|
||||
declare module "next" {
|
||||
export interface NextApiRequest extends IncomingMessage {
|
||||
userId: number;
|
||||
method: string;
|
||||
isAdmin: boolean;
|
||||
query: { [key: string]: string | string[] };
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
session: any;
|
||||
}
|
||||
}
|
||||
|
||||
// Used to check if the apiKey is not expired, could be extracted if reused. but not for now.
|
||||
export const dateNotInPast = function (date: Date) {
|
||||
const now = new Date();
|
||||
|
@ -29,23 +14,30 @@ export const dateNotInPast = function (date: Date) {
|
|||
|
||||
// This verifies the apiKey and sets the user if it is valid.
|
||||
export const verifyApiKey: NextMiddleware = async (req, res, next) => {
|
||||
const { prisma, userId, isAdmin } = req;
|
||||
// If the user is an admin and using a license key (from customPrisma), skip the apiKey check.
|
||||
if (userId === 0 && isAdmin) {
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
// Check if the apiKey query param is provided.
|
||||
if (!req.query.apiKey) return res.status(401).json({ message: "No apiKey provided" });
|
||||
// We remove the prefix from the user provided api_key. If no env set default to "cal_"
|
||||
// remove the prefix from the user provided api_key. If no env set default to "cal_"
|
||||
const strippedApiKey = `${req.query.apiKey}`.replace(process.env.API_KEY_PREFIX || "cal_", "");
|
||||
// Hash the key again before matching against the database records.
|
||||
const hashedKey = hashAPIKey(strippedApiKey);
|
||||
// Check if the hashed api key exists in database.
|
||||
const apiKey = await prisma.apiKey.findUnique({ where: { hashedKey } });
|
||||
// If we cannot find any api key. Throw a 401 Unauthorized.
|
||||
// If cannot find any api key. Throw a 401 Unauthorized.
|
||||
if (!apiKey) return res.status(401).json({ error: "Your apiKey is not valid" });
|
||||
if (apiKey.expiresAt && dateNotInPast(apiKey.expiresAt)) {
|
||||
return res.status(401).json({ error: "This apiKey is expired" });
|
||||
}
|
||||
if (!apiKey.userId) return res.status(404).json({ error: "No user found for this apiKey" });
|
||||
/* We save the user id in the request for later use */
|
||||
// save the user id in the request for later use
|
||||
req.userId = apiKey.userId;
|
||||
/* We save the isAdmin boolean here for later use */
|
||||
req.isAdmin = await isAdminGuard(req.userId);
|
||||
// save the isAdmin boolean here for later use
|
||||
req.isAdmin = await isAdminGuard(req.userId, prisma);
|
||||
|
||||
await next();
|
||||
};
|
||||
|
|
|
@ -2,6 +2,8 @@ import { label } from "next-api-middleware";
|
|||
|
||||
import { addRequestId } from "./addRequestid";
|
||||
import { captureErrors } from "./captureErrors";
|
||||
import { customPrismaClient } from "./customPrisma";
|
||||
import { extendRequest } from "./extendRequest";
|
||||
import {
|
||||
HTTP_POST,
|
||||
HTTP_DELETE,
|
||||
|
@ -22,9 +24,12 @@ const withMiddleware = label(
|
|||
HTTP_DELETE,
|
||||
addRequestId,
|
||||
verifyApiKey,
|
||||
customPrismaClient,
|
||||
extendRequest,
|
||||
sentry: captureErrors,
|
||||
},
|
||||
["sentry", "verifyApiKey", "addRequestId"] // <-- Provide a list of middleware to call automatically
|
||||
// The order here, determines the order of execution, put customPrismaClient before verifyApiKey always.
|
||||
["extendRequest", "sentry", "customPrismaClient", "verifyApiKey", "addRequestId"] // <-- Provide a list of middleware to call automatically
|
||||
);
|
||||
|
||||
export { withMiddleware };
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import { UserPermissionRole } from "@prisma/client";
|
||||
import { PrismaClient, UserPermissionRole } from "@prisma/client";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
export const isAdminGuard = async (userId: number) => {
|
||||
export const isAdminGuard = async (userId: number, prisma: PrismaClient) => {
|
||||
const user = await prisma.user.findUnique({ where: { id: userId } });
|
||||
return user?.role === UserPermissionRole.ADMIN;
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@ export type GetSubscriberOptions = {
|
|||
eventTypeId: number;
|
||||
triggerEvent: WebhookTriggerEvents;
|
||||
};
|
||||
|
||||
/** @note will this not work with custom prisma? since we're importing prisma directly and not passing it from request here **/
|
||||
const getWebhooks = async (options: GetSubscriberOptions) => {
|
||||
const { userId, eventTypeId } = options;
|
||||
const allWebhooks = await prisma.webhook.findMany({
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@calcom/tsconfig": "*",
|
||||
"@calcom/types": "*",
|
||||
"babel-jest": "^28.1.0",
|
||||
"jest": "^28.1.0",
|
||||
"node-mocks-http": "^1.11.0"
|
||||
|
@ -26,6 +27,8 @@
|
|||
"@calcom/app-store-cli": "*",
|
||||
"@calcom/prisma": "*",
|
||||
"@sentry/nextjs": "^6.19.7",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"memory-cache": "^0.2.0",
|
||||
"modify-response-middleware": "^1.1.0",
|
||||
"next": "^12.1.6",
|
||||
"next-api-middleware": "^1.0.1",
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { AttendeeResponse } from "@lib/types";
|
||||
import { schemaAttendeeEditBodyParams, schemaAttendeeReadPublic } from "@lib/validations/attendee";
|
||||
|
@ -11,7 +9,7 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export async function attendeeById(
|
||||
{ method, query, body, userId, isAdmin }: NextApiRequest,
|
||||
{ method, query, body, userId, isAdmin, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<AttendeeResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { AttendeeResponse, AttendeesResponse } from "@lib/types";
|
||||
import type { AttendeeResponse, AttendeesResponse } from "@lib/types";
|
||||
import { schemaAttendeeCreateBodyParams, schemaAttendeeReadPublic } from "@lib/validations/attendee";
|
||||
|
||||
async function createOrlistAllAttendees(
|
||||
{ method, userId, body, isAdmin }: NextApiRequest,
|
||||
{ method, userId, body, prisma, isAdmin }: NextApiRequest,
|
||||
res: NextApiResponse<AttendeesResponse | AttendeeResponse>
|
||||
) {
|
||||
let attendees;
|
||||
|
@ -138,13 +136,7 @@ async function createOrlistAllAttendees(
|
|||
attendee,
|
||||
message: "Attendee created successfully",
|
||||
});
|
||||
} else {
|
||||
(error: Error) =>
|
||||
res.status(400).json({
|
||||
message: "Could not create new attendee",
|
||||
error,
|
||||
});
|
||||
}
|
||||
} else (error: Error) => res.status(400).json({ error });
|
||||
}
|
||||
} else res.status(405).json({ message: `Method ${method} not allowed` });
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { AvailabilityResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -14,7 +12,7 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export async function availabilityById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<AvailabilityResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { AvailabilityResponse, AvailabilitiesResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -10,7 +8,7 @@ import {
|
|||
} from "@lib/validations/availability";
|
||||
|
||||
async function createOrlistAllAvailabilities(
|
||||
{ method, body, userId }: NextApiRequest,
|
||||
{ method, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<AvailabilitiesResponse | AvailabilityResponse>
|
||||
) {
|
||||
if (method === "GET") {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { BookingReferenceResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -14,7 +12,7 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export async function bookingReferenceById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<BookingReferenceResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
@ -64,7 +62,6 @@ export async function bookingReferenceById(
|
|||
.then((data) => schemaBookingReferenceReadPublic.parse(data))
|
||||
.then((booking_reference) => res.status(200).json({ booking_reference }))
|
||||
.catch((error: Error) => {
|
||||
console.log(error);
|
||||
res.status(404).json({
|
||||
message: `BookingReference with id: ${safeQuery.data.id} not found`,
|
||||
error,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { BookingReferenceResponse, BookingReferencesResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -10,7 +8,7 @@ import {
|
|||
} from "@lib/validations/booking-reference";
|
||||
|
||||
async function createOrlistAllBookingReferences(
|
||||
{ method, userId, body }: NextApiRequest,
|
||||
{ method, userId, body, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<BookingReferencesResponse | BookingReferenceResponse>
|
||||
) {
|
||||
const userWithBookings = await prisma.user.findUnique({
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { BookingResponse } from "@lib/types";
|
||||
import { schemaBookingEditBodyParams, schemaBookingReadPublic } from "@lib/validations/booking";
|
||||
|
@ -11,7 +9,7 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export async function bookingById(
|
||||
{ method, query, body, userId, isAdmin }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma, isAdmin }: NextApiRequest,
|
||||
res: NextApiResponse<BookingResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -2,8 +2,6 @@ import { WebhookTriggerEvents } from "@prisma/client";
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { BookingResponse, BookingsResponse } from "@lib/types";
|
||||
import sendPayload from "@lib/utils/sendPayload";
|
||||
|
@ -12,10 +10,9 @@ import { schemaBookingCreateBodyParams, schemaBookingReadPublic } from "@lib/val
|
|||
import { schemaEventTypeReadPublic } from "@lib/validations/event-type";
|
||||
|
||||
async function createOrlistAllBookings(
|
||||
{ method, body, userId, isAdmin }: NextApiRequest,
|
||||
{ method, body, userId, isAdmin, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<BookingsResponse | BookingResponse>
|
||||
) {
|
||||
console.log("userIduserId", userId);
|
||||
if (method === "GET") {
|
||||
/**
|
||||
* @swagger
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { EventTypeCustomInputResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -72,7 +70,7 @@ import {
|
|||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function eventTypeById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<EventTypeCustomInputResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { EventTypeCustomInputResponse, EventTypeCustomInputsResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -10,7 +8,7 @@ import {
|
|||
} from "@lib/validations/event-type-custom-input";
|
||||
|
||||
async function createOrlistAllEventTypeCustomInputs(
|
||||
{ userId, method, body }: NextApiRequest,
|
||||
{ userId, method, body, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<EventTypeCustomInputsResponse | EventTypeCustomInputResponse>
|
||||
) {
|
||||
const data = await prisma.eventType.findMany({ where: { userId } });
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { DestinationCalendarResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -14,7 +12,7 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export async function destionationCalendarById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<DestinationCalendarResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { DestinationCalendarResponse, DestinationCalendarsResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -10,7 +8,7 @@ import {
|
|||
} from "@lib/validations/destination-calendar";
|
||||
|
||||
async function createOrlistAllDestinationCalendars(
|
||||
{ method, body, userId }: NextApiRequest,
|
||||
{ method, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<DestinationCalendarsResponse | DestinationCalendarResponse>
|
||||
) {
|
||||
if (method === "GET") {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { DailyEventReferenceResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -14,7 +12,7 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export async function dailyEventReferenceById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<DailyEventReferenceResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { DailyEventReferenceResponse, DailyEventReferencesResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -10,7 +8,7 @@ import {
|
|||
} from "@lib/validations/event-reference";
|
||||
|
||||
async function createOrlistAllDailyEventReferences(
|
||||
{ method, body, userId }: NextApiRequest,
|
||||
{ method, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<DailyEventReferencesResponse | DailyEventReferenceResponse>
|
||||
) {
|
||||
const userBookings = await prisma.booking.findMany({ where: { userId } });
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { EventTypeResponse } from "@lib/types";
|
||||
import { schemaEventTypeEditBodyParams, schemaEventTypeReadPublic } from "@lib/validations/event-type";
|
||||
|
@ -11,7 +9,7 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export async function eventTypeById(
|
||||
{ method, query, body, userId, isAdmin }: NextApiRequest,
|
||||
{ method, query, body, userId, isAdmin, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<EventTypeResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { EventTypeResponse, EventTypesResponse } from "@lib/types";
|
||||
import { schemaEventTypeCreateBodyParams, schemaEventTypeReadPublic } from "@lib/validations/event-type";
|
||||
|
||||
async function createOrlistAllEventTypes(
|
||||
{ method, body, userId, isAdmin }: NextApiRequest,
|
||||
{ method, body, userId, isAdmin, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<EventTypesResponse | EventTypeResponse>
|
||||
) {
|
||||
if (method === "GET") {
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { WebhookResponse } from "@lib/types";
|
||||
import { schemaQueryIdAsString } from "@lib/validations/shared/queryIdString";
|
||||
import { schemaWebhookEditBodyParams, schemaWebhookReadPublic } from "@lib/validations/webhook";
|
||||
|
||||
export async function WebhookById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<WebhookResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdAsString.safeParse(query);
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { WebhookResponse, WebhooksResponse } from "@lib/types";
|
||||
import { schemaWebhookCreateBodyParams } from "@lib/validations/webhook";
|
||||
|
||||
async function createOrlistAllWebhooks(
|
||||
{ method, body, userId }: NextApiRequest,
|
||||
{ method, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<WebhooksResponse | WebhookResponse>
|
||||
) {
|
||||
if (method === "GET") {
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { MembershipResponse } from "@lib/types";
|
||||
import { schemaMembershipBodyParams, schemaMembershipPublic } from "@lib/validations/membership";
|
||||
import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString";
|
||||
|
||||
export async function membershipById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<MembershipResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdAsString.safeParse(query);
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { MembershipResponse, MembershipsResponse } from "@lib/types";
|
||||
import { schemaMembershipBodyParams, schemaMembershipPublic } from "@lib/validations/membership";
|
||||
|
||||
async function createOrlistAllMemberships(
|
||||
{ method, body, userId }: NextApiRequest,
|
||||
{ method, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<MembershipsResponse | MembershipResponse>
|
||||
) {
|
||||
if (method === "GET") {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { PaymentResponse } from "@lib/types";
|
||||
import { schemaPaymentPublic } from "@lib/validations/payment";
|
||||
|
@ -33,7 +31,7 @@ import {
|
|||
* description: Payment was not found
|
||||
*/
|
||||
export async function paymentById(
|
||||
{ method, query, userId }: NextApiRequest,
|
||||
{ method, query, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<PaymentResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { PaymentsResponse } from "@lib/types";
|
||||
import { schemaPaymentPublic } from "@lib/validations/payment";
|
||||
|
@ -21,7 +19,7 @@ import { schemaPaymentPublic } from "@lib/validations/payment";
|
|||
* 404:
|
||||
* description: No payments were found
|
||||
*/
|
||||
async function allPayments({ userId }: NextApiRequest, res: NextApiResponse<PaymentsResponse>) {
|
||||
async function allPayments({ userId, prisma }: NextApiRequest, res: NextApiResponse<PaymentsResponse>) {
|
||||
const userWithBookings = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
include: { bookings: true },
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { ScheduleResponse } from "@lib/types";
|
||||
import { schemaScheduleBodyParams, schemaSchedulePublic } from "@lib/validations/schedule";
|
||||
|
@ -11,7 +9,7 @@ import {
|
|||
} from "@lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
export async function scheduleById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<ScheduleResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { ScheduleResponse, SchedulesResponse } from "@lib/types";
|
||||
import { schemaScheduleBodyParams, schemaSchedulePublic } from "@lib/validations/schedule";
|
||||
|
||||
async function createOrlistAllSchedules(
|
||||
{ method, body, userId }: NextApiRequest,
|
||||
{ method, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<SchedulesResponse | ScheduleResponse>
|
||||
) {
|
||||
if (method === "GET") {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { SelectedCalendarResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -11,7 +9,7 @@ import {
|
|||
import { schemaQueryIdAsString, withValidQueryIdString } from "@lib/validations/shared/queryIdString";
|
||||
|
||||
export async function selectedCalendarById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<SelectedCalendarResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdAsString.safeParse(query);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { SelectedCalendarResponse, SelectedCalendarsResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -10,7 +8,7 @@ import {
|
|||
} from "@lib/validations/selected-calendar";
|
||||
|
||||
async function createOrlistAllSelectedCalendars(
|
||||
{ method, body, userId }: NextApiRequest,
|
||||
{ method, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<SelectedCalendarsResponse | SelectedCalendarResponse>
|
||||
) {
|
||||
if (method === "GET") {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import type { TeamResponse } from "@lib/types";
|
||||
import {
|
||||
|
@ -72,7 +70,7 @@ import { schemaTeamBodyParams, schemaTeamPublic } from "@lib/validations/team";
|
|||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function teamById(
|
||||
{ method, query, body, userId }: NextApiRequest,
|
||||
{ method, query, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<TeamResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "@lib/helpers/withMiddleware";
|
||||
import { TeamResponse, TeamsResponse } from "@lib/types";
|
||||
import { schemaMembershipPublic } from "@lib/validations/membership";
|
||||
import { schemaTeamBodyParams, schemaTeamPublic } from "@lib/validations/team";
|
||||
|
||||
async function createOrlistAllTeams(
|
||||
{ method, body, userId }: NextApiRequest,
|
||||
{ method, body, userId, prisma }: NextApiRequest,
|
||||
res: NextApiResponse<TeamsResponse | TeamResponse>
|
||||
) {
|
||||
if (method === "GET") {
|
||||
|
|
|
@ -33,7 +33,7 @@ import { schemaQueryUserId } from "@lib/validations/shared/queryUserId";
|
|||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const query = schemaQueryUserId.parse(req.query);
|
||||
const isAdmin = await isAdminGuard(req.userId);
|
||||
const isAdmin = await isAdminGuard(req.userId, req.prisma);
|
||||
// Here we only check for ownership of the user if the user is not admin, otherwise we let ADMIN's edit any user
|
||||
if (!isAdmin && query.userId !== req.userId)
|
||||
throw new HttpError({ statusCode: 401, message: "Unauthorized" });
|
||||
|
|
|
@ -34,7 +34,7 @@ import { schemaUserReadPublic } from "@lib/validations/user";
|
|||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const query = schemaQueryUserId.parse(req.query);
|
||||
const isAdmin = await isAdminGuard(req.userId);
|
||||
const isAdmin = await isAdminGuard(req.userId, req.prisma);
|
||||
// Here we only check for ownership of the user if the user is not admin, otherwise we let ADMIN's edit any user
|
||||
if (!isAdmin && query.userId !== req.userId)
|
||||
throw new HttpError({ statusCode: 401, message: "Unauthorized" });
|
||||
|
|
|
@ -55,7 +55,7 @@ import { schemaUserEditBodyParams, schemaUserReadPublic } from "@lib/validations
|
|||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const query = schemaQueryUserId.parse(req.query);
|
||||
const isAdmin = await isAdminGuard(req.userId);
|
||||
const isAdmin = await isAdminGuard(req.userId, req.prisma);
|
||||
// Here we only check for ownership of the user if the user is not admin, otherwise we let ADMIN's edit any user
|
||||
if (!isAdmin && query.userId !== req.userId)
|
||||
throw new HttpError({ statusCode: 401, message: "Unauthorized" });
|
||||
|
|
|
@ -24,8 +24,8 @@ import { Prisma } from ".prisma/client";
|
|||
* 404:
|
||||
* description: No users were found
|
||||
*/
|
||||
async function getHandler({ userId }: NextApiRequest) {
|
||||
const isAdmin = await isAdminGuard(userId);
|
||||
async function getHandler({ userId, prisma }: NextApiRequest) {
|
||||
const isAdmin = await isAdminGuard(userId, prisma);
|
||||
const where: Prisma.UserWhereInput = {};
|
||||
// If user is not ADMIN, return only his data.
|
||||
if (!isAdmin) where.id = userId;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { isAdminGuard } from "@lib/utils/isAdmin";
|
|||
import { schemaUserCreateBodyParams } from "@lib/validations/user";
|
||||
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const isAdmin = await isAdminGuard(req.userId);
|
||||
const isAdmin = await isAdminGuard(req.userId, req.prisma);
|
||||
// If user is not ADMIN, return unauthorized.
|
||||
if (!isAdmin) throw new HttpError({ statusCode: 401, message: "You are not authorized" });
|
||||
const data = schemaUserCreateBodyParams.parse(req.body);
|
||||
|
|
Loading…
Reference in New Issue