Skip to content

Commit

Permalink
[MM-676]: Fixed issue of meeting link being posted when user successf…
Browse files Browse the repository at this point in the history
…ully connects to MS Teams Meetings (#123)

* [MM-676]: Fixed the issue of meeting link being posted on connecting account

* [MM-676]: removed extra function call

* [MM-676]: Updated the successfull connection message

* [GH-676] Fixed issue reported by QA

---------

Co-authored-by: raghavaggarwal2308 <raghav.aggarwal@brightscout.com>
  • Loading branch information
Kshitij-Katiyar and raghavaggarwal2308 authored Aug 29, 2024
1 parent 13cc73b commit 3d3f8b5
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 28 deletions.
12 changes: 11 additions & 1 deletion server/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ func (p *Plugin) handleStart(args []string, extra *model.CommandArgs) (string, e

_, authErr := p.authenticateAndFetchUser(userID, extra.ChannelId)
if authErr != nil {
// the user state will be needed later while connecting the user to MS teams meeting via OAuth
if _, err := p.StoreState(userID, extra.ChannelId, false); err != nil {
p.API.LogWarn("failed to store user state", "error", err.Error())
}

return authErr.Message, authErr.Err
}

Expand All @@ -152,6 +157,11 @@ func (p *Plugin) handleConnect(args []string, extra *model.CommandArgs) (string,

msUser, authErr := p.authenticateAndFetchUser(extra.UserId, extra.ChannelId)
if authErr != nil {
// the user state will be needed later while connecting the user to MS teams meeting via OAuth
if _, err := p.StoreState(extra.UserId, extra.ChannelId, true); err != nil {
p.API.LogWarn("failed to store user state", "error", err.Error())
}

return authErr.Message, authErr.Err
}

Expand All @@ -172,7 +182,7 @@ func (p *Plugin) handleDisconnect(args []string, extra *model.CommandArgs) (stri
}

p.trackDisconnect(extra.UserId)
return "User disconnected from MS Teams Meetings.", nil
return "You have successfully disconnected from MS Teams Meetings.", nil
}

// ExecuteCommand is called when any registered by this plugin command is executed
Expand Down
51 changes: 34 additions & 17 deletions server/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"fmt"
"net/http"

"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/plugin"
"github.com/pkg/errors"
"golang.org/x/oauth2"
)

Expand Down Expand Up @@ -63,7 +63,7 @@ func (p *Plugin) connectUser(w http.ResponseWriter, r *http.Request) {
return
}

state, err := p.StoreState(userID, channelID)
state, err := p.GetState(getOAuthUserStateKey(userID))
if err != nil {
p.API.LogError("connectUser, failed to store user state", "UserID", userID, "Error", err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
Expand Down Expand Up @@ -99,7 +99,7 @@ func (p *Plugin) completeUserOAuth(w http.ResponseWriter, r *http.Request) {

state := r.URL.Query().Get("state")

key, userID, channelID, err := p.ParseState(state)
key, userID, channelID, justConnect, err := p.ParseState(state)
if err != nil {
p.API.LogDebug("complete oauth, cannot parse state", "error", err.Error())
http.Error(w, "invalid state", http.StatusBadRequest)
Expand Down Expand Up @@ -174,22 +174,8 @@ func (p *Plugin) completeUserOAuth(w http.ResponseWriter, r *http.Request) {
return
}

user, appErr := p.API.GetUser(userID)
if appErr != nil {
p.API.LogError("complete oauth, error getting MM user", "error", appErr.Error())
http.Error(w, appErr.Error(), http.StatusInternalServerError)
return
}

p.trackConnect(userID)

_, _, err = p.postMeeting(user, channelID, "")
if err != nil {
p.API.LogDebug(errors.Wrap(err, "error posting meeting").Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

html := `
<!DOCTYPE html>
<html>
Expand All @@ -203,6 +189,29 @@ func (p *Plugin) completeUserOAuth(w http.ResponseWriter, r *http.Request) {
</body>
</html>
`
if justConnect {
post := &model.Post{
UserId: p.botUserID,
ChannelId: channelID,
Message: "You have successfully connected to MS Teams Meetings.",
}

p.API.SendEphemeralPost(userID, post)
} else {
user, appErr := p.API.GetUser(userID)
if appErr != nil {
p.API.LogError("complete oauth, error getting MM user", "error", appErr.Error())
http.Error(w, appErr.Error(), http.StatusInternalServerError)
return
}

_, _, err = p.postMeeting(user, channelID, "")
if err != nil {
p.API.LogDebug("complete oauth, error posting meeting", "error", err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}

w.Header().Set("Content-Type", "text/html")
_, _ = w.Write([]byte(html))
Expand Down Expand Up @@ -269,10 +278,18 @@ func (p *Plugin) handleStartMeeting(w http.ResponseWriter, r *http.Request) {
if _, err = w.Write([]byte(`{"meeting_url": ""}`)); err != nil {
p.API.LogWarn("failed to write response", "error", err.Error())
}

if _, err = p.postConnect(req.ChannelID, userID); err != nil {
p.API.LogWarn("failed to create connect post", "error", err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

// the user state will be needed later while connecting the user to MS teams meeting via OAuth
if _, err = p.StoreState(userID, req.ChannelID, false); err != nil {
p.API.LogWarn("failed to store user state", "error", err.Error())
}

return
}

Expand Down
26 changes: 16 additions & 10 deletions server/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ import (
"errors"
"fmt"
"strings"

"github.com/mattermost/mattermost/server/public/model"
)

const (
stateLength = 3
stateLength = 4
trueString = "true"
msteamsMeetingStateKeyPrefix = "msteamsmeetinguserstate"
)

func (p *Plugin) StoreState(userID string, extra string) (string, error) {
key := fmt.Sprintf("%v_%v", model.NewId()[0:15], userID)
state := fmt.Sprintf("%v_%v", key, extra)
func (p *Plugin) StoreState(userID, channelID string, justConnect bool) (string, error) {
key := getOAuthUserStateKey(userID)
state := fmt.Sprintf("%v_%v_%v", key, channelID, justConnect)

appErr := p.API.KVSet(key, []byte(state))
if appErr != nil {
Expand All @@ -40,17 +40,23 @@ func (p *Plugin) DeleteState(key string) error {
return nil
}

func (p *Plugin) ParseState(state string) (key, userID, extra string, err error) {
func (p *Plugin) ParseState(state string) (key, userID, channelID string, justConnect bool, err error) {
stateComponents := strings.Split(state, "_")

if len(stateComponents) != stateLength {
p.API.LogDebug("complete oauth, state mismatch", "stateComponents", fmt.Sprintf("%v", stateComponents), "state", state)
return "", "", "", errors.New("status mismatch")
return "", "", "", false, errors.New("status mismatch")
}

key = fmt.Sprintf("%v_%v", stateComponents[0], stateComponents[1])
userID = stateComponents[1]
extra = stateComponents[2]
channelID = stateComponents[2]
justConnect = stateComponents[3] == trueString

return key, userID, channelID, justConnect, nil
}

return key, userID, extra, nil
// getOAuthUserStateKey generates and returns the key for storing the OAuth user state in the KV store.
func getOAuthUserStateKey(userID string) string {
return fmt.Sprintf("%v_%v", msteamsMeetingStateKeyPrefix, userID)
}

0 comments on commit 3d3f8b5

Please sign in to comment.