Skip to content

Commit

Permalink
[mattermostGH-145] Add link to ephemeral message after uninstall
Browse files Browse the repository at this point in the history
  • Loading branch information
Paulo Barros committed Feb 9, 2020
1 parent 4de6a53 commit 21a11bf
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 59 deletions.
82 changes: 25 additions & 57 deletions server/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,60 +418,17 @@ If you see an option to create a Jira issue, you're all set! If not, refer to ou
return p.responsef(header, addResponseFormat, jiraURL, p.GetSiteURL(), ji.GetMattermostKey(), pkey)
}

// executeUninstallCloud will uninstall the jira cloud instance if the url matches, and then update all connected
// clients so that their Jira-related menu options are removed.
func executeUninstallCloud(p *Plugin, c *plugin.Context, header *model.CommandArgs, args ...string) *model.CommandResponse {
authorized, err := authorizedSysAdmin(p, header.UserId)
if err != nil {
return p.responsef(header, "%v", err)
}
if !authorized {
return p.responsef(header, "`/jira uninstall` can only be run by a System Administrator.")
}
if len(args) != 1 {
return p.help(header)
}

jiraURL, err := utils.NormalizeInstallURL(p.GetSiteURL(), args[0])
if err != nil {
return p.responsef(header, err.Error())
}

ji, err := p.currentInstanceStore.LoadCurrentJIRAInstance()
if err != nil {
return p.responsef(header, "No current Jira instance to uninstall")
}

jci, ok := ji.(*jiraCloudInstance)
if !ok {
return p.responsef(header, "The current Jira instance is not a cloud instance")
}

if jiraURL != jci.GetURL() {
return p.responsef(header, "You have entered an incorrect URL. The current Jira instance URL is: `"+jci.GetURL()+"`. Please enter the URL correctly to confirm the uninstall command.")
}

err = p.instanceStore.DeleteJiraInstance(jci.GetURL())
if err != nil {
return p.responsef(header, "Failed to delete Jira instance "+ji.GetURL())
}

// Notify users we have uninstalled an instance
p.API.PublishWebSocketEvent(
wSEventInstanceStatus,
map[string]interface{}{
"instance_installed": false,
"instance_type": "",
},
&model.WebsocketBroadcast{},
)

const uninstallInstructions = `Jira instance successfully disconnected. Go to **Settings > Apps > Manage Apps** to remove the application in your Jira Cloud instance.`

return p.responsef(header, uninstallInstructions)
return executeUninstall(p, c, header, "cloud", args...)
}

func executeUninstallServer(p *Plugin, c *plugin.Context, header *model.CommandArgs, args ...string) *model.CommandResponse {
return executeUninstall(p, c, header, "server", args...)
}

// executeUninstall will uninstall the jira instance if the url matches, and then update all connected clients
// so that their Jira-related menu options are removed.
func executeUninstall(p *Plugin, c *plugin.Context, header *model.CommandArgs, instanceType string, args ...string) *model.CommandResponse {
authorized, err := authorizedSysAdmin(p, header.UserId)
if err != nil {
return p.responsef(header, "%v", err)
Expand All @@ -493,16 +450,22 @@ func executeUninstallServer(p *Plugin, c *plugin.Context, header *model.CommandA
return p.responsef(header, "No current Jira instance to uninstall")
}

jsi, ok := ji.(*jiraServerInstance)
var ok bool
if instanceType == "cloud" {
_, ok = ji.(*jiraCloudInstance)
} else {
_, ok = ji.(*jiraServerInstance)
}

if !ok {
return p.responsef(header, "The current Jira instance is not a server instance")
return p.responsef(header, fmt.Sprintf("The current Jira instance is not a %s instance", instanceType))
}

if jiraURL != jsi.GetURL() {
return p.responsef(header, "You have entered an incorrect URL. The current Jira instance URL is: `"+jsi.GetURL()+"`. Please enter the URL correctly to confirm the uninstall command.")
if jiraURL != ji.GetURL() {
return p.responsef(header, `You have entered an incorrect URL. The current Jira instance URL is %s. Please enter the URL correctly to confirm the uninstall command.`, ji.GetURL())
}

err = p.instanceStore.DeleteJiraInstance(jsi.GetURL())
err = p.instanceStore.DeleteJiraInstance(ji.GetURL())
if err != nil {
return p.responsef(header, "Failed to delete Jira instance "+ji.GetURL())
}
Expand All @@ -517,9 +480,14 @@ func executeUninstallServer(p *Plugin, c *plugin.Context, header *model.CommandA
&model.WebsocketBroadcast{},
)

const uninstallInstructions = `Jira instance successfully disconnected. Go to **Settings > Applications > Application Links** to remove the application in your Jira Server or Data Center instance.`
var uninstallInstructions string
if instanceType == "cloud" {
uninstallInstructions = `Jira instance successfully disconnected. Go to [**Settings > Apps > Manage Apps**](%s/plugins/servlet/upm) to remove the application in your Jira Cloud instance.`
} else {
uninstallInstructions = `Jira instance successfully disconnected. Go to [**Settings > Applications > Application Links**](%s/plugins/servlet/applinks/listApplicationLinks) to remove the application in your Jira Server or Data Center instance.`
}

return p.responsef(header, uninstallInstructions)
return p.responsef(header, uninstallInstructions, jiraURL)
}

func executeUnassign(p *Plugin, c *plugin.Context, header *model.CommandArgs, args ...string) *model.CommandResponse {
Expand Down
73 changes: 71 additions & 2 deletions server/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package main

import (
"errors"
"strings"
"testing"

"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/plugin"
"github.com/mattermost/mattermost-server/v5/plugin/plugintest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"strings"
"testing"
)

const (
Expand Down Expand Up @@ -235,3 +236,71 @@ func TestPlugin_ExecuteCommand_Installation(t *testing.T) {
})
}
}

func TestPlugin_ExecuteCommand_Uninstall(t *testing.T) {
p := Plugin{}
tc := TestConfiguration{}
p.updateConfig(func(conf *config) {
conf.Secret = tc.Secret
})
api := &plugintest.API{}
siteURL := "https://somelink.com"
api.On("GetConfig").Return(&model.Config{ServiceSettings: model.ServiceSettings{SiteURL: &siteURL}})

sysAdminUser := &model.User{
Id: mockUserIDSysAdmin,
Roles: "system_admin",
}
api.On("GetUser", mockUserIDSysAdmin).Return(sysAdminUser, nil)
nonSysAdminUser := &model.User{
Id: mockUserIDNonSysAdmin,
Roles: "",
}
api.On("GetUser", mockUserIDNonSysAdmin).Return(nonSysAdminUser, nil)

tests := map[string]struct {
commandArgs *model.CommandArgs
expectedMsgPrefix string
}{
"no params - user is sys admin": {
commandArgs: &model.CommandArgs{Command: "/jira uninstall", UserId: mockUserIDSysAdmin},
expectedMsgPrefix: strings.TrimSpace(helpTextHeader + commonHelpText + sysAdminHelpText),
},
"no params - user is not sys admin": {
commandArgs: &model.CommandArgs{Command: "/jira uninstall", UserId: mockUserIDNonSysAdmin},
expectedMsgPrefix: strings.TrimSpace(helpTextHeader + commonHelpText),
},
"uninstall with invalid option": {
commandArgs: &model.CommandArgs{Command: "/jira uninstall foo", UserId: mockUserIDSysAdmin},
expectedMsgPrefix: strings.TrimSpace(helpTextHeader + commonHelpText + sysAdminHelpText),
},
"uninstall server instance without URL": {
commandArgs: &model.CommandArgs{Command: "/jira uninstall server", UserId: mockUserIDSysAdmin},
expectedMsgPrefix: strings.TrimSpace(helpTextHeader + commonHelpText + sysAdminHelpText),
},
"uninstall cloud instance without URL": {
commandArgs: &model.CommandArgs{Command: "/jira uninstall cloud", UserId: mockUserIDSysAdmin},
expectedMsgPrefix: strings.TrimSpace(helpTextHeader + commonHelpText + sysAdminHelpText),
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
isSendEphemeralPostCalled := false
currentTestAPI := api
currentTestAPI.On("SendEphemeralPost", mock.AnythingOfType("string"), mock.AnythingOfType("*model.Post")).Run(func(args mock.Arguments) {
isSendEphemeralPostCalled = true

post := args.Get(1).(*model.Post)
actual := strings.TrimSpace(post.Message)
assert.True(t, strings.HasPrefix(actual, tt.expectedMsgPrefix), "Expected returned message to start with: \n%s\nActual:\n%s", tt.expectedMsgPrefix, actual)
}).Once().Return(&model.Post{})

p.SetAPI(currentTestAPI)

cmdResponse, appError := p.ExecuteCommand(&plugin.Context{}, tt.commandArgs)
require.Nil(t, appError)
require.NotNil(t, cmdResponse)
assert.True(t, isSendEphemeralPostCalled)
})
}
}

0 comments on commit 21a11bf

Please sign in to comment.