Skip to content

Commit

Permalink
[GH-283]: Fixed issue #283 'Removed the code for depreciated JWT' (#299)
Browse files Browse the repository at this point in the history
* [MI-3162]: Fixed issue #283 'Removed the code for depreciated JWT' (#6)

* [MI-3162]:Removed the code for depreciated JWT

* [MI-3162] Fixed some testcases

* [MI-3162]:Fixed the test cases

* [MI-3162]:Fixed self review comments

* [MI-3162]:Fixed lint errors

---------

Co-authored-by: raghavaggarwal2308 <[email protected]>

* [MM-283]:Fixed review comments

* [MM-283]: Fixed review comment

* [MM-283]:Fixed review comments

* [MM-283]: Fixed help command.

---------

Co-authored-by: raghavaggarwal2308 <[email protected]>
Co-authored-by: Abhishek Verma <[email protected]>
Co-authored-by: Abhishek Verma <[email protected]>
  • Loading branch information
4 people authored Oct 27, 2023
1 parent 598725e commit 60b8447
Show file tree
Hide file tree
Showing 12 changed files with 38 additions and 231 deletions.
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,11 @@ Select **Done** and then save your app.
* If you're using a self-hosted private cloud or on-premises Zoom server, enter the **Zoom URL** and **Zoom API URL** for the Zoom server, for example `https://yourzoom.com` and `https://api.yourzoom.com/v2` respectively. Leave blank if you're using Zoom's vendor-hosted SaaS service.
* **Cloud Hosted?**
* Leave **Zoom API URL** and **Zoom URL** fields blank.
* How are your users connecting to Zoom?
* **OAuth?**
* Set **Enable OAuth** to `true`.
* Use the Client ID and Client Secret generated when configuring Zoom to fill in the fields **Zoom OAuth Client ID** and **Zoom OAuth Client Secret**.
* Select the **Regenerate** button next to the field **At Rest Token Encryption Key**.
* Make sure **Enable Password based authentication** is set to `false`.
* Ignore **API Key** and **API Secret** fields.

* Connect your users to Zoom using OAuth.
* Use the Client ID and Client Secret generated when configuring Zoom to fill in the fields **Zoom OAuth Client ID** and **Zoom OAuth Client Secret**.
* Select the **Regenerate** button next to the field **At Rest Token Encryption Key**.
* Make sure **Enable Password based authentication** is set to `false`.
* Ignore **API Key** and **API Secret** fields.
* If you are using Webhooks or Deauthorization, make sure you select the **Regenerate** button on **Webhook Secret** field.
* Select **Save**.

Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module github.com/mattermost/mattermost-plugin-zoom
go 1.15

require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/mattermost/mattermost-plugin-api v0.0.21
github.com/mattermost/mattermost-server/v6 v6.0.2
github.com/mholt/archiver/v3 v3.5.0
Expand Down
1 change: 0 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/dgoogauth v0.0.0-20190221195224-5a805980a5f3/go.mod h1:hEfFauPHz7+NnjR/yHJGhrKo1Za+zStgwUETx3yzqgY=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
Expand Down
27 changes: 0 additions & 27 deletions plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,6 @@
"placeholder": "https://api.zoom.us/v2",
"default": null
},
{
"key": "EnableOAuth",
"display_name": "Enable OAuth:",
"type": "bool",
"help_text": "When true, OAuth will be used as the authentication means with Zoom. \n When false, JWT will be used as the authentication means with Zoom. \n If you're currently using a JWT Zoom application and switch to OAuth, all users will need to connect their Zoom account using OAuth the next time they try to start a meeting. [More information](https://mattermost.gitbook.io/plugin-zoom/installation/zoom-configuration).",
"placeholder": "",
"default": true,
"hosting": "on-prem"
},
{
"key": "AccountLevelApp",
"display_name": "OAuth by Account Level App (Beta):",
Expand Down Expand Up @@ -83,24 +74,6 @@
"placeholder": "",
"default": null
},
{
"key": "APIKey",
"display_name": "API Key:",
"type": "text",
"help_text": "The API key generated by Zoom, used to create meetings and pull user data.",
"placeholder": "",
"default": null,
"hosting": "on-prem"
},
{
"key": "APISecret",
"display_name": "API Secret:",
"type": "text",
"help_text": "The API secret generated by Zoom for your API key.",
"placeholder": "",
"default": null,
"hosting": "on-prem"
},
{
"key": "WebhookSecret",
"display_name": "Webhook Secret:",
Expand Down
14 changes: 6 additions & 8 deletions server/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (p *Plugin) getCommand() (*model.Command, error) {
return nil, errors.Wrap(err, "failed to get icon data")
}

canConnect := p.configuration.EnableOAuth && !p.configuration.AccountLevelApp
canConnect := !p.configuration.AccountLevelApp

autoCompleteDesc := "Available commands: start, help, settings"
if canConnect {
Expand Down Expand Up @@ -101,7 +101,7 @@ func (p *Plugin) executeCommand(c *plugin.Context, args *model.CommandArgs) (str
case actionDisconnect:
return p.runDisconnectCommand(user)
case actionHelp, "":
return p.runHelpCommand()
return p.runHelpCommand(user)
case settings:
return p.runSettingCommand(args, strings.Fields(args.Command)[2:], user)
default:
Expand All @@ -110,9 +110,7 @@ func (p *Plugin) executeCommand(c *plugin.Context, args *model.CommandArgs) (str
}

func (p *Plugin) canConnect(user *model.User) bool {
return p.OAuthEnabled() && // we are not on JWT
(!p.configuration.AccountLevelApp || // we are on user managed app
user.IsSystemAdmin()) // admins can connect Account level apps
return !p.configuration.AccountLevelApp || user.IsSystemAdmin() // admins can connect Account level apps
}

func (p *Plugin) ExecuteCommand(c *plugin.Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) {
Expand Down Expand Up @@ -244,9 +242,9 @@ func (p *Plugin) runDisconnectCommand(user *model.User) (string, error) {
}

// runHelpCommand runs command to display help text.
func (p *Plugin) runHelpCommand() (string, error) {
func (p *Plugin) runHelpCommand(user *model.User) (string, error) {
text := starterText + strings.ReplaceAll(helpText+"\n"+settingHelpText, "|", "`")
if p.configuration.EnableOAuth {
if p.canConnect(user) {
text += "\n" + strings.ReplaceAll(oAuthHelpText, "|", "`")
}

Expand Down Expand Up @@ -276,7 +274,7 @@ func (p *Plugin) updateUserPersonalSettings(usePMIValue, userID string) *model.A

// getAutocompleteData retrieves auto-complete data for the "/zoom" command
func (p *Plugin) getAutocompleteData() *model.AutocompleteData {
canConnect := p.OAuthEnabled() && !p.configuration.AccountLevelApp
canConnect := !p.configuration.AccountLevelApp

available := "start, help, settings"
if canConnect {
Expand Down
41 changes: 6 additions & 35 deletions server/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (

"github.com/mattermost/mattermost-plugin-api/experimental/telemetry"
"github.com/pkg/errors"

"github.com/mattermost/mattermost-plugin-zoom/server/zoom"
)

const (
Expand All @@ -32,9 +30,6 @@ const (
type configuration struct {
ZoomURL string
ZoomAPIURL string
APIKey string
APISecret string
EnableOAuth bool
AccountLevelApp bool
OAuthClientID string
OAuthClientSecret string
Expand All @@ -57,25 +52,14 @@ func (c *configuration) Clone() *configuration {
// IsValid checks if all needed fields are set.
func (c *configuration) IsValid(isCloud bool) error {
switch {
case !c.EnableOAuth && !isCloud: // JWT for on-prem
switch {
case len(c.APIKey) == 0:
return errors.New("please configure APIKey")

case len(c.APISecret) == 0:
return errors.New("please configure APISecret")
}
case c.EnableOAuth || isCloud: // OAuth for either platform
switch {
case len(c.OAuthClientSecret) == 0:
return errors.New("please configure OAuthClientSecret")
case len(c.OAuthClientSecret) == 0:
return errors.New("please configure OAuthClientSecret")

case len(c.OAuthClientID) == 0:
return errors.New("please configure OAuthClientID")
case len(c.OAuthClientID) == 0:
return errors.New("please configure OAuthClientID")

case len(c.EncryptionKey) == 0:
return errors.New("please generate EncryptionKey from Zoom plugin settings")
}
case len(c.EncryptionKey) == 0:
return errors.New("please generate EncryptionKey from Zoom plugin settings")
}

if len(c.WebhookSecret) == 0 {
Expand Down Expand Up @@ -129,10 +113,6 @@ func (p *Plugin) setConfiguration(configuration *configuration) {
// OnConfigurationChange is invoked when configuration changes may have been made.
func (p *Plugin) OnConfigurationChange() error {
var configuration = new(configuration)
prevConfigEnableOAuth := false
if p.configuration != nil {
prevConfigEnableOAuth = p.configuration.EnableOAuth
}
prevConfigAccountLevelOAuth := false
if p.configuration != nil {
prevConfigAccountLevelOAuth = p.configuration.AccountLevelApp
Expand All @@ -148,7 +128,6 @@ func (p *Plugin) OnConfigurationChange() error {
}

p.setConfiguration(configuration)
p.jwtClient = zoom.NewJWTClient(p.getZoomAPIURL(), configuration.APIKey, configuration.APISecret)

enableDiagnostics := false
if config := p.API.GetConfig(); config != nil {
Expand All @@ -158,14 +137,6 @@ func (p *Plugin) OnConfigurationChange() error {
}
p.tracker = telemetry.NewTracker(p.telemetryClient, p.API.GetDiagnosticId(), p.API.GetServerVersion(), manifest.ID, manifest.Version, "zoom", enableDiagnostics)

if prevConfigEnableOAuth != p.configuration.EnableOAuth {
method := telemetryOauthModeJWT
if p.configuration.EnableOAuth {
method = telemetryOauthModeOauth
}

p.trackOAuthModeChange(method)
}
if prevConfigAccountLevelOAuth != p.configuration.AccountLevelApp {
method := telemetryOauthModeOauth
if p.configuration.AccountLevelApp {
Expand Down
18 changes: 0 additions & 18 deletions server/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ const (
type Plugin struct {
plugin.MattermostPlugin

jwtClient zoom.Client

client *pluginapi.Client

// botUserID of the created bot account.
Expand Down Expand Up @@ -101,8 +99,6 @@ func (p *Plugin) OnActivate() error {
return errors.Wrap(appErr, "couldn't set profile image")
}

p.jwtClient = zoom.NewJWTClient(p.getZoomAPIURL(), config.APIKey, config.APISecret)

p.telemetryClient, err = telemetry.NewRudderClient()
if err != nil {
p.API.LogWarn("telemetry client not started", "error", err.Error())
Expand Down Expand Up @@ -137,11 +133,6 @@ func (p *Plugin) registerSiteURL() error {
func (p *Plugin) getActiveClient(user *model.User) (zoom.Client, string, error) {
config := p.getConfiguration()

// JWT
if !p.OAuthEnabled() {
return p.jwtClient, "", nil
}

// OAuth Account Level
if config.AccountLevelApp {
message := "Zoom App not connected. Contact your System administrator."
Expand Down Expand Up @@ -262,12 +253,3 @@ func (p *Plugin) isCloudLicense() bool {
license := p.API.GetLicense()
return license != nil && license.Features != nil && license.Features.Cloud != nil && *license.Features.Cloud
}

func (p *Plugin) OAuthEnabled() bool {
config := p.getConfiguration()
if config.EnableOAuth {
return true
}

return p.isCloudLicense()
}
28 changes: 19 additions & 9 deletions server/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/oauth2"

"github.com/mattermost/mattermost-plugin-api/experimental/telemetry"
"github.com/mattermost/mattermost-server/v6/model"
Expand Down Expand Up @@ -52,6 +53,7 @@ func TestPlugin(t *testing.T) {
}
}
}))

defer ts.Close()

noAuthMeetingRequest := httptest.NewRequest("POST", "/api/v1/meetings", strings.NewReader("{\"channel_id\": \"thechannelid\"}"))
Expand Down Expand Up @@ -99,21 +101,27 @@ func TestPlugin(t *testing.T) {
ExpectedStatusCode: http.StatusUnauthorized,
HasPermissionToChannel: true,
},
"UnauthorizedChannelPermissions": {
Request: unauthorizedUserRequest,
ExpectedStatusCode: http.StatusInternalServerError,
HasPermissionToChannel: false,
},
} {
t.Run(name, func(t *testing.T) {
botUserID := "yei0BahL3cohya8vuaboShaeSi"

api := &plugintest.API{}

userInfo, err := json.Marshal(zoom.OAuthUserInfo{
OAuthToken: &oauth2.Token{
AccessToken: "2a41c3138d2187a756c51428f78d192e9b88dcf44dd62d1b081ace4ec2241e0a",
},
})

require.Nil(t, err)
api.On("GetLicense").Return(nil)
api.On("GetServerVersion").Return("6.2.0")

api.On("KVGet", "mmi_botid").Return([]byte(botUserID), nil)
api.On("KVGet", "zoomtoken_theuserid").Return(userInfo, nil)

api.On("SendEphemeralPost", "theuserid", mock.AnythingOfType("*model.Post")).Return(nil)

api.On("PatchBot", botUserID, mock.AnythingOfType("*model.BotPatch")).Return(nil, nil)

api.On("GetUser", "theuserid").Return(&model.User{
Expand All @@ -132,6 +140,7 @@ func TestPlugin(t *testing.T) {

api.On("KVSetWithExpiry", fmt.Sprintf("%v%v", postMeetingKey, 234), mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil)
api.On("KVSetWithExpiry", fmt.Sprintf("%v%v", postMeetingKey, 123), mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil)
api.On("KVSetWithExpiry", "zoomuserstate_theuserid", mock.AnythingOfType("[]uint8"), mock.AnythingOfType("int64")).Return(nil)

api.On("KVGet", fmt.Sprintf("%v%v", postMeetingKey, 234)).Return([]byte("thepostid"), nil)
api.On("KVGet", fmt.Sprintf("%v%v", postMeetingKey, 123)).Return([]byte("thepostid"), nil)
Expand Down Expand Up @@ -164,10 +173,11 @@ func TestPlugin(t *testing.T) {

p := Plugin{}
p.setConfiguration(&configuration{
ZoomAPIURL: ts.URL,
APIKey: "theapikey",
APISecret: "theapisecret",
WebhookSecret: "thewebhooksecret",
ZoomAPIURL: ts.URL,
WebhookSecret: "thewebhooksecret",
EncryptionKey: "4Su-mLR7N6VwC6aXjYhQoT0shtS9fKz+",
OAuthClientID: "clientid",
OAuthClientSecret: "clientsecret",
})
p.SetAPI(api)
p.tracker = telemetry.NewTracker(nil, "", "", "", "", "", false)
Expand Down
1 change: 0 additions & 1 deletion server/telemetry.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package main

const (
telemetryOauthModeJWT = "JWT"
telemetryOauthModeOauth = "Oauth"
telemetryOauthModeOauthAccountLevel = "Oauth Account Level"

Expand Down
1 change: 0 additions & 1 deletion server/webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
)

var testConfig = &configuration{
EnableOAuth: true,
OAuthClientID: "clientid",
OAuthClientSecret: "clientsecret",
EncryptionKey: "encryptionkey",
Expand Down
Loading

0 comments on commit 60b8447

Please sign in to comment.