Skip to content

Commit

Permalink
feat: add Zoom oauth app type and default Zoom Oauth App (#1165)
Browse files Browse the repository at this point in the history
* init commit for default zoom oauth app

* Update Zoom OauthTYpeApp Icon. run pnpm run format for linting

* make each scope click-to-copy
  • Loading branch information
tybalex authored Jan 10, 2025
1 parent 6db580c commit c53d7d9
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 112 deletions.
1 change: 1 addition & 0 deletions apiclient/types/oauthapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const (
OAuthAppTypeGitHub OAuthAppType = "github"
OAuthAppTypeGoogle OAuthAppType = "google"
OAuthAppTypeSalesforce OAuthAppType = "salesforce"
OAuthAppTypeZoom OAuthAppType = "zoom"
OAuthAppTypeCustom OAuthAppType = "custom"
)

Expand Down
6 changes: 6 additions & 0 deletions pkg/gateway/types/oauth_apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ const (
GoogleTokenURL = "https://oauth2.googleapis.com/token"

GitHubAuthorizeURL = "https://github.com/login/oauth/authorize"

ZoomAuthorizeURL = "https://zoom.us/oauth/authorize"
ZoomTokenURL = "https://zoom.us/oauth/token"
)

var (
Expand Down Expand Up @@ -68,6 +71,9 @@ func ValidateAndSetDefaultsOAuthAppManifest(r *types.OAuthAppManifest, create bo
case types.OAuthAppTypeGitHub:
r.AuthURL = GitHubAuthorizeURL
r.TokenURL = GitHubTokenURL
case types.OAuthAppTypeZoom:
r.AuthURL = ZoomAuthorizeURL
r.TokenURL = ZoomTokenURL
case types.OAuthAppTypeSalesforce:
salesforceAuthorizeFragment := "/services/oauth2/authorize"
salesforceTokenFragment := "/services/oauth2/token"
Expand Down
18 changes: 10 additions & 8 deletions ui/admin/app/components/oauth-apps/OAuthAppTypeIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NotionLogoIcon } from "@radix-ui/react-icons";
import { KeyIcon } from "lucide-react";
import { BiLogoZoom } from "react-icons/bi";
import {
FaAtlassian,
FaGithub,
Expand All @@ -13,14 +14,15 @@ import { OAuthProvider } from "~/lib/model/oauthApps/oauth-helpers";
import { cn } from "~/lib/utils";

const IconMap = {
[OAuthProvider.Atlassian]: FaAtlassian,
[OAuthProvider.GitHub]: FaGithub,
[OAuthProvider.Slack]: FaSlack,
[OAuthProvider.Salesforce]: FaSalesforce,
[OAuthProvider.Google]: FaGoogle,
[OAuthProvider.Microsoft365]: FaMicrosoft,
[OAuthProvider.Notion]: NotionLogoIcon,
[OAuthProvider.Custom]: KeyIcon,
[OAuthProvider.Atlassian]: FaAtlassian,
[OAuthProvider.GitHub]: FaGithub,
[OAuthProvider.Slack]: FaSlack,
[OAuthProvider.Salesforce]: FaSalesforce,
[OAuthProvider.Google]: FaGoogle,
[OAuthProvider.Microsoft365]: FaMicrosoft,
[OAuthProvider.Notion]: NotionLogoIcon,
[OAuthProvider.Zoom]: BiLogoZoom,
[OAuthProvider.Custom]: KeyIcon,
};

export function OAuthAppTypeIcon({
Expand Down
20 changes: 11 additions & 9 deletions ui/admin/app/lib/model/oauthApps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ import { Microsoft365OAuthApp } from "~/lib/model/oauthApps/providers/microsoft3
import { NotionOAuthApp } from "~/lib/model/oauthApps/providers/notion";
import { SalesforceOAuthApp } from "~/lib/model/oauthApps/providers/salesforce";
import { SlackOAuthApp } from "~/lib/model/oauthApps/providers/slack";
import { ZoomOAuthApp } from "~/lib/model/oauthApps/providers/zoom";
import { EntityMeta } from "~/lib/model/primitives";

export const OAuthAppSpecMap = {
[OAuthProvider.Atlassian]: AtlassianOAuthApp,
[OAuthProvider.GitHub]: GitHubOAuthApp,
[OAuthProvider.Google]: GoogleOAuthApp,
[OAuthProvider.Microsoft365]: Microsoft365OAuthApp,
[OAuthProvider.Slack]: SlackOAuthApp,
[OAuthProvider.Salesforce]: SalesforceOAuthApp,
[OAuthProvider.Notion]: NotionOAuthApp,
// Custom OAuth apps are intentionally omitted from the map.
// They are handled separately
[OAuthProvider.Atlassian]: AtlassianOAuthApp,
[OAuthProvider.GitHub]: GitHubOAuthApp,
[OAuthProvider.Google]: GoogleOAuthApp,
[OAuthProvider.Microsoft365]: Microsoft365OAuthApp,
[OAuthProvider.Slack]: SlackOAuthApp,
[OAuthProvider.Salesforce]: SalesforceOAuthApp,
[OAuthProvider.Notion]: NotionOAuthApp,
[OAuthProvider.Zoom]: ZoomOAuthApp,
// Custom OAuth apps are intentionally omitted from the map.
// They are handled separately
} as const;

export type OAuthAppDetail = OAuthAppSpec & {
Expand Down
17 changes: 9 additions & 8 deletions ui/admin/app/lib/model/oauthApps/oauth-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { ZodObject, ZodType } from "zod";
import { ApiUrl } from "~/lib/routers/baseRouter";

export const OAuthProvider = {
Atlassian: "atlassian",
GitHub: "github",
Google: "google",
Microsoft365: "microsoft365",
Slack: "slack",
Salesforce: "salesforce",
Notion: "notion",
Custom: "custom",
Atlassian: "atlassian",
GitHub: "github",
Google: "google",
Microsoft365: "microsoft365",
Slack: "slack",
Salesforce: "salesforce",
Notion: "notion",
Zoom: "zoom",
Custom: "custom",
} as const;
export type OAuthProvider = (typeof OAuthProvider)[keyof typeof OAuthProvider];

Expand Down
174 changes: 87 additions & 87 deletions ui/admin/app/lib/model/oauthApps/providers/atlassian.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,93 +13,93 @@ const schema = z.object({
});

const steps: OAuthFormStep<typeof schema.shape>[] = [
{
type: "markdown",
text:
"### Step 1: Create a new Atlassian OAuth 2.0 Integration\n" +
"- Navigate to [Create a new OAuth 2.0 (3LO) integration](https://developer.atlassian.com/console/myapps/create-3lo-app)\n" +
"- Enter `Obot` as the integration name.\n" +
"- Click the checkbox to the terms and conditions.\n" +
"- Click the `Create` button.\n",
},
{
type: "markdown",
text:
"### Step 2: Configure OAuth Scopes\n" +
"Configure required OAuth Scopes by completing both sections below.\n",
},
{
type: "sectionGroup",
sections: [
{
title: "User identity API Scopes",
steps: [
{
type: "markdown",
text:
"- Navigate to the `Permissions` tab in the sidebar.\n" +
"- Click on the `Add` button for `User identity API`\n" +
"- Click on the `Configure` button for `User identity API`\n" +
"- Click on the `Edit Scopes` button to open the `Edit User identity API` modal.\n" +
"- Click the checkboxes to select the `read:me` and `read:account` scopes.\n" +
"- Click on the `Save` button.\n",
},
],
},
{
title: "Jira API Scopes",
steps: [
{
type: "markdown",
text:
"- Navigate to the `Permissions` tab in the sidebar.\n" +
"- Click on the `Add` button for `Jira API`\n" +
"- Click on the `Configure` button for `Jira API`\n" +
"- Click on the `Edit Scopes` button to open the `Edit Jira API` modal.\n" +
"- Click the checkboxes to select the `read:jira-work`, `write:jira-work`, and `read:jira-user` scopes.\n" +
"- Click on the `Save` button.\n",
},
],
},
],
},
{
type: "markdown",
text:
"### Step 3: Configure your OAuth Consent Screen\n" +
"- Navigate to the `Authorization` tab in the sidebar.\n" +
"- Click on the `Add` button for `OAuth 2.0 (3LO)`.\n" +
"- Enter the URL below in the `Callback URL` box and click on the `Save changes` button:\n",
},
{
type: "copy",
text: getOAuthLinks("atlassian").redirectURL,
},
{
type: "markdown",
text:
"### Step 4: Register your OAuth App credentials with Obot\n" +
"- Navigate to the `Settings` tab in the sidebar.\n" +
"- Enter the `Client ID` and `Client Secret` from the `Authentication details` section into the fields below\n",
},
{ type: "input", input: "clientID", label: "Client ID" },
{
type: "input",
input: "clientSecret",
label: "Client Secret",
inputType: "password",
},
{
type: "markdown",
text:
"### (Optional): Make Your OAuth App Public\n" +
"By default, your OAuth App is private. When users authorize their account with your app, they will see a warning like: `Make sure you trust [Your App Name]`. To remove this warning, follow these steps to make your app public:\n" +
"- Navigate to the `Distribution` tab in the sidebar\n" +
"- Click on `Edit` button and change the `DISTRIBUTION STATUS` of your app to `Sharing`.\n" +
"- Fill in the required vendor and security details in the same window\n" +
"- Once you've completed the required details, click the **Save Changes** button\n" +
"Your app is now public, and users will no longer see the warning message.\n",
},
{
type: "markdown",
text:
"### Step 1: Create a new Atlassian OAuth 2.0 Integration\n" +
"- Navigate to [Create a new OAuth 2.0 (3LO) integration](https://developer.atlassian.com/console/myapps/create-3lo-app)\n" +
"- Enter `Obot` as the integration name.\n" +
"- Click the checkbox to the terms and conditions.\n" +
"- Click the `Create` button.\n",
},
{
type: "markdown",
text:
"### Step 2: Configure OAuth Scopes\n" +
"Configure required OAuth Scopes by completing both sections below.\n",
},
{
type: "sectionGroup",
sections: [
{
title: "User identity API Scopes",
steps: [
{
type: "markdown",
text:
"- Navigate to the `Permissions` tab in the sidebar.\n" +
"- Click on the `Add` button for `User identity API`\n" +
"- Click on the `Configure` button for `User identity API`\n" +
"- Click on the `Edit Scopes` button to open the `Edit User identity API` modal.\n" +
"- Click the checkboxes to select the `read:me` and `read:account` scopes.\n" +
"- Click on the `Save` button.\n",
},
],
},
{
title: "Jira API Scopes",
steps: [
{
type: "markdown",
text:
"- Navigate to the `Permissions` tab in the sidebar.\n" +
"- Click on the `Add` button for `Jira API`\n" +
"- Click on the `Configure` button for `Jira API`\n" +
"- Click on the `Edit Scopes` button to open the `Edit Jira API` modal.\n" +
"- Click the checkboxes to select the `read:jira-work`, `write:jira-work`, and `read:jira-user` scopes.\n" +
"- Click on the `Save` button.\n",
},
],
},
],
},
{
type: "markdown",
text:
"### Step 3: Configure your OAuth Consent Screen\n" +
"- Navigate to the `Authorization` tab in the sidebar.\n" +
"- Click on the `Add` button for `OAuth 2.0 (3LO)`.\n" +
"- Enter the URL below in the `Callback URL` box and click on the `Save changes` button:\n",
},
{
type: "copy",
text: getOAuthLinks("atlassian").redirectURL,
},
{
type: "markdown",
text:
"### Step 4: Register your OAuth App credentials with Obot\n" +
"- Navigate to the `Settings` tab in the sidebar.\n" +
"- Enter the `Client ID` and `Client Secret` from the `Authentication details` section into the fields below\n",
},
{ type: "input", input: "clientID", label: "Client ID" },
{
type: "input",
input: "clientSecret",
label: "Client Secret",
inputType: "password",
},
{
type: "markdown",
text:
"### (Optional): Make Your OAuth App Public\n" +
"By default, your OAuth App is private. When users authorize your atlassian app to access their account, they will see a warning like: `Make sure you trust [Your App Name]`. To remove this warning, follow these steps to make your app public:\n" +
"- Navigate to the `Distribution` tab in the sidebar\n" +
"- Click on `Edit` button and change the `DISTRIBUTION STATUS` of your app to `Sharing`.\n" +
"- Fill in the required vendor and security details in the same window\n" +
"- Once you've completed the required details, click the **Save Changes** button.\n" +
"\nYour app is now public, and users will no longer see the warning message.\n",
},
];

export const AtlassianOAuthApp = {
Expand Down
97 changes: 97 additions & 0 deletions ui/admin/app/lib/model/oauthApps/providers/zoom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { z } from "zod";

import {
OAuthAppSpec,
OAuthFormStep,
getOAuthLinks,
} from "~/lib/model/oauthApps/oauth-helpers";
import { assetUrl } from "~/lib/utils";

const schema = z.object({
clientID: z.string().min(1, "Client ID is required"),
clientSecret: z.string().min(1, "Client Secret is required"),
});

const scopes = [
"user:read:user",
"meeting:read:summary",
"meeting:read:invitation",
"meeting:read:list_templates",
"meeting:read:meeting",
"meeting:read:list_upcoming_meetings",
"meeting:delete:meeting",
"meeting:update:meeting",
"meeting:write:meeting",
"meeting:read:list_meetings",
"cloud_recording:read:list_recording_files",
"cloud_recording:read:list_user_recordings",
];

const steps: OAuthFormStep<z.infer<typeof schema>>[] = [
{
type: "markdown",
text:
"### Step 1: Create a new app in Zoom App Marketplace\n" +
"If you already have an app, you can skip to Step 2.\n\n" +
"- Ensure you are logged into your preferred Zoom account.\n" +
"- From the [Zoom App Marketplace](https://marketplace.zoom.us/), hover over the **Develop** box on the top right corner and then select **Build App**.\n" +
"- When asked `What kind of app are you creating?` in the pop-up window, select **General App** and click **Create**.\n" +
"- Now You should be redirected to the **App Basic Information** page.\n" +
"- In the **Select how the app is managed** section, make sure it is set to **User-managed**.\n" +
"- Scroll down to the **Oauth Information** section, copy the url below and paste it into the **OAuth Redirect URL** field.\n",
},
{
type: "copy",
text: getOAuthLinks("zoom").redirectURL,
},
{
type: "markdown",
text: "- Click **Continue** at the bottom and then click **Scopes** on the left sidebar to continue.\n",
},
{
type: "markdown",
text:
"### Step 2: Configure the app's necessary scopes\n" +
"- From the [Zoom App Management Page](https://marketplace.zoom.us/user/build), click on the app you created and click **Scopes** on the left sidebar.\n" +
"(You will already be on this page if you've completed step 1)\n" +
"- Click on **Add Scopes** to add necessary scopes for the zoom tool. Ensure the following scopes are added:\n",
},
{
type: "sectionGroup",
sections: [
{
title: "Scopes: ",
displayStepsInline: true,
defaultOpen: true,
steps: scopes.map((scope) => ({
type: "copy",
text: scope,
})),
},
],
},
{
type: "markdown",
text:
"### Step 3: Register your App with Obot\n" +
"- **Client ID** and **Client Secret** can be found in the **App Credentials** box, located at the top of the left sidebar. Alternatively, you can find them in the **App Credentials** section of the **Basic Information** page.\n" +
"- Copy the **Client ID** and **Client Secret** and paste them into the respective fields below.\n",
},
{ type: "input", input: "clientID", label: "Client ID" },
{
type: "input",
input: "clientSecret",
label: "Client Secret",
inputType: "password",
},
];

export const ZoomOAuthApp = {
schema,
alias: "zoom",
type: "zoom",
displayName: "Zoom",
logo: assetUrl("/assets/zoom_logo.svg"),
steps: steps,
noGatewayIntegration: true,
} satisfies OAuthAppSpec;
Loading

0 comments on commit c53d7d9

Please sign in to comment.