-
Notifications
You must be signed in to change notification settings - Fork 11.6k
chore: Sync Services to update external tools #3814
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1e3308a
d55d5d3
73d5d27
4d1c09c
1b9469d
761f18e
0f29f1e
6bb2991
a643736
8964274
ab789d5
da7cf23
34705e0
ee41a4b
657bcc8
6b0efbf
442f068
21e2bfd
4db9cff
ba55ea1
33ae79e
b82bb95
10b2b68
0154340
8088768
0719cea
88394a5
56c7ae3
1e6c3f9
ade1890
fe82fcb
f4b28fd
188afc0
eeaf865
bf5a221
d7e532e
74a5499
563310a
0699187
25f91d4
fdd01ee
7b61fd0
1c29518
51df1db
239e43f
c9ff368
66859af
44f75af
72c3397
bce1609
da825d7
c19a3d6
91d84d3
4accdd0
d9e4d5e
fb49252
0eea4ec
79e90b5
f3a3c32
53c7f15
a784f1a
1a245ec
b129292
12c4004
4327134
02385f0
ab4135d
970063a
0161856
44c37d6
45ea0dd
679ddad
8d8fe6e
10d5550
7b7ae7e
8b597c4
69b8d3e
b1174a4
8d648e6
b1abd74
1922d91
8acb1dd
4530b93
f6c46e4
d361db8
73a48c8
f830426
268b994
e557950
c283eac
9fc920e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -130,3 +130,9 @@ EMAIL_SERVER_PASSWORD='<office365_password>' | |
|
|
||
| # Set the following value to true if you wish to enable Team Impersonation | ||
| NEXT_PUBLIC_TEAM_IMPERSONATION=false | ||
|
|
||
| # Close.com internal CRM | ||
| CLOSECOM_API_KEY= | ||
|
|
||
| # Sendgrid internal email sender | ||
| SENDGRID_API_KEY= | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are the ones I mentioned @zomars, only for internal use and available for any self-hoster who wants to track down key info from their users in Sendgrid and Close.com |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,6 +97,7 @@ | |
| "nodemailer": "^6.7.7", | ||
| "otplib": "^12.0.1", | ||
| "qrcode": "^1.5.1", | ||
| "raw-body": "^2.5.1", | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Used to calculate the signature from the request from Help Scout in its dedicated API |
||
| "react": "^18.2.0", | ||
| "react-colorful": "^5.5.1", | ||
| "react-date-picker": "^8.3.6", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,7 @@ import isOutOfBounds, { BookingDateInPastError } from "@calcom/lib/isOutOfBounds | |
| import logger from "@calcom/lib/logger"; | ||
| import { getLuckyUser } from "@calcom/lib/server"; | ||
| import { defaultResponder } from "@calcom/lib/server"; | ||
| import { updateWebUser as syncServicesUpdateWebUser } from "@calcom/lib/sync/SyncServiceManager"; | ||
| import prisma, { userSelect } from "@calcom/prisma"; | ||
| import { extendedBookingCreateBody } from "@calcom/prisma/zod-utils"; | ||
| import type { BufferedBusyTime } from "@calcom/types/BufferedBusyTime"; | ||
|
|
@@ -673,6 +674,14 @@ async function handler(req: NextApiRequest) { | |
| let booking: Booking | null = null; | ||
| try { | ||
| booking = await createBooking(); | ||
| // Sync Services | ||
| await syncServicesUpdateWebUser( | ||
| currentUser && | ||
| (await prisma.user.findFirst({ | ||
| where: { id: currentUser.id }, | ||
| select: { id: true, email: true, name: true, plan: true, username: true, createdDate: true }, | ||
| })) | ||
| ); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updating sync services when a new booking is created, in order to make it update last booking custom field. |
||
| evt.uid = booking?.uid ?? null; | ||
| } catch (_err) { | ||
| const err = getErrorFromUnknown(_err); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| import { createHmac } from "crypto"; | ||
| import type { NextApiRequest, NextApiResponse } from "next"; | ||
| import getRawBody from "raw-body"; | ||
| import z from "zod"; | ||
|
|
||
| import { default as webPrisma } from "@calcom/prisma"; | ||
|
|
||
| export const config = { | ||
| api: { | ||
| bodyParser: false, | ||
| }, | ||
| }; | ||
|
|
||
| const helpscoutRequestBodySchema = z.object({ | ||
| customer: z.object({ | ||
| email: z.string().email(), | ||
| }), | ||
| }); | ||
|
|
||
| /** | ||
| * API for Helpscout to retrieve key information about a user from a ticket | ||
| * Note: HelpScout expects a JSON with a `html` prop to show its content as HTML | ||
| */ | ||
| export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
| if (req.method !== "POST") return res.status(405).json({ message: "Method not allowed" }); | ||
|
|
||
| const hsSignature = req.headers["x-helpscout-signature"]; | ||
| if (!hsSignature) return res.status(400).end(); | ||
|
|
||
| if (!process.env.CALENDSO_ENCRYPTION_KEY) return res.status(500).end(); | ||
|
|
||
| const rawBody = await getRawBody(req); | ||
| const parsedBody = helpscoutRequestBodySchema.safeParse(JSON.parse(rawBody.toString())); | ||
|
|
||
| if (!parsedBody.success) return res.status(400).end(); | ||
|
|
||
| const calculatedSig = createHmac("sha1", process.env.CALENDSO_ENCRYPTION_KEY) | ||
| .update(rawBody) | ||
| .digest("base64"); | ||
|
|
||
| if (req.headers["x-helpscout-signature"] !== calculatedSig) return res.status(400).end(); | ||
|
|
||
| const user = await webPrisma.user.findFirst({ | ||
| where: { | ||
| email: parsedBody.data.customer.email, | ||
| }, | ||
| select: { | ||
| username: true, | ||
| id: true, | ||
| plan: true, | ||
| createdDate: true, | ||
| }, | ||
| }); | ||
|
|
||
| if (!user) return res.status(200).json({ html: "User not found" }); | ||
|
|
||
| const lastBooking = await webPrisma.attendee.findFirst({ | ||
| where: { | ||
| email: parsedBody.data.customer.email, | ||
| }, | ||
| select: { | ||
| booking: { | ||
| select: { | ||
| createdAt: true, | ||
| }, | ||
| }, | ||
| }, | ||
| orderBy: { | ||
| booking: { | ||
| createdAt: "desc", | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| return res.status(200).json({ | ||
| html: ` | ||
| <ul> | ||
| <li><b>Username:</b> ${user.username}</li> | ||
| <li><b>Last booking:</b> ${ | ||
| lastBooking && lastBooking.booking | ||
| ? new Date(lastBooking.booking.createdAt).toLocaleDateString("en-US") | ||
| : "No info" | ||
| }</li> | ||
| <li><b>Plan:</b> ${user.plan}</li> | ||
| <li><b>Account created:</b> ${new Date(user.createdDate).toLocaleDateString("en-US")}</li> | ||
| </ul> | ||
| `, | ||
| }); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are needed if you want to hook up Sendgrid and Close.com Sync Services. It remains optional for any self-hoster. Documentation will be done to explain Sync Services and its purpose.