Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c2d1bff2b | ||
|
|
7a790aaabe | ||
|
|
8fe8beb686 | ||
|
|
71b0dd2aa3 | ||
|
|
28c793c3fe | ||
|
|
af6899d122 | ||
|
|
f4baf88ed5 | ||
|
|
09ca75eb1f | ||
|
|
3aff79e7d1 | ||
|
|
a7405db0d4 | ||
|
|
802fbdf491 | ||
|
|
2803b5072c | ||
|
|
502a3241e4 | ||
|
|
a4bc0793d7 | ||
|
|
4af209fc9d | ||
|
|
76b33165e5 | ||
|
|
5109075494 | ||
|
|
52791599e1 | ||
|
|
54db9a42a9 | ||
|
|
ce204d7a98 | ||
|
|
44170b267f | ||
|
|
cb30e5f1e0 | ||
|
|
d6d2aae67f | ||
|
|
b06e46342c | ||
|
|
4cf482f860 | ||
|
|
f2478ea7d3 | ||
|
|
0e110022fb | ||
|
|
ee80577cc3 | ||
|
|
8402dfa3a2 | ||
|
|
4585199b5e | ||
|
|
ae2446f42f | ||
|
|
2f6d109a70 | ||
|
|
7ff884ca7d | ||
|
|
9230b2d2ca | ||
|
|
1a645f3110 | ||
|
|
4eb11e76ea | ||
|
|
e3a5ce5f6e | ||
|
|
12e171823b | ||
|
|
3c723d6f5b | ||
|
|
1482d9a9af | ||
|
|
0efe25feb4 | ||
|
|
602192e026 | ||
|
|
aeb54e6401 | ||
|
|
b8c1d623f3 | ||
|
|
30e4d769e3 | ||
|
|
3babfa7cf3 | ||
|
|
e45ee8fab3 | ||
|
|
3c96e122b4 | ||
|
|
f21a915814 | ||
|
|
3467e2272f | ||
|
|
844592e15e | ||
|
|
bdacb18d5c | ||
|
|
1b5d50c45c | ||
|
|
1c39dbad3d | ||
|
|
e60454750e | ||
|
|
286f696302 | ||
|
|
8deaea3edd | ||
|
|
7d497a621f | ||
|
|
5c8e0483b1 | ||
|
|
3cefa94a94 | ||
|
|
30549d5c14 | ||
|
|
b87972399e | ||
|
|
0784df6a31 | ||
|
|
fc062878ed | ||
|
|
33c1d80a42 | ||
|
|
1064e1181d | ||
|
|
dfd683ffc4 | ||
|
|
0972307998 | ||
|
|
157f633ef2 | ||
|
|
cc1c3b210a | ||
|
|
fcfd47e7d2 | ||
|
|
284c4c9084 | ||
|
|
9fd3594f6c | ||
|
|
531371bf55 | ||
|
|
99fd4fe7a4 | ||
|
|
a677d0d2c4 | ||
|
|
d8cee20d0c | ||
|
|
a7ce12e22f | ||
|
|
88b67a8121 | ||
|
|
7e2a1a23b9 | ||
|
|
a115a3458e | ||
|
|
ae503acccc | ||
|
|
61e7c89f36 | ||
|
|
60ba7a5ca2 | ||
|
|
bfa718e193 | ||
|
|
b29a52d0b0 | ||
|
|
c21d9d08ab | ||
|
|
615e1dcfe8 | ||
|
|
a24f9b76f6 | ||
|
|
62f8ac1c6d | ||
|
|
09b91d5a7e | ||
|
|
01ac2e640a | ||
|
|
e39bf37f91 | ||
|
|
1f845944ac | ||
|
|
7f53db601d | ||
|
|
1cc9f1d25d | ||
|
|
c6ee482478 | ||
|
|
5292dd2e66 | ||
|
|
f59d62f03c | ||
|
|
cb02268e7f | ||
|
|
e33453c50d | ||
|
|
15ffeec745 | ||
|
|
b7252ed79c | ||
|
|
9b04df9bbe | ||
|
|
657be16a4e | ||
|
|
b0afb15939 | ||
|
|
3a9b8a9bf6 | ||
|
|
92a919069d | ||
|
|
0071d16575 | ||
|
|
23d22ee7ea | ||
|
|
3a4f944aac | ||
|
|
3eadae0aad | ||
|
|
0cc2fe2d7f | ||
|
|
0970c77009 | ||
|
|
5b733765f4 | ||
|
|
83fe4d6625 | ||
|
|
91beeeb525 | ||
|
|
81c0b1ffe9 | ||
|
|
aedc88f975 | ||
|
|
67256b5b6e | ||
|
|
ef02d64f90 | ||
|
|
8685862617 | ||
|
|
7422488b5d | ||
|
|
c3e1481d6a | ||
|
|
a1d1883b34 | ||
|
|
f2ae94a190 | ||
|
|
b82a597645 | ||
|
|
5ba0ee8e85 | ||
|
|
1463f97f14 | ||
|
|
34fea35e83 | ||
|
|
2d75048037 | ||
|
|
b549735334 | ||
|
|
86c379817e | ||
|
|
5d1976295c | ||
|
|
e9b1fa1f50 | ||
|
|
80080dda7a | ||
|
|
27c25e1f95 | ||
|
|
858be0f5d8 | ||
|
|
68d0090f50 | ||
|
|
a43fa13b11 | ||
|
|
2bf6da30b3 | ||
|
|
d85e0b51e4 | ||
|
|
55a317d677 | ||
|
|
5fff8fc58c | ||
|
|
0d68767d0a | ||
|
|
2051e87436 | ||
|
|
77a157a12b | ||
|
|
c4f25f2c44 | ||
|
|
d967facb63 | ||
|
|
c6dad39fb0 | ||
|
|
eec7f4d7d4 | ||
|
|
95d5824ba9 | ||
|
|
5f95a4d041 | ||
|
|
8e97444129 | ||
|
|
8d8264b5f5 | ||
|
|
2ad81221d0 | ||
|
|
3d1ac4523f | ||
|
|
b38807cb0f | ||
|
|
11fb387370 | ||
|
|
1546f9115d | ||
|
|
40ecd5dd9d | ||
|
|
ac6ac14a23 | ||
|
|
c6534160e4 | ||
|
|
aa2db562b8 | ||
|
|
b7ed314be2 | ||
|
|
d102268b33 | ||
|
|
f4397d6593 | ||
|
|
192603a1fa | ||
|
|
a3d969680f | ||
|
|
adc3b3aec6 | ||
|
|
92286e2453 | ||
|
|
51b2a15cb0 | ||
|
|
fa9a099dd6 | ||
|
|
83ceb46cca |
+3
-2
@@ -232,6 +232,7 @@ NEXT_PUBLIC_COMPANY_NAME="Cal.com, Inc."
|
||||
# NEXT_PUBLIC_DISABLE_SIGNUP=true
|
||||
NEXT_PUBLIC_DISABLE_SIGNUP=
|
||||
|
||||
# Set this to 'non-strict' to enable CSP for support pages. 'strict' isn't supported yet. Also, check the README for details.
|
||||
# Content Security Policy
|
||||
CSP_POLICY=
|
||||
|
||||
@@ -294,9 +295,9 @@ E2E_TEST_CALCOM_GCAL_KEYS=
|
||||
# Used for self-hosters that are implementing Cal.com into their applications that already have certain integrations
|
||||
# Under settings/admin/apps ensure that all app secrets are set the same as the parent application
|
||||
# You can use: `openssl rand -base64 32` to generate one
|
||||
CALCOM_WEBHOOK_SECRET=""
|
||||
CALCOM_CREDENTIAL_SYNC_SECRET=""
|
||||
# This is the header name that will be used to verify the webhook secret. Should be in lowercase
|
||||
CALCOM_WEBHOOK_HEADER_NAME="calcom-webhook-secret"
|
||||
CALCOM_CREDENTIAL_SYNC_HEADER_NAME="calcom-credential-sync-secret"
|
||||
CALCOM_CREDENTIAL_SYNC_ENDPOINT=""
|
||||
# Key should match on Cal.com and your application
|
||||
# must be 24 bytes for AES256 encryption algorithm
|
||||
|
||||
@@ -13,7 +13,7 @@ Fixes # (issue)
|
||||
<!-- Please provide all documents that are important to understand the reason of that PR. -->
|
||||
|
||||
- If there is a requirement document, please, share it here.
|
||||
- If there is ab UI/UX design document, please, share it here.
|
||||
- If there is a UI/UX design document, please, share it here.
|
||||
|
||||
## Type of change
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
name: Manually Delete BuildJet Cache
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
cache_key:
|
||||
description: "BuildJet Cache Key to Delete"
|
||||
required: true
|
||||
type: string
|
||||
jobs:
|
||||
manually-delete-buildjet-cache:
|
||||
runs-on: buildjet-2vcpu-ubuntu-2204
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- uses: buildjet/cache-delete@v1
|
||||
with:
|
||||
cache_key: ${{ inputs.cache_key }}
|
||||
+63
-57
@@ -1,5 +1,6 @@
|
||||
import { ChatPromptTemplate } from "@langchain/core/prompts";
|
||||
import { ChatOpenAI } from "@langchain/openai";
|
||||
import { initializeAgentExecutorWithOptions } from "langchain/agents";
|
||||
import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents";
|
||||
|
||||
import { env } from "../env.mjs";
|
||||
import createBookingIfAvailable from "../tools/createBooking";
|
||||
@@ -47,67 +48,72 @@ const agent = async (
|
||||
/**
|
||||
* Initialize the agent executor with arguments.
|
||||
*/
|
||||
const executor = await initializeAgentExecutorWithOptions(tools, model, {
|
||||
agentArgs: {
|
||||
prefix: `You are Cal.ai - a bleeding edge scheduling assistant that interfaces via email.
|
||||
Make sure your final answers are definitive, complete and well formatted.
|
||||
Sometimes, tools return errors. In this case, try to handle the error intelligently or ask the user for more information.
|
||||
Tools will always handle times in UTC, but times sent to users should be formatted per that user's timezone.
|
||||
In responses to users, always summarize necessary context and open the door to follow ups. For example "I have booked your chat with @username for 3pm on Wednesday, December 20th, 2023 EST. Please let me know if you need to reschedule."
|
||||
If you can't find a referenced user, ask the user for their email or @username. Make sure to specify that usernames require the @username format. Users don't know other users' userIds.
|
||||
const prompt =
|
||||
ChatPromptTemplate.fromTemplate(`You are Cal.ai - a bleeding edge scheduling assistant that interfaces via email.
|
||||
Make sure your final answers are definitive, complete and well formatted.
|
||||
Sometimes, tools return errors. In this case, try to handle the error intelligently or ask the user for more information.
|
||||
Tools will always handle times in UTC, but times sent to users should be formatted per that user's timezone.
|
||||
In responses to users, always summarize necessary context and open the door to follow ups. For example "I have booked your chat with @username for 3pm on Wednesday, December 20th, 2023 EST. Please let me know if you need to reschedule."
|
||||
If you can't find a referenced user, ask the user for their email or @username. Make sure to specify that usernames require the @username format. Users don't know other users' userIds.
|
||||
|
||||
The primary user's id is: ${userId}
|
||||
The primary user's username is: ${user.username}
|
||||
The current time in the primary user's timezone is: ${now(user.timeZone, {
|
||||
weekday: "long",
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
})}
|
||||
The primary user's time zone is: ${user.timeZone}
|
||||
The primary user's event types are: ${user.eventTypes
|
||||
.map((e: EventType) => `ID: ${e.id}, Slug: ${e.slug}, Title: ${e.title}, Length: ${e.length};`)
|
||||
.join("\n")}
|
||||
The primary user's working hours are: ${user.workingHours
|
||||
.map(
|
||||
(w: WorkingHours) =>
|
||||
`Days: ${w.days.join(", ")}, Start Time (minutes in UTC): ${
|
||||
w.startTime
|
||||
}, End Time (minutes in UTC): ${w.endTime};`
|
||||
)
|
||||
.join("\n")}
|
||||
${
|
||||
users.length
|
||||
? `The email references the following @usernames and emails: ${users
|
||||
.map(
|
||||
(u) =>
|
||||
`${
|
||||
(u.id ? `, id: ${u.id}` : "id: (non user)") +
|
||||
(u.username
|
||||
? u.type === "fromUsername"
|
||||
? `, username: @${u.username}`
|
||||
: ", username: REDACTED"
|
||||
: ", (no username)") +
|
||||
(u.email
|
||||
? u.type === "fromEmail"
|
||||
? `, email: ${u.email}`
|
||||
: ", email: REDACTED"
|
||||
: ", (no email)")
|
||||
};`
|
||||
)
|
||||
.join("\n")}`
|
||||
: ""
|
||||
}`);
|
||||
const agent = await createOpenAIFunctionsAgent({
|
||||
llm: model,
|
||||
prompt,
|
||||
tools,
|
||||
});
|
||||
|
||||
The primary user's id is: ${userId}
|
||||
The primary user's username is: ${user.username}
|
||||
The current time in the primary user's timezone is: ${now(user.timeZone, {
|
||||
weekday: "long",
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
})}
|
||||
The primary user's time zone is: ${user.timeZone}
|
||||
The primary user's event types are: ${user.eventTypes
|
||||
.map((e: EventType) => `ID: ${e.id}, Slug: ${e.slug}, Title: ${e.title}, Length: ${e.length};`)
|
||||
.join("\n")}
|
||||
The primary user's working hours are: ${user.workingHours
|
||||
.map(
|
||||
(w: WorkingHours) =>
|
||||
`Days: ${w.days.join(", ")}, Start Time (minutes in UTC): ${
|
||||
w.startTime
|
||||
}, End Time (minutes in UTC): ${w.endTime};`
|
||||
)
|
||||
.join("\n")}
|
||||
${
|
||||
users.length
|
||||
? `The email references the following @usernames and emails: ${users
|
||||
.map(
|
||||
(u) =>
|
||||
`${
|
||||
(u.id ? `, id: ${u.id}` : "id: (non user)") +
|
||||
(u.username
|
||||
? u.type === "fromUsername"
|
||||
? `, username: @${u.username}`
|
||||
: ", username: REDACTED"
|
||||
: ", (no username)") +
|
||||
(u.email
|
||||
? u.type === "fromEmail"
|
||||
? `, email: ${u.email}`
|
||||
: ", email: REDACTED"
|
||||
: ", (no email)")
|
||||
};`
|
||||
)
|
||||
.join("\n")}`
|
||||
: ""
|
||||
}
|
||||
`,
|
||||
},
|
||||
agentType: "openai-functions",
|
||||
const executor = new AgentExecutor({
|
||||
agent,
|
||||
tools,
|
||||
returnIntermediateSteps: env.NODE_ENV === "development",
|
||||
verbose: env.NODE_ENV === "development",
|
||||
});
|
||||
|
||||
const result = await executor.call({ input });
|
||||
const result = await executor.invoke({ input });
|
||||
const { output } = result;
|
||||
|
||||
return output;
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
import type { NextMiddleware } from "next-api-middleware";
|
||||
|
||||
import { CONSOLE_URL } from "@calcom/lib/constants";
|
||||
import { customPrisma } from "@calcom/prisma";
|
||||
|
||||
const LOCAL_CONSOLE_URL = process.env.NEXT_PUBLIC_CONSOLE_URL || CONSOLE_URL;
|
||||
|
||||
// This replaces the prisma client for the custom one if the key is valid
|
||||
export const customPrismaClient: NextMiddleware = async (req, res, next) => {
|
||||
const {
|
||||
query: { key },
|
||||
} = req;
|
||||
// If no custom api Id is provided, attach to request the regular cal.com prisma client.
|
||||
if (!key) {
|
||||
req.prisma = customPrisma();
|
||||
await next();
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a key, we check if the deployment matching the key, has a databaseUrl value set.
|
||||
const databaseUrl = await fetch(`${LOCAL_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;
|
||||
}
|
||||
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.isCustomPrisma = true;
|
||||
// We don't need the key from here and on. Prevents unrecognized key errors.
|
||||
delete req.query.key;
|
||||
await next();
|
||||
await req.prisma.$disconnect();
|
||||
// @ts-expect-error testing
|
||||
delete req.prisma;
|
||||
};
|
||||
@@ -3,6 +3,7 @@ import type { NextMiddleware } from "next-api-middleware";
|
||||
import { hashAPIKey } from "@calcom/features/ee/api-keys/lib/apiKeys";
|
||||
import checkLicense from "@calcom/features/ee/common/server/checkLicense";
|
||||
import { IS_PRODUCTION } from "@calcom/lib/constants";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { isAdminGuard } from "../utils/isAdmin";
|
||||
|
||||
@@ -16,15 +17,9 @@ 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, isCustomPrisma, isAdmin } = req;
|
||||
const hasValidLicense = await checkLicense(prisma);
|
||||
if (!hasValidLicense && IS_PRODUCTION)
|
||||
return res.status(401).json({ error: "Invalid or missing CALCOM_LICENSE_KEY environment variable" });
|
||||
// If the user is an admin and using a license key (from customPrisma), skip the apiKey check.
|
||||
if (isCustomPrisma && 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" });
|
||||
// remove the prefix from the user provided api_key. If no env set default to "cal_"
|
||||
@@ -43,6 +38,5 @@ export const verifyApiKey: NextMiddleware = async (req, res, next) => {
|
||||
req.userId = apiKey.userId;
|
||||
// save the isAdmin boolean here for later use
|
||||
req.isAdmin = await isAdminGuard(req);
|
||||
req.isCustomPrisma = false;
|
||||
await next();
|
||||
};
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { NextMiddleware } from "next-api-middleware";
|
||||
|
||||
import { APP_CREDENTIAL_SHARING_ENABLED } from "@calcom/lib/constants";
|
||||
|
||||
export const verifyCredentialSyncEnabled: NextMiddleware = async (req, res, next) => {
|
||||
const { isAdmin } = req;
|
||||
|
||||
if (!isAdmin) {
|
||||
return res.status(403).json({ error: "Only admin API keys can access credential syncing endpoints" });
|
||||
}
|
||||
|
||||
if (!APP_CREDENTIAL_SHARING_ENABLED) {
|
||||
return res.status(501).json({ error: "Credential syncing is not enabled" });
|
||||
}
|
||||
|
||||
if (
|
||||
req.headers[process.env.CALCOM_CREDENTIAL_SYNC_HEADER_NAME || "calcom-credential-sync-secret"] !==
|
||||
process.env.CALCOM_CREDENTIAL_SYNC_SECRET
|
||||
) {
|
||||
return res.status(401).json({ message: "Invalid credential sync secret" });
|
||||
}
|
||||
|
||||
await next();
|
||||
};
|
||||
@@ -2,7 +2,6 @@ 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,
|
||||
@@ -14,6 +13,7 @@ import {
|
||||
} from "./httpMethods";
|
||||
import { rateLimitApiKey } from "./rateLimitApiKey";
|
||||
import { verifyApiKey } from "./verifyApiKey";
|
||||
import { verifyCredentialSyncEnabled } from "./verifyCredentialSyncEnabled";
|
||||
import { withPagination } from "./withPagination";
|
||||
|
||||
const middleware = {
|
||||
@@ -26,25 +26,22 @@ const middleware = {
|
||||
addRequestId,
|
||||
verifyApiKey,
|
||||
rateLimitApiKey,
|
||||
customPrismaClient,
|
||||
extendRequest,
|
||||
pagination: withPagination,
|
||||
captureErrors,
|
||||
verifyCredentialSyncEnabled,
|
||||
};
|
||||
|
||||
type Middleware = keyof typeof middleware;
|
||||
|
||||
const middlewareOrder =
|
||||
const middlewareOrder = [
|
||||
// The order here, determines the order of execution
|
||||
[
|
||||
"extendRequest",
|
||||
"captureErrors",
|
||||
// - Put customPrismaClient before verifyApiKey always.
|
||||
"customPrismaClient",
|
||||
"verifyApiKey",
|
||||
"rateLimitApiKey",
|
||||
"addRequestId",
|
||||
] as Middleware[]; // <-- Provide a list of middleware to call automatically
|
||||
"extendRequest",
|
||||
"captureErrors",
|
||||
"verifyApiKey",
|
||||
"rateLimitApiKey",
|
||||
"addRequestId",
|
||||
] as Middleware[]; // <-- Provide a list of middleware to call automatically
|
||||
|
||||
const withMiddleware = label(middleware, middlewareOrder);
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
import { UserPermissionRole } from "@calcom/prisma/enums";
|
||||
|
||||
export const isAdminGuard = async (req: NextApiRequest) => {
|
||||
const { userId, prisma } = req;
|
||||
const { userId } = req;
|
||||
const user = await prisma.user.findUnique({ where: { id: userId } });
|
||||
return user?.role === UserPermissionRole.ADMIN;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import { z } from "zod";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
|
||||
const userId = z.string().transform((val) => {
|
||||
const userIdInt = parseInt(val);
|
||||
|
||||
if (isNaN(userIdInt)) {
|
||||
throw new HttpError({ message: "userId is not a valid number", statusCode: 400 });
|
||||
}
|
||||
|
||||
return userIdInt;
|
||||
});
|
||||
const appSlug = z.string();
|
||||
const credentialId = z.string().transform((val) => {
|
||||
const credentialIdInt = parseInt(val);
|
||||
|
||||
if (isNaN(credentialIdInt)) {
|
||||
throw new HttpError({ message: "credentialId is not a valid number", statusCode: 400 });
|
||||
}
|
||||
|
||||
return credentialIdInt;
|
||||
});
|
||||
const encryptedKey = z.string();
|
||||
|
||||
export const schemaCredentialGetParams = z.object({
|
||||
userId,
|
||||
appSlug: appSlug.optional(),
|
||||
});
|
||||
|
||||
export const schemaCredentialPostParams = z.object({
|
||||
userId,
|
||||
createSelectedCalendar: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((val) => {
|
||||
return val === "true";
|
||||
}),
|
||||
createDestinationCalendar: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((val) => {
|
||||
return val === "true";
|
||||
}),
|
||||
});
|
||||
|
||||
export const schemaCredentialPostBody = z.object({
|
||||
appSlug,
|
||||
encryptedKey,
|
||||
});
|
||||
|
||||
export const schemaCredentialPatchParams = z.object({
|
||||
userId,
|
||||
credentialId,
|
||||
});
|
||||
|
||||
export const schemaCredentialPatchBody = z.object({
|
||||
encryptedKey,
|
||||
});
|
||||
|
||||
export const schemaCredentialDeleteParams = z.object({
|
||||
userId,
|
||||
credentialId,
|
||||
});
|
||||
@@ -74,6 +74,7 @@ export const schemaUserBaseBodyParams = User.pick({
|
||||
timeZone: true,
|
||||
weekStart: true,
|
||||
theme: true,
|
||||
appTheme: true,
|
||||
defaultScheduleId: true,
|
||||
locale: true,
|
||||
hideBranding: true,
|
||||
@@ -100,6 +101,7 @@ const schemaUserEditParams = z.object({
|
||||
hideBranding: z.boolean().optional(),
|
||||
timeZone: timeZone.optional(),
|
||||
theme: z.nativeEnum(theme).optional().nullable(),
|
||||
appTheme: z.nativeEnum(theme).optional().nullable(),
|
||||
timeFormat: z.nativeEnum(timeFormat).optional(),
|
||||
defaultScheduleId: z
|
||||
.number()
|
||||
@@ -122,6 +124,7 @@ const schemaUserCreateParams = z.object({
|
||||
hideBranding: z.boolean().optional(),
|
||||
timeZone: timeZone.optional(),
|
||||
theme: z.nativeEnum(theme).optional().nullable(),
|
||||
appTheme: z.nativeEnum(theme).optional().nullable(),
|
||||
timeFormat: z.nativeEnum(timeFormat).optional(),
|
||||
defaultScheduleId: z
|
||||
.number()
|
||||
@@ -159,6 +162,7 @@ export const schemaUserReadPublic = User.pick({
|
||||
weekStart: true,
|
||||
endTime: true,
|
||||
bufferTime: true,
|
||||
appTheme: true,
|
||||
theme: true,
|
||||
defaultScheduleId: true,
|
||||
locale: true,
|
||||
|
||||
Vendored
-4
@@ -1,8 +1,6 @@
|
||||
import type { Session } from "next-auth";
|
||||
import type { NextApiRequest as BaseNextApiRequest } from "next/types";
|
||||
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
|
||||
export type * from "next/types";
|
||||
|
||||
export declare module "next" {
|
||||
@@ -11,11 +9,9 @@ export declare module "next" {
|
||||
|
||||
userId: number;
|
||||
method: string;
|
||||
prisma: PrismaClient;
|
||||
// session: { user: { id: number } };
|
||||
// query: Partial<{ [key: string]: string | string[] }>;
|
||||
isAdmin: boolean;
|
||||
isCustomPrisma: boolean;
|
||||
pagination: { take: number; skip: number };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdAsString } from "~/lib/validations/shared/queryIdString";
|
||||
|
||||
export async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { id } = schemaQueryIdAsString.parse(req.query);
|
||||
// Admin can check any api key
|
||||
if (isAdmin) return;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdAsString } from "~/lib/validations/shared/queryIdString";
|
||||
|
||||
async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdAsString.parse(query);
|
||||
await prisma.apiKey.delete({ where: { id } });
|
||||
return { message: `ApiKey with id: ${id} deleted` };
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { apiKeyPublicSchema } from "~/lib/validations/api-key";
|
||||
import { schemaQueryIdAsString } from "~/lib/validations/shared/queryIdString";
|
||||
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdAsString.parse(query);
|
||||
const api_key = await prisma.apiKey.findUniqueOrThrow({ where: { id } });
|
||||
return { api_key: apiKeyPublicSchema.parse(api_key) };
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { apiKeyEditBodySchema, apiKeyPublicSchema } from "~/lib/validations/api-key";
|
||||
import { schemaQueryIdAsString } from "~/lib/validations/shared/queryIdString";
|
||||
|
||||
async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, body } = req;
|
||||
const { body } = req;
|
||||
const { id } = schemaQueryIdAsString.parse(req.query);
|
||||
const data = apiKeyEditBodySchema.parse(body);
|
||||
const api_key = await prisma.apiKey.update({ where: { id }, data });
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { Ensure } from "@calcom/types/utils";
|
||||
|
||||
import { apiKeyPublicSchema } from "~/lib/validations/api-key";
|
||||
@@ -29,7 +30,7 @@ function hasReqArgs(req: CustomNextApiRequest): req is Ensure<CustomNextApiReque
|
||||
}
|
||||
|
||||
async function getHandler(req: CustomNextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
req.args = isAdmin ? {} : { where: { userId } };
|
||||
// Proof of concept: allowing mutation in exchange of composability
|
||||
handleAdminRequests(req);
|
||||
|
||||
@@ -5,11 +5,12 @@ import { v4 } from "uuid";
|
||||
import { generateUniqueAPIKey } from "@calcom/features/ee/api-keys/lib/apiKeys";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { apiKeyCreateBodySchema, apiKeyPublicSchema } from "~/lib/validations/api-key";
|
||||
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { neverExpires, userId: bodyUserId, ...input } = apiKeyCreateBodySchema.parse(req.body);
|
||||
const [hashedKey, apiKey] = generateUniqueAPIKey();
|
||||
const args: Prisma.ApiKeyCreateArgs = {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const query = schemaQueryIdParseInt.parse(req.query);
|
||||
// @note: Here we make sure to only return attendee's of the user's own bookings if the user is not an admin.
|
||||
if (isAdmin) return;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
@@ -34,7 +35,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
await prisma.attendee.delete({ where: { id } });
|
||||
return { message: `Attendee with id: ${id} deleted successfully` };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaAttendeeReadPublic } from "~/lib/validations/attendee";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -35,7 +36,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Attendee was not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const attendee = await prisma.attendee.findUnique({ where: { id } });
|
||||
return { attendee: schemaAttendeeReadPublic.parse(attendee) };
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { z } from "zod";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaAttendeeEditBodyParams, schemaAttendeeReadPublic } from "~/lib/validations/attendee";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -53,7 +54,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
*/
|
||||
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query, body } = req;
|
||||
const { query, body } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const data = schemaAttendeeEditBodyParams.parse(body);
|
||||
await checkPermissions(req, data);
|
||||
@@ -62,7 +63,7 @@ export async function patchHandler(req: NextApiRequest) {
|
||||
}
|
||||
|
||||
async function checkPermissions(req: NextApiRequest, body: z.infer<typeof schemaAttendeeEditBodyParams>) {
|
||||
const { isAdmin, prisma } = req;
|
||||
const { isAdmin } = req;
|
||||
if (isAdmin) return;
|
||||
const { userId } = req;
|
||||
const { bookingId } = body;
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaAttendeeReadPublic } from "~/lib/validations/attendee";
|
||||
|
||||
@@ -30,7 +31,7 @@ import { schemaAttendeeReadPublic } from "~/lib/validations/attendee";
|
||||
* description: No attendees were found
|
||||
*/
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const args: Prisma.AttendeeFindManyArgs = isAdmin ? {} : { where: { booking: { userId } } };
|
||||
const data = await prisma.attendee.findMany(args);
|
||||
const attendees = data.map((attendee) => schemaAttendeeReadPublic.parse(attendee));
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaAttendeeCreateBodyParams, schemaAttendeeReadPublic } from "~/lib/validations/attendee";
|
||||
|
||||
@@ -51,7 +52,7 @@ import { schemaAttendeeCreateBodyParams, schemaAttendeeReadPublic } from "~/lib/
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const body = schemaAttendeeCreateBodyParams.parse(req.body);
|
||||
|
||||
if (!isAdmin) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, prisma, isAdmin, query } = req;
|
||||
const { userId, isAdmin, query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
/** Admins can skip the ownership verification */
|
||||
if (isAdmin) return;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
@@ -36,7 +37,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
await prisma.availability.delete({ where: { id } });
|
||||
return { message: `Availability with id: ${id} deleted successfully` };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaAvailabilityReadPublic } from "~/lib/validations/availability";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -37,7 +38,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Availability not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const availability = await prisma.availability.findUnique({
|
||||
where: { id },
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
schemaAvailabilityEditBodyParams,
|
||||
@@ -72,7 +73,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query, body } = req;
|
||||
const { query, body } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const data = schemaAvailabilityEditBodyParams.parse(body);
|
||||
const availability = await prisma.availability.update({
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
schemaAvailabilityCreateBodyParams,
|
||||
@@ -71,7 +72,6 @@ import {
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { prisma } = req;
|
||||
const data = schemaAvailabilityCreateBodyParams.parse(req.body);
|
||||
await checkPermissions(req);
|
||||
const availability = await prisma.availability.create({
|
||||
@@ -86,7 +86,7 @@ async function postHandler(req: NextApiRequest) {
|
||||
}
|
||||
|
||||
async function checkPermissions(req: NextApiRequest) {
|
||||
const { userId, prisma, isAdmin } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
if (isAdmin) return;
|
||||
const data = schemaAvailabilityCreateBodyParams.parse(req.body);
|
||||
const schedule = await prisma.schedule.findFirst({
|
||||
|
||||
@@ -4,6 +4,7 @@ import { z } from "zod";
|
||||
import { getUserAvailability } from "@calcom/core/getUserAvailability";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { availabilityUserSelect } from "@calcom/prisma";
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
import { stringOrNumber } from "@calcom/prisma/zod-utils";
|
||||
@@ -188,7 +189,7 @@ const availabilitySchema = z
|
||||
);
|
||||
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { prisma, isAdmin, userId: reqUserId } = req;
|
||||
const { isAdmin, userId: reqUserId } = req;
|
||||
const { username, userId, eventTypeId, dateTo, dateFrom, teamId } = availabilitySchema.parse(req.query);
|
||||
if (!teamId)
|
||||
return getUserAvailability({
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(req.query);
|
||||
// Here we make sure to only return references of the user's own bookings if the user is not an admin.
|
||||
if (isAdmin) return;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
@@ -34,7 +35,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
await prisma.bookingReference.delete({ where: { id } });
|
||||
return { message: `BookingReference with id: ${id} deleted` };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaBookingReferenceReadPublic } from "~/lib/validations/booking-reference";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -35,7 +36,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: BookingReference was not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const booking_reference = await prisma.bookingReference.findUniqueOrThrow({ where: { id } });
|
||||
return { booking_reference: schemaBookingReferenceReadPublic.parse(booking_reference) };
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
schemaBookingEditBodyParams,
|
||||
@@ -59,7 +60,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query, body, isAdmin, userId } = req;
|
||||
const { query, body, isAdmin, userId } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const data = schemaBookingEditBodyParams.parse(body);
|
||||
/* If user tries to update bookingId, we run extra checks */
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaBookingReferenceReadPublic } from "~/lib/validations/booking-reference";
|
||||
|
||||
@@ -29,7 +30,7 @@ import { schemaBookingReferenceReadPublic } from "~/lib/validations/booking-refe
|
||||
* description: No booking references were found
|
||||
*/
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const args: Prisma.BookingReferenceFindManyArgs = isAdmin ? {} : { where: { booking: { userId } } };
|
||||
const data = await prisma.bookingReference.findMany(args);
|
||||
return { booking_references: data.map((br) => schemaBookingReferenceReadPublic.parse(br)) };
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
schemaBookingCreateBodyParams,
|
||||
@@ -61,7 +62,7 @@ import {
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const body = schemaBookingCreateBodyParams.parse(req.body);
|
||||
const args: Prisma.BookingFindFirstOrThrowArgs = isAdmin
|
||||
? /* If admin, we only check that the booking exists */
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, prisma, isAdmin, query } = req;
|
||||
const { userId, isAdmin, query } = req;
|
||||
if (isAdmin) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaBookingReadPublic } from "~/lib/validations/booking";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -86,7 +87,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
*/
|
||||
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const booking = await prisma.booking.findUnique({
|
||||
where: { id },
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { z } from "zod";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaBookingEditBodyParams, schemaBookingReadPublic } from "~/lib/validations/booking";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -99,7 +100,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query, body } = req;
|
||||
const { query, body } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const data = schemaBookingEditBodyParams.parse(body);
|
||||
await checkPermissions(req, data);
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaBookingGetParams, schemaBookingReadPublic } from "~/lib/validations/booking";
|
||||
import { schemaQuerySingleOrMultipleAttendeeEmails } from "~/lib/validations/shared/queryAttendeeEmail";
|
||||
@@ -161,7 +162,7 @@ function buildWhereClause(
|
||||
}
|
||||
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
|
||||
const { dateFrom, dateTo } = schemaBookingGetParams.parse(req.query);
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import { schemaCredentialDeleteParams } from "~/lib/validations/credential-sync";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /credential-sync:
|
||||
* delete:
|
||||
* operationId: deleteUserAppCredential
|
||||
* summary: Delete a credential record for a user
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* - in: query
|
||||
* name: userId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: ID of the user to fetch the credentials for
|
||||
* - in: query
|
||||
* name: credentialId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: ID of the credential to update
|
||||
* tags:
|
||||
* - credentials
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 505:
|
||||
* description: Credential syncing not enabled
|
||||
*/
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { prisma } = req;
|
||||
|
||||
const { userId: reqUserId, credentialId: reqCredentialId } = schemaCredentialDeleteParams.parse(req.query);
|
||||
|
||||
const userId = parseInt(reqUserId);
|
||||
const credentialId = parseInt(reqCredentialId);
|
||||
|
||||
const credential = await prisma.credential.delete({
|
||||
where: {
|
||||
id: credentialId,
|
||||
userId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
appId: true,
|
||||
},
|
||||
});
|
||||
|
||||
return { credentialDeleted: credential };
|
||||
}
|
||||
|
||||
export default defaultResponder(handler);
|
||||
@@ -0,0 +1,63 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import { schemaCredentialGetParams } from "~/lib/validations/credential-sync";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /credential-sync:
|
||||
* get:
|
||||
* operationId: getUserAppCredentials
|
||||
* summary: Get all app credentials for a user
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* - in: query
|
||||
* name: userId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: ID of the user to fetch the credentials for
|
||||
* tags:
|
||||
* - credentials
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 505:
|
||||
* description: Credential syncing not enabled
|
||||
*/
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { prisma } = req;
|
||||
|
||||
const { appSlug, userId } = schemaCredentialGetParams.parse(req.query);
|
||||
|
||||
let credentials = await prisma.credential.findMany({
|
||||
where: {
|
||||
userId,
|
||||
...(appSlug && { appId: appSlug }),
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
appId: true,
|
||||
},
|
||||
});
|
||||
|
||||
// For apps we're transitioning to using the term slug to keep things consistent
|
||||
credentials = credentials.map((credential) => {
|
||||
return {
|
||||
...credential,
|
||||
appSlug: credential.appId,
|
||||
};
|
||||
});
|
||||
|
||||
return { credentials };
|
||||
}
|
||||
|
||||
export default defaultResponder(handler);
|
||||
@@ -0,0 +1,86 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { minimumTokenResponseSchema } from "@calcom/app-store/_utils/oauth/parseRefreshTokenResponse";
|
||||
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import { schemaCredentialPatchParams, schemaCredentialPatchBody } from "~/lib/validations/credential-sync";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /credential-sync:
|
||||
* patch:
|
||||
* operationId: updateUserAppCredential
|
||||
* summary: Update a credential record for a user
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* - in: query
|
||||
* name: userId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: ID of the user to fetch the credentials for
|
||||
* - in: query
|
||||
* name: credentialId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: ID of the credential to update
|
||||
* tags:
|
||||
* - credentials
|
||||
* requestBody:
|
||||
* description: Update a new credential
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - encryptedKey
|
||||
* properties:
|
||||
* encryptedKey:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 505:
|
||||
* description: Credential syncing not enabled
|
||||
*/
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { prisma } = req;
|
||||
|
||||
const { userId, credentialId } = schemaCredentialPatchParams.parse(req.query);
|
||||
|
||||
const { encryptedKey } = schemaCredentialPatchBody.parse(req.body);
|
||||
|
||||
const decryptedKey = JSON.parse(
|
||||
symmetricDecrypt(encryptedKey, process.env.CALCOM_APP_CREDENTIAL_ENCRYPTION_KEY || "")
|
||||
);
|
||||
|
||||
const key = minimumTokenResponseSchema.parse(decryptedKey);
|
||||
|
||||
const credential = await prisma.credential.update({
|
||||
where: {
|
||||
id: credentialId,
|
||||
userId,
|
||||
},
|
||||
data: {
|
||||
key,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
appId: true,
|
||||
},
|
||||
});
|
||||
|
||||
return { credential };
|
||||
}
|
||||
|
||||
export default defaultResponder(handler);
|
||||
@@ -0,0 +1,142 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { getCalendar } from "@calcom/app-store/_utils/getCalendar";
|
||||
import { minimumTokenResponseSchema } from "@calcom/app-store/_utils/oauth/parseRefreshTokenResponse";
|
||||
import { appStoreMetadata } from "@calcom/app-store/appStoreMetaData";
|
||||
import { symmetricDecrypt } from "@calcom/lib/crypto";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
|
||||
import { schemaCredentialPostParams, schemaCredentialPostBody } from "~/lib/validations/credential-sync";
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /credential-sync:
|
||||
* post:
|
||||
* operationId: createUserAppCredential
|
||||
* summary: Create a credential record for a user
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: apiKey
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: Your API key
|
||||
* - in: query
|
||||
* name: userId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: ID of the user to fetch the credentials for
|
||||
* tags:
|
||||
* - credentials
|
||||
* requestBody:
|
||||
* description: Create a new credential
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - encryptedKey
|
||||
* - appSlug
|
||||
* properties:
|
||||
* encryptedKey:
|
||||
* type: string
|
||||
* appSlug:
|
||||
* type: string
|
||||
* responses:
|
||||
* 200:
|
||||
* description: OK
|
||||
* 401:
|
||||
* description: Authorization information is missing or invalid.
|
||||
* 505:
|
||||
* description: Credential syncing not enabled
|
||||
*/
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { prisma } = req;
|
||||
|
||||
if (!req.body) {
|
||||
throw new HttpError({ message: "Request body is missing", statusCode: 400 });
|
||||
}
|
||||
|
||||
const { userId, createSelectedCalendar, createDestinationCalendar } = schemaCredentialPostParams.parse(
|
||||
req.query
|
||||
);
|
||||
|
||||
const { appSlug, encryptedKey } = schemaCredentialPostBody.parse(req.body);
|
||||
|
||||
const decryptedKey = JSON.parse(
|
||||
symmetricDecrypt(encryptedKey, process.env.CALCOM_APP_CREDENTIAL_ENCRYPTION_KEY || "")
|
||||
);
|
||||
|
||||
const key = minimumTokenResponseSchema.parse(decryptedKey);
|
||||
|
||||
// Need to get app type
|
||||
const app = await prisma.app.findUnique({
|
||||
where: { slug: appSlug },
|
||||
select: { dirName: true, categories: true },
|
||||
});
|
||||
|
||||
if (!app) {
|
||||
throw new HttpError({ message: "App not found", statusCode: 500 });
|
||||
}
|
||||
|
||||
const createCalendarResources =
|
||||
app.categories.some((category) => category === "calendar") &&
|
||||
(createSelectedCalendar || createDestinationCalendar);
|
||||
|
||||
const appMetadata = appStoreMetadata[app.dirName as keyof typeof appStoreMetadata];
|
||||
|
||||
const credential = await prisma.credential.create({
|
||||
data: {
|
||||
userId,
|
||||
appId: appSlug,
|
||||
key,
|
||||
type: appMetadata.type,
|
||||
},
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (createCalendarResources) {
|
||||
const calendar = await getCalendar(credential);
|
||||
const calendars = await calendar.listCalendars();
|
||||
|
||||
const calendarToCreate = calendars.find((calendar) => calendar.primary) || calendars[0];
|
||||
|
||||
if (createSelectedCalendar) {
|
||||
await prisma.selectedCalendar.createMany({
|
||||
data: [
|
||||
{
|
||||
userId,
|
||||
integration: appMetadata.type,
|
||||
externalId: calendarToCreate.externalId,
|
||||
credentialId: credential.id,
|
||||
},
|
||||
],
|
||||
skipDuplicates: true,
|
||||
});
|
||||
}
|
||||
if (createDestinationCalendar) {
|
||||
await prisma.destinationCalendar.create({
|
||||
data: {
|
||||
integration: appMetadata.type,
|
||||
externalId: calendarToCreate.externalId,
|
||||
credential: { connect: { id: credential.id } },
|
||||
primaryEmail: calendarToCreate.email || credential.user.email,
|
||||
user: { connect: { id: userId } },
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return { credential: { id: credential.id, type: credential.type } };
|
||||
}
|
||||
|
||||
export default defaultResponder(handler);
|
||||
@@ -0,0 +1,12 @@
|
||||
import { defaultHandler } from "@calcom/lib/server";
|
||||
|
||||
import { withMiddleware } from "~/lib/helpers/withMiddleware";
|
||||
|
||||
export default withMiddleware("verifyCredentialSyncEnabled")(
|
||||
defaultHandler({
|
||||
GET: import("./_get"),
|
||||
POST: import("./_post"),
|
||||
PATCH: import("./_patch"),
|
||||
DELETE: import("./_delete"),
|
||||
})
|
||||
);
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(req.query);
|
||||
// Admins can just skip this check
|
||||
if (isAdmin) return;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
@@ -33,7 +34,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
await prisma.eventTypeCustomInput.delete({ where: { id } });
|
||||
return { message: `CustomInputEventType with id: ${id} deleted successfully` };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaEventTypeCustomInputPublic } from "~/lib/validations/event-type-custom-input";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -34,7 +35,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: EventType was not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const data = await prisma.eventTypeCustomInput.findUniqueOrThrow({ where: { id } });
|
||||
return { event_type_custom_input: schemaEventTypeCustomInputPublic.parse(data) };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
schemaEventTypeCustomInputEditBodyParams,
|
||||
@@ -76,7 +77,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const data = schemaEventTypeCustomInputEditBodyParams.parse(req.body);
|
||||
const result = await prisma.eventTypeCustomInput.update({ where: { id }, data });
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaEventTypeCustomInputPublic } from "~/lib/validations/event-type-custom-input";
|
||||
|
||||
@@ -28,7 +29,7 @@ import { schemaEventTypeCustomInputPublic } from "~/lib/validations/event-type-c
|
||||
* description: No eventTypeCustomInputs were found
|
||||
*/
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const args: Prisma.EventTypeCustomInputFindManyArgs = isAdmin ? {} : { where: { eventType: { userId } } };
|
||||
const data = await prisma.eventTypeCustomInput.findMany(args);
|
||||
return { event_type_custom_inputs: data.map((v) => schemaEventTypeCustomInputPublic.parse(v)) };
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
schemaEventTypeCustomInputBodyParams,
|
||||
@@ -79,7 +80,7 @@ import {
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { eventTypeId, ...body } = schemaEventTypeCustomInputBodyParams.parse(req.body);
|
||||
|
||||
if (!isAdmin) {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(req.query);
|
||||
if (isAdmin) return;
|
||||
const userEventTypes = await prisma.eventType.findMany({
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
@@ -33,7 +34,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Destination calendar not found
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
await prisma.destinationCalendar.delete({ where: { id } });
|
||||
return { message: `OK, Destination Calendar removed successfully` };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaDestinationCalendarReadPublic } from "~/lib/validations/destination-calendar";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -34,7 +35,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Destination calendar not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
|
||||
const destinationCalendar = await prisma.destinationCalendar.findUnique({
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { z } from "zod";
|
||||
import { getCalendarCredentials, getConnectedCalendars } from "@calcom/core/CalendarManager";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
|
||||
|
||||
@@ -82,7 +83,7 @@ type UserCredentialType = {
|
||||
};
|
||||
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma, query, body } = req;
|
||||
const { userId, isAdmin, query, body } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const parsedBody = schemaDestinationCalendarEditBodyParams.parse(body);
|
||||
const assignedUserId = isAdmin ? parsedBody.userId || userId : userId;
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { extractUserIdsFromQuery } from "~/lib/utils/extractUserIdsFromQuery";
|
||||
import { schemaDestinationCalendarReadPublic } from "~/lib/validations/destination-calendar";
|
||||
@@ -29,7 +30,7 @@ import { schemaDestinationCalendarReadPublic } from "~/lib/validations/destinati
|
||||
* description: No destination calendars were found
|
||||
*/
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { userId, prisma } = req;
|
||||
const { userId } = req;
|
||||
const userIds = req.query.userId ? extractUserIdsFromQuery(req) : [userId];
|
||||
|
||||
const userEventTypes = await prisma.eventType.findMany({
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
import { getCalendarCredentials, getConnectedCalendars } from "@calcom/core/CalendarManager";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential";
|
||||
|
||||
import {
|
||||
@@ -60,7 +61,7 @@ import {
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma, body } = req;
|
||||
const { userId, isAdmin, body } = req;
|
||||
const parsedBody = schemaDestinationCalendarCreateBodyParams.parse(body);
|
||||
await checkPermissions(req, userId);
|
||||
|
||||
@@ -132,7 +133,7 @@ async function checkPermissions(req: NextApiRequest, userId: number) {
|
||||
if (isAdmin && !body.userId) throw new HttpError({ statusCode: 400, message: "`userId` required" });
|
||||
/* User should only be able to create for their own destination calendars*/
|
||||
if (!isAdmin && body.eventTypeId) {
|
||||
const ownsEventType = await req.prisma.eventType.findFirst({ where: { id: body.eventTypeId, userId } });
|
||||
const ownsEventType = await prisma.eventType.findFirst({ where: { id: body.eventTypeId, userId } });
|
||||
if (!ownsEventType) throw new HttpError({ statusCode: 401, message: "Unauthorized" });
|
||||
}
|
||||
// TODO:: Add support for team event types with validation
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(req.query);
|
||||
if (isAdmin) return;
|
||||
const eventType = await prisma.eventType.findFirst({
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
@@ -37,7 +38,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
await checkPermissions(req);
|
||||
await prisma.eventType.delete({ where: { id } });
|
||||
@@ -45,7 +46,7 @@ export async function deleteHandler(req: NextApiRequest) {
|
||||
}
|
||||
|
||||
async function checkPermissions(req: NextApiRequest) {
|
||||
const { userId, prisma, isAdmin } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(req.query);
|
||||
if (isAdmin) return;
|
||||
/** Only event type owners can delete it */
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
|
||||
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
||||
@@ -43,7 +44,7 @@ import getCalLink from "../_utils/getCalLink";
|
||||
* description: EventType was not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
|
||||
const eventType = await prisma.eventType.findUnique({
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { z } from "zod";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { SchedulingType } from "@calcom/prisma/enums";
|
||||
|
||||
import type { schemaEventTypeBaseBodyParams } from "~/lib/validations/event-type";
|
||||
@@ -203,7 +204,7 @@ import checkTeamEventEditPermission from "../_utils/checkTeamEventEditPermission
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query, body } = req;
|
||||
const { query, body } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const {
|
||||
hosts = [],
|
||||
@@ -236,7 +237,7 @@ export async function patchHandler(req: NextApiRequest) {
|
||||
}
|
||||
|
||||
async function checkPermissions(req: NextApiRequest, body: z.infer<typeof schemaEventTypeBaseBodyParams>) {
|
||||
const { userId, prisma, isAdmin } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(req.query);
|
||||
if (isAdmin) return;
|
||||
/** Only event type owners can modify it */
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import type { PrismaClient } from "@calcom/prisma";
|
||||
|
||||
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
||||
@@ -42,7 +43,7 @@ import getCalLink from "./_utils/getCalLink";
|
||||
* description: No event types were found
|
||||
*/
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { userId, prisma, isAdmin } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const userIds = req.query.userId ? extractUserIdsFromQuery(req) : [userId];
|
||||
const { slug } = schemaQuerySlug.parse(req.query);
|
||||
const shouldUseUserId = !isAdmin || !slug || !!req.query.userId;
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { MembershipRole } from "@calcom/prisma/client";
|
||||
|
||||
import { schemaEventTypeCreateBodyParams, schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
||||
@@ -264,7 +265,7 @@ import ensureOnlyMembersAsHosts from "./_utils/ensureOnlyMembersAsHosts";
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma, body } = req;
|
||||
const { userId, isAdmin, body } = req;
|
||||
|
||||
const {
|
||||
hosts = [],
|
||||
@@ -321,7 +322,7 @@ async function checkPermissions(req: NextApiRequest) {
|
||||
if (
|
||||
body.teamId &&
|
||||
!isAdmin &&
|
||||
!(await canUserAccessTeamWithRole(req.prisma, req.userId, isAdmin, body.teamId, {
|
||||
!(await canUserAccessTeamWithRole(req.userId, isAdmin, body.teamId, {
|
||||
in: [MembershipRole.OWNER, MembershipRole.ADMIN],
|
||||
}))
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
/**
|
||||
* Checks if a user, identified by the provided userId, has ownership (or admin rights) over
|
||||
@@ -13,7 +14,7 @@ import { HttpError } from "@calcom/lib/http-error";
|
||||
* or if the user doesn't have ownership or admin rights to the associated team.
|
||||
*/
|
||||
export default async function checkParentEventOwnership(req: NextApiRequest) {
|
||||
const { userId, prisma, body } = req;
|
||||
const { userId, body } = req;
|
||||
/** These are already parsed upstream, we can assume they're good here. */
|
||||
const parentId = Number(body.parentId);
|
||||
const parentEventType = await prisma.eventType.findUnique({
|
||||
|
||||
@@ -2,14 +2,19 @@ import type { NextApiRequest } from "next";
|
||||
import type { z } from "zod";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import type { schemaEventTypeBaseBodyParams } from "~/lib/validations/event-type";
|
||||
import type { schemaEventTypeCreateBodyParams } from "~/lib/validations/event-type";
|
||||
|
||||
export default async function checkTeamEventEditPermission(
|
||||
req: NextApiRequest,
|
||||
body: Pick<z.infer<typeof schemaEventTypeBaseBodyParams>, "teamId">
|
||||
body: Pick<z.infer<typeof schemaEventTypeCreateBodyParams>, "teamId" | "userId">
|
||||
) {
|
||||
const { prisma, userId } = req;
|
||||
const { isAdmin } = req;
|
||||
let userId = req.userId;
|
||||
if (isAdmin && body.userId) {
|
||||
userId = body.userId;
|
||||
}
|
||||
if (body.teamId) {
|
||||
const membership = await prisma.membership.findFirst({
|
||||
where: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
/**
|
||||
* Checks if a user, identified by the provided userId, is a member of the team associated
|
||||
@@ -13,7 +14,7 @@ import { HttpError } from "@calcom/lib/http-error";
|
||||
* or if the user isn't a member of the associated team.
|
||||
*/
|
||||
export default async function checkUserMembership(req: NextApiRequest) {
|
||||
const { prisma, body } = req;
|
||||
const { body } = req;
|
||||
/** These are already parsed upstream, we can assume they're good here. */
|
||||
const parentId = Number(body.parentId);
|
||||
const userId = Number(body.userId);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
import type { z } from "zod";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import type { schemaEventTypeCreateBodyParams } from "~/lib/validations/event-type";
|
||||
|
||||
export default async function ensureOnlyMembersAsHosts(
|
||||
@@ -8,7 +10,7 @@ export default async function ensureOnlyMembersAsHosts(
|
||||
body: Pick<z.infer<typeof schemaEventTypeCreateBodyParams>, "hosts" | "teamId">
|
||||
) {
|
||||
if (body.teamId && body.hosts && body.hosts.length > 0) {
|
||||
const teamMemberCount = await req.prisma.membership.count({
|
||||
const teamMemberCount = await prisma.membership.count({
|
||||
where: {
|
||||
teamId: body.teamId,
|
||||
userId: { in: body.hosts.map((host) => host.userId) },
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { createContext } from "@calcom/trpc/server/createContext";
|
||||
import { viewerTeamsRouter } from "@calcom/trpc/server/routers/viewer/teams/_router";
|
||||
import type { TInviteMemberInputSchema } from "@calcom/trpc/server/routers/viewer/teams/inviteMember/inviteMember.schema";
|
||||
@@ -57,7 +58,7 @@ async function postHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||
}
|
||||
|
||||
async function checkPermissions(req: NextApiRequest, body: TInviteMemberInputSchema) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
if (isAdmin) return;
|
||||
// To prevent auto-accepted invites, limit it to ADMIN users
|
||||
if (!isAdmin && "accepted" in body)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaUserReadPublic } from "~/lib/validations/user";
|
||||
|
||||
async function handler({ userId, prisma }: NextApiRequest) {
|
||||
async function handler({ userId }: NextApiRequest) {
|
||||
const data = await prisma.user.findUniqueOrThrow({ where: { id: userId } });
|
||||
return { user: schemaUserReadPublic.parse(data) };
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { membershipIdSchema } from "~/lib/validations/membership";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { teamId } = membershipIdSchema.parse(req.query);
|
||||
// Admins can just skip this check
|
||||
if (isAdmin) return;
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { membershipIdSchema } from "~/lib/validations/membership";
|
||||
|
||||
@@ -34,7 +35,7 @@ import { membershipIdSchema } from "~/lib/validations/membership";
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const userId_teamId = membershipIdSchema.parse(query);
|
||||
await checkPermissions(req);
|
||||
await prisma.membership.delete({ where: { userId_teamId } });
|
||||
@@ -42,7 +43,7 @@ export async function deleteHandler(req: NextApiRequest) {
|
||||
}
|
||||
|
||||
async function checkPermissions(req: NextApiRequest) {
|
||||
const { prisma, isAdmin, userId, query } = req;
|
||||
const { isAdmin, userId, query } = req;
|
||||
const userId_teamId = membershipIdSchema.parse(query);
|
||||
// Admin User can do anything including deletion of Admin Team Member in any team
|
||||
if (isAdmin) {
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { membershipIdSchema, schemaMembershipPublic } from "~/lib/validations/membership";
|
||||
|
||||
@@ -34,7 +35,7 @@ import { membershipIdSchema, schemaMembershipPublic } from "~/lib/validations/me
|
||||
* description: Membership was not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const userId_teamId = membershipIdSchema.parse(query);
|
||||
const args: Prisma.MembershipFindUniqueOrThrowArgs = { where: { userId_teamId } };
|
||||
// Just in case the user want to get more info about the team itself
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
membershipEditBodySchema,
|
||||
@@ -39,7 +40,7 @@ import {
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const userId_teamId = membershipIdSchema.parse(query);
|
||||
const data = membershipEditBodySchema.parse(req.body);
|
||||
const args: Prisma.MembershipUpdateArgs = { where: { userId_teamId }, data };
|
||||
@@ -51,7 +52,7 @@ export async function patchHandler(req: NextApiRequest) {
|
||||
}
|
||||
|
||||
async function checkPermissions(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { userId: queryUserId, teamId } = membershipIdSchema.parse(req.query);
|
||||
const data = membershipEditBodySchema.parse(req.body);
|
||||
// Admins can just skip this check
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaMembershipPublic } from "~/lib/validations/membership";
|
||||
import {
|
||||
@@ -26,7 +27,6 @@ import {
|
||||
* description: No memberships were found
|
||||
*/
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { prisma } = req;
|
||||
const args: Prisma.MembershipFindManyArgs = {
|
||||
where: {
|
||||
/** Admins can query multiple users */
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { membershipCreateBodySchema, schemaMembershipPublic } from "~/lib/validations/membership";
|
||||
|
||||
@@ -22,7 +23,6 @@ import { membershipCreateBodySchema, schemaMembershipPublic } from "~/lib/valida
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { prisma } = req;
|
||||
const data = membershipCreateBodySchema.parse(req.body);
|
||||
const args: Prisma.MembershipCreateArgs = { data };
|
||||
|
||||
@@ -37,7 +37,7 @@ async function postHandler(req: NextApiRequest) {
|
||||
}
|
||||
|
||||
async function checkPermissions(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
if (isAdmin) return;
|
||||
const body = membershipCreateBodySchema.parse(req.body);
|
||||
// To prevent auto-accepted invites, limit it to ADMIN users
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
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";
|
||||
@@ -37,7 +39,7 @@ import {
|
||||
* description: Payment was not found
|
||||
*/
|
||||
export async function paymentById(
|
||||
{ method, query, userId, prisma }: NextApiRequest,
|
||||
{ method, query, userId }: NextApiRequest,
|
||||
res: NextApiResponse<PaymentResponse>
|
||||
) {
|
||||
const safeQuery = schemaQueryIdParseInt.safeParse(query);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "~/lib/helpers/withMiddleware";
|
||||
import type { PaymentsResponse } from "~/lib/types";
|
||||
import { schemaPaymentPublic } from "~/lib/validations/payment";
|
||||
@@ -19,7 +21,7 @@ import { schemaPaymentPublic } from "~/lib/validations/payment";
|
||||
* 404:
|
||||
* description: No payments were found
|
||||
*/
|
||||
async function allPayments({ userId, prisma }: NextApiRequest, res: NextApiResponse<PaymentsResponse>) {
|
||||
async function allPayments({ userId }: NextApiRequest, res: NextApiResponse<PaymentsResponse>) {
|
||||
const userWithBookings = await prisma.user.findUnique({
|
||||
where: { id: userId },
|
||||
include: { bookings: true },
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(req.query);
|
||||
// Admins can just skip this check
|
||||
if (isAdmin) return;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
|
||||
@@ -34,7 +35,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
|
||||
/* If we're deleting any default user schedule, we unset it */
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaSchedulePublic } from "~/lib/validations/schedule";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -72,7 +73,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
*/
|
||||
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const data = await prisma.schedule.findUniqueOrThrow({ where: { id }, include: { availability: true } });
|
||||
return { schedule: schemaSchedulePublic.parse(data) };
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { z } from "zod";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaSchedulePublic, schemaSingleScheduleBodyParams } from "~/lib/validations/schedule";
|
||||
import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransformParseInt";
|
||||
@@ -81,7 +82,7 @@ import { schemaQueryIdParseInt } from "~/lib/validations/shared/queryIdTransform
|
||||
*/
|
||||
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { id } = schemaQueryIdParseInt.parse(query);
|
||||
const data = schemaSingleScheduleBodyParams.parse(req.body);
|
||||
await checkPermissions(req, data);
|
||||
|
||||
@@ -4,6 +4,7 @@ import { z } from "zod";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaSchedulePublic } from "~/lib/validations/schedule";
|
||||
import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/queryUserId";
|
||||
@@ -76,7 +77,7 @@ export const schemaUserIds = z
|
||||
*/
|
||||
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { prisma, userId, isAdmin } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const args: Prisma.ScheduleFindManyArgs = isAdmin ? {} : { where: { userId } };
|
||||
args.include = { availability: true };
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { NextApiRequest } from "next";
|
||||
import { DEFAULT_SCHEDULE, getAvailabilityFromSchedule } from "@calcom/lib/availability";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaCreateScheduleBodyParams, schemaSchedulePublic } from "~/lib/validations/schedule";
|
||||
|
||||
@@ -79,7 +80,7 @@ import { schemaCreateScheduleBodyParams, schemaSchedulePublic } from "~/lib/vali
|
||||
*/
|
||||
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const body = schemaCreateScheduleBodyParams.parse(req.body);
|
||||
let args: Prisma.ScheduleCreateArgs = { data: { ...body, userId } };
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { selectedCalendarIdSchema } from "~/lib/validations/selected-calendar";
|
||||
|
||||
@@ -46,7 +47,7 @@ import { selectedCalendarIdSchema } from "~/lib/validations/selected-calendar";
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const userId_integration_externalId = selectedCalendarIdSchema.parse(query);
|
||||
await prisma.selectedCalendar.delete({ where: { userId_integration_externalId } });
|
||||
return { message: `Selected Calendar with id: ${query.id} deleted successfully` };
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaSelectedCalendarPublic, selectedCalendarIdSchema } from "~/lib/validations/selected-calendar";
|
||||
|
||||
@@ -46,7 +47,7 @@ import { schemaSelectedCalendarPublic, selectedCalendarIdSchema } from "~/lib/va
|
||||
* description: SelectedCalendar was not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const userId_integration_externalId = selectedCalendarIdSchema.parse(query);
|
||||
const data = await prisma.selectedCalendar.findUniqueOrThrow({
|
||||
where: { userId_integration_externalId },
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
schemaSelectedCalendarPublic,
|
||||
@@ -52,7 +53,7 @@ import {
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, query, isAdmin } = req;
|
||||
const { query, isAdmin } = req;
|
||||
const userId_integration_externalId = selectedCalendarIdSchema.parse(query);
|
||||
const { userId: bodyUserId, ...data } = schemaSelectedCalendarUpdateBodyParams.parse(req.body);
|
||||
const args: Prisma.SelectedCalendarUpdateArgs = { where: { userId_integration_externalId }, data };
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaSelectedCalendarPublic } from "~/lib/validations/selected-calendar";
|
||||
import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/queryUserId";
|
||||
@@ -31,7 +32,7 @@ import { schemaQuerySingleOrMultipleUserIds } from "~/lib/validations/shared/que
|
||||
* description: No selected calendars were found
|
||||
*/
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
/* Admin gets all selected calendar by default, otherwise only the user's ones */
|
||||
const args: Prisma.SelectedCalendarFindManyArgs = isAdmin ? {} : { where: { userId } };
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import {
|
||||
schemaSelectedCalendarBodyParams,
|
||||
@@ -49,7 +50,7 @@ import {
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { userId: bodyUserId, ...body } = schemaSelectedCalendarBodyParams.parse(req.body);
|
||||
const args: Prisma.SelectedCalendarCreateArgs = { data: { ...body, userId } };
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
|
||||
import { schemaQueryTeamId } from "~/lib/validations/shared/queryTeamId";
|
||||
|
||||
async function authMiddleware(req: NextApiRequest) {
|
||||
const { userId, prisma, isAdmin } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { teamId } = schemaQueryTeamId.parse(req.query);
|
||||
/** Admins can skip the ownership verification */
|
||||
if (isAdmin) return;
|
||||
@@ -21,17 +22,16 @@ export async function checkPermissions(
|
||||
req: NextApiRequest,
|
||||
role: Prisma.MembershipWhereInput["role"] = MembershipRole.OWNER
|
||||
) {
|
||||
const { userId, prisma, isAdmin } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const { teamId } = schemaQueryTeamId.parse({
|
||||
teamId: req.query.teamId,
|
||||
version: req.query.version,
|
||||
apiKey: req.query.apiKey,
|
||||
});
|
||||
return canUserAccessTeamWithRole(prisma, userId, isAdmin, teamId, role);
|
||||
return canUserAccessTeamWithRole(userId, isAdmin, teamId, role);
|
||||
}
|
||||
|
||||
export async function canUserAccessTeamWithRole(
|
||||
prisma: NextApiRequest["prisma"],
|
||||
userId: number,
|
||||
isAdmin: boolean,
|
||||
teamId: number,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryTeamId } from "~/lib/validations/shared/queryTeamId";
|
||||
|
||||
@@ -36,7 +37,7 @@ import { checkPermissions } from "./_auth-middleware";
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, query } = req;
|
||||
const { query } = req;
|
||||
const { teamId } = schemaQueryTeamId.parse(query);
|
||||
await checkPermissions(req);
|
||||
await prisma.team.delete({ where: { id: teamId } });
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryTeamId } from "~/lib/validations/shared/queryTeamId";
|
||||
import { schemaTeamReadPublic } from "~/lib/validations/team";
|
||||
@@ -36,7 +37,7 @@ import { schemaTeamReadPublic } from "~/lib/validations/team";
|
||||
* description: Team was not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, isAdmin, userId } = req;
|
||||
const { isAdmin, userId } = req;
|
||||
const { teamId } = schemaQueryTeamId.parse(req.query);
|
||||
const where: Prisma.TeamWhereInput = { id: teamId };
|
||||
// Non-admins can only query the teams they're part of
|
||||
|
||||
@@ -5,6 +5,7 @@ import { purchaseTeamSubscription } from "@calcom/features/ee/teams/lib/payments
|
||||
import { IS_TEAM_BILLING_ENABLED } from "@calcom/lib/constants";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
@@ -55,7 +56,7 @@ import { schemaTeamReadPublic, schemaTeamUpdateBodyParams } from "~/lib/validati
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, body, userId } = req;
|
||||
const { body, userId } = req;
|
||||
const data = schemaTeamUpdateBodyParams.parse(body);
|
||||
const { teamId } = schemaQueryTeamId.parse(req.query);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaEventTypeReadPublic } from "~/lib/validations/event-type";
|
||||
|
||||
@@ -41,7 +42,7 @@ const querySchema = z.object({
|
||||
* description: No event types were found
|
||||
*/
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { userId, isAdmin, prisma } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
|
||||
const { teamId } = querySchema.parse(req.query);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaTeamsReadPublic } from "~/lib/validations/team";
|
||||
|
||||
@@ -29,7 +30,7 @@ import { schemaTeamsReadPublic } from "~/lib/validations/team";
|
||||
* description: No teams were found
|
||||
*/
|
||||
async function getHandler(req: NextApiRequest) {
|
||||
const { userId, prisma, isAdmin } = req;
|
||||
const { userId, isAdmin } = req;
|
||||
const where: Prisma.TeamWhereInput = {};
|
||||
// If user is not ADMIN, return only his data.
|
||||
if (!isAdmin) where.members = { some: { userId } };
|
||||
|
||||
@@ -5,6 +5,7 @@ import stripe from "@calcom/app-store/stripepayment/lib/server";
|
||||
import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { MembershipRole } from "@calcom/prisma/enums";
|
||||
|
||||
import { schemaMembershipPublic } from "~/lib/validations/membership";
|
||||
@@ -78,7 +79,7 @@ import { schemaTeamCreateBodyParams, schemaTeamReadPublic } from "~/lib/validati
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { prisma, body, userId, isAdmin } = req;
|
||||
const { body, userId, isAdmin } = req;
|
||||
const { ownerId, ...data } = schemaTeamCreateBodyParams.parse(body);
|
||||
|
||||
await checkPermissions(req);
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { NextApiRequest } from "next";
|
||||
import { deleteUser } from "@calcom/features/users/lib/userDeletionService";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryUserId } from "~/lib/validations/shared/queryUserId";
|
||||
|
||||
@@ -37,7 +38,7 @@ import { schemaQueryUserId } from "~/lib/validations/shared/queryUserId";
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
export async function deleteHandler(req: NextApiRequest) {
|
||||
const { prisma, isAdmin } = req;
|
||||
const { isAdmin } = req;
|
||||
const query = schemaQueryUserId.parse(req.query);
|
||||
// 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: 403, message: "Forbidden" });
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryUserId } from "~/lib/validations/shared/queryUserId";
|
||||
import { schemaUserReadPublic } from "~/lib/validations/user";
|
||||
@@ -37,7 +38,7 @@ import { schemaUserReadPublic } from "~/lib/validations/user";
|
||||
* description: User was not found
|
||||
*/
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const { prisma, isAdmin } = req;
|
||||
const { isAdmin } = req;
|
||||
|
||||
const query = schemaQueryUserId.parse(req.query);
|
||||
// Here we only check for ownership of the user if the user is not admin, otherwise we let ADMIN's edit any user
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaQueryUserId } from "~/lib/validations/shared/queryUserId";
|
||||
import { schemaUserEditBodyParams, schemaUserReadPublic } from "~/lib/validations/user";
|
||||
@@ -94,7 +95,7 @@ import { schemaUserEditBodyParams, schemaUserReadPublic } from "~/lib/validation
|
||||
* description: Insufficient permissions to access resource.
|
||||
*/
|
||||
export async function patchHandler(req: NextApiRequest) {
|
||||
const { prisma, isAdmin } = req;
|
||||
const { isAdmin } = req;
|
||||
const query = schemaQueryUserId.parse(req.query);
|
||||
// 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: 403, message: "Forbidden" });
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { Prisma } from "@prisma/client";
|
||||
import type { NextApiRequest } from "next";
|
||||
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { withMiddleware } from "~/lib/helpers/withMiddleware";
|
||||
import { schemaQuerySingleOrMultipleUserEmails } from "~/lib/validations/shared/queryUserEmail";
|
||||
@@ -44,7 +45,6 @@ import { schemaUsersReadPublic } from "~/lib/validations/user";
|
||||
export async function getHandler(req: NextApiRequest) {
|
||||
const {
|
||||
userId,
|
||||
prisma,
|
||||
isAdmin,
|
||||
pagination: { take, skip },
|
||||
} = req;
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { NextApiRequest } from "next";
|
||||
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { defaultResponder } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { schemaUserCreateBodyParams } from "~/lib/validations/user";
|
||||
|
||||
@@ -87,7 +88,7 @@ import { schemaUserCreateBodyParams } from "~/lib/validations/user";
|
||||
* description: Authorization information is missing or invalid.
|
||||
*/
|
||||
async function postHandler(req: NextApiRequest) {
|
||||
const { prisma, isAdmin } = req;
|
||||
const { isAdmin } = req;
|
||||
// If user is not ADMIN, return unauthorized.
|
||||
if (!isAdmin) throw new HttpError({ statusCode: 401, message: "You are not authorized" });
|
||||
const data = await schemaUserCreateBodyParams.parseAsync(req.body);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user