-
Notifications
You must be signed in to change notification settings - Fork 8.4k
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
feat: Zoho Calendar #8144
feat: Zoho Calendar #8144
Changes from 7 commits
68ab3bf
3d7a699
8a51e76
c64440e
3d8c819
9ee3b12
6b861fd
b046b4e
e6c3772
10bf10d
d56a491
a91e12f
2cfc402
62c38e9
0e65ec8
86c235f
249b54c
29e7384
37518ee
5935818
735d9bf
436020e
0451429
0788823
6ce4754
1cb5334
86e00c6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. Auto-generated files shouldn't be committed. |
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. Auto-generated files shouldn't be committed. |
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. Auto-generated files shouldn't be committed. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
items: | ||
- /api/app-store/zohocalendar/ZCal1.jpg | ||
hariombalhara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
--- | ||
|
||
Zoho Calendar is an online business calendar that makes scheduling easy for you. You can use it to stay on top of your schedule and also share calendars with your team to keep everyone on the same page. | ||
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. @sydwardrae @Jaibles Please review App description |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import type { AppMeta } from "@calcom/types/App"; | ||
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. Replacing this file with config.json. It is deprecated and AppStore CLI doesn't create it. |
||
|
||
import _package from "./package.json"; | ||
|
||
export const metadata = { | ||
name: "Zoho Calendar", | ||
description: _package.description, | ||
installed: true, | ||
type: "zoho_calendar", | ||
title: "Zoho Calendar", | ||
imageSrc: "/api/app-store/zohocalendar/icon.svg", | ||
hariombalhara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
variant: "calendar", | ||
category: "calendar", | ||
categories: ["calendar"], | ||
logo: "/api/app-store/zohocalendar/icon.svg", | ||
hariombalhara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
publisher: "Cal.com", | ||
rating: 5, | ||
hariombalhara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
reviews: 69, | ||
hariombalhara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
slug: "zoho-calendar", | ||
trending: false, | ||
hariombalhara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
url: "https://cal.com/", | ||
verified: true, | ||
hariombalhara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
email: "[email protected]", | ||
dirName: "zohocalendar", | ||
hariombalhara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} as AppMeta; | ||
|
||
export default metadata; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next"; | ||
import { stringify } from "querystring"; | ||
import { z } from "zod"; | ||
|
||
import { WEBAPP_URL } from "@calcom/lib/constants"; | ||
|
||
import { encodeOAuthState } from "../../_utils/encodeOAuthState"; | ||
import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug"; | ||
|
||
const zohoKeysSchema = z.object({ | ||
client_id: z.string(), | ||
client_secret: z.string(), | ||
}); | ||
|
||
export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
if (req.method === "GET") { | ||
const appKeys = await getAppKeysFromSlug("zoho-calendar"); | ||
const { client_id } = zohoKeysSchema.parse(appKeys); | ||
|
||
const state = encodeOAuthState(req); | ||
|
||
const params = { | ||
client_id, | ||
response_type: "code", | ||
redirect_uri: WEBAPP_URL + "/api/integrations/zohocalendar/callback", | ||
scope: ["ZohoCalendar.calendar.ALL", "ZohoCalendar.event.ALL", "ZohoCalendar.freebusy.READ"], | ||
access_type: "offline", | ||
state, | ||
prompt: "consent", | ||
}; | ||
|
||
const query = stringify(params); | ||
|
||
res.status(200).json({ url: `https://accounts.zoho.com/oauth/v2/auth?${query}` }); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import type { NextApiRequest, NextApiResponse } from "next"; | ||
import { stringify } from "querystring"; | ||
import { z } from "zod"; | ||
|
||
import { WEBAPP_URL } from "@calcom/lib/constants"; | ||
import { getSafeRedirectUrl } from "@calcom/lib/getSafeRedirectUrl"; | ||
import logger from "@calcom/lib/logger"; | ||
import prisma from "@calcom/prisma"; | ||
|
||
import { decodeOAuthState } from "../../_utils/decodeOAuthState"; | ||
import getAppKeysFromSlug from "../../_utils/getAppKeysFromSlug"; | ||
import getInstalledAppPath from "../../_utils/getInstalledAppPath"; | ||
import type { ZohoAuthCredentials } from "../types/ZohoCalendar"; | ||
|
||
const log = logger.getChildLogger({ prefix: [`[[zohocalendar/api/callback]`] }); | ||
|
||
const zohoKeysSchema = z.object({ | ||
hariombalhara marked this conversation as resolved.
Show resolved
Hide resolved
|
||
client_id: z.string(), | ||
client_secret: z.string(), | ||
}); | ||
|
||
export default async function handler(req: NextApiRequest, res: NextApiResponse) { | ||
const { code } = req.query; | ||
const state = decodeOAuthState(req); | ||
|
||
if (code && typeof code !== "string") { | ||
res.status(400).json({ message: "`code` must be a string" }); | ||
return; | ||
} | ||
if (!req.session?.user?.id) { | ||
return res.status(401).json({ message: "You must be logged in to do this" }); | ||
} | ||
|
||
const appKeys = await getAppKeysFromSlug("zoho-calendar"); | ||
const { client_id, client_secret } = zohoKeysSchema.parse(appKeys); | ||
|
||
const params = { | ||
client_id, | ||
grant_type: "authorization_code", | ||
client_secret, | ||
redirect_uri: WEBAPP_URL + "/api/integrations/zohocalendar/callback", | ||
code, | ||
}; | ||
|
||
const query = stringify(params); | ||
|
||
const response = await fetch(`https://accounts.zoho.com/oauth/v2/token?${query}`, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json; charset=utf-8", | ||
}, | ||
}); | ||
|
||
const responseBody = await response.json(); | ||
console.log(responseBody); | ||
|
||
if (!response.ok || responseBody.error) { | ||
log.error("get access_token failed", responseBody); | ||
return res.redirect("/apps/installed?error=" + JSON.stringify(responseBody)); | ||
} | ||
|
||
const key: ZohoAuthCredentials = { | ||
access_token: responseBody.access_token, | ||
refresh_token: responseBody.refresh_token, | ||
expires_in: Math.round(+new Date() / 1000 + responseBody.expires_in), | ||
}; | ||
|
||
await prisma.credential.create({ | ||
data: { | ||
type: "zoho_calendar", | ||
key, | ||
userId: req.session.user.id, | ||
appId: "zoho-calendar", | ||
}, | ||
}); | ||
|
||
res.redirect( | ||
getSafeRedirectUrl(state?.returnTo) ?? getInstalledAppPath({ variant: "calendar", slug: "zoho-calendar" }) | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { default as add } from "./add"; | ||
export { default as callback } from "./callback"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import type { InstallAppButtonProps } from "@calcom/app-store/types"; | ||
|
||
import useAddAppMutation from "../../_utils/useAddAppMutation"; | ||
|
||
export default function InstallAppButton(props: InstallAppButtonProps) { | ||
const mutation = useAddAppMutation("zoho_calendar"); | ||
|
||
return ( | ||
<> | ||
{props.render({ | ||
onClick() { | ||
mutation.mutate(""); | ||
}, | ||
loading: mutation.isLoading, | ||
})} | ||
</> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default as InstallAppButton } from "./InstallAppButton"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * as api from "./api"; | ||
export * as lib from "./lib"; | ||
export { metadata } from "./_metadata"; |
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.
Auto-generated files shouldn't be committed.