Skip to content

Commit

Permalink
Implemented few review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
srkgupta committed Apr 4, 2023
1 parent 3ca9321 commit 6b5cfe2
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 37 deletions.
2 changes: 1 addition & 1 deletion server/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const commonHelpText = "\n" +
const sysAdminHelpText = "\n###### For System Administrators:\n" +
"Install Jira instances:\n" +
"* `/jira instance install cloud [jiraURL]` - Connect Mattermost to a Jira Cloud instance located at <jiraURL>\n" +
"* `/jira instance install cloud-oauth` - Connect Mattermost to a Jira Cloud instance using OAuth 2.0 located at <jiraURL>\n" +
"* `/jira instance install cloud-oauth [jiraURL]` - Connect Mattermost to a Jira Cloud instance using OAuth 2.0 located at <jiraURL>\n" +
"* `/jira instance install server [jiraURL]` - Connect Mattermost to a Jira Server or Data Center instance located at <jiraURL>\n" +
"Uninstall Jira instances:\n" +
"* `/jira instance uninstall cloud [jiraURL]` - Disconnect Mattermost from a Jira Cloud instance located at <jiraURL>\n" +
Expand Down
4 changes: 2 additions & 2 deletions server/instance_cloud_oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ func (ci *cloudOAuthInstance) getJiraCloudResourceID(client http.Client) (string
err = json.Unmarshal(contents, &resources)

if err != nil {
return "", fmt.Errorf("failed marshall: %s", err.Error())
return "", errors.Wrap(err, "failed to unmarshal JiraAccessibleResources")
}

// We return the first resource ID only
if len(resources) < 1 {
return "", errors.New("No resources available for this Jira Cloud Account")
return "", errors.New("No resources are available for this Jira Cloud Account.")
}

return resources[0].ID, nil
Expand Down
82 changes: 55 additions & 27 deletions server/setup_flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ const (
stepChooseEdition flow.Name = "choose-edition"
stepCloudAddedInstance flow.Name = "cloud-added"
stepCloudOAuthConfigure flow.Name = "cloud-oauth-configure"
stepCloudOAuthSetCallbackURL flow.Name = "cloud-oauth-callback"
stepCloudEnableDeveloperMode flow.Name = "cloud-enable-dev"
stepCloudUploadApp flow.Name = "cloud-upload-app"
stepInstalledJiraApp flow.Name = "installed-app"
Expand Down Expand Up @@ -73,7 +72,6 @@ func (p *Plugin) NewSetupFlow() *flow.Flow {

// Jira Cloud OAuth steps
p.stepCloudOAuthConfigure(),
p.stepCloudOAuthSetCallbackURL(),

// Jira server steps
p.stepServerAddAppLink(),
Expand Down Expand Up @@ -207,9 +205,24 @@ func (p *Plugin) stepChooseEdition() flow.Step {
}).
WithButton(
flow.Button{
Name: "Jira Cloud (OAuth 2.0)",
Color: flow.ColorPrimary,
OnClick: flow.Goto(stepCloudOAuthConfigure),
Name: "Jira Cloud (OAuth 2.0)",
Color: flow.ColorPrimary,
Dialog: &model.Dialog{
Title: "Enter your Jira Cloud URL",
IntroductionText: "Enter a Jira Cloud URL (typically, `https://yourorg.atlassian.net`), or just the organization part, `yourorg`",
SubmitLabel: "Continue",
Elements: []model.DialogElement{
{
DisplayName: "Jira Cloud organization",
Name: "url",
Type: "text",
// text, not URL since normally just the org name needs
// to be entered.
SubType: "text",
},
},
},
OnDialogSubmit: p.initCreateCloudOAuthInstance,
}).
WithButton(flow.Button{
Name: "Jira Server",
Expand Down Expand Up @@ -327,30 +340,33 @@ func (p *Plugin) stepCloudUploadApp() flow.Step {

func (p *Plugin) stepCloudOAuthConfigure() flow.Step {
return flow.NewStep(stepCloudOAuthConfigure).
WithPretext("##### :white_check_mark: Step 2(a): Register an OAuth 2.0 Application in Jira").
WithPretext("##### :white_check_mark: Step 2: Register an OAuth 2.0 Application in Jira").
WithText(fmt.Sprintf("Complete the following steps, then come back here to select **Configure**.\n\n"+
"1. Follow [these instructions](https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/#enabling-oauth-2-0--3lo-) to register an OAuth 2.0 application in Jira.\n"+
"2. Set the following values:\n"+
" - Name: `Mattermost Jira Plugin - <your company name>`\n"+
"3. Select **Permissions** in the left menu. Next to the JIRA API, select **Add**\n"+
"4. Then select **Configure** and ensure following scopes are selected:\n"+
" - Scopes: `%s`\n"+
"3. Copy the **Client ID** and **Secret** from the registered 0Auth Application's **Settings** page and keep it handy.\n", JiraScopes)).
"5. Select **Authorization** in the left menu.\n"+
"6. Next to OAuth 2.0 (3LO), select **Configure** and set the Callback URL as follows:\n"+
" {{.OAuthCompleteURL}}\n"+
"7. Click **Save Changes**.\n"+
"8. Select **Settings** in the left menu.\n"+
"9. Copy the **Client ID** and **Secret** and keep it handy.\n", JiraScopes)).
WithButton(flow.Button{
Name: "Configure",
Color: flow.ColorPrimary,
Dialog: &model.Dialog{
Title: "Configure your Jira Cloud OAuth 2.0",
IntroductionText: "Enter a Jira Cloud URL (typically, `https://yourorg.atlassian.net`), or just the organization part, `yourorg`",
SubmitLabel: "Continue",
Title: "Configure your Jira Cloud OAuth 2.0",
SubmitLabel: "Continue",
Elements: []model.DialogElement{
{
DisplayName: "Jira Cloud organization",
Name: "url",
Type: "text",
// text, not URL since normally just the org name needs
// to be entered.
SubType: "text",
Default: `{{.JiraURL}}`,
SubType: "text",
},
{
DisplayName: "Jira OAuth Client ID",
Expand All @@ -370,22 +386,10 @@ func (p *Plugin) stepCloudOAuthConfigure() flow.Step {
},
OnDialogSubmit: p.submitCreateCloudOAuthInstance,
}).
OnRender(p.trackSetupWizard("setup_wizard_cloud_oauth2_start", nil)).
OnRender(p.trackSetupWizard("setup_wizard_cloud_oauth2_configure", nil)).
WithButton(cancelButton)
}

func (p *Plugin) stepCloudOAuthSetCallbackURL() flow.Step {
return flow.NewStep(stepCloudOAuthSetCallbackURL).
WithPretext("##### :white_check_mark: Step 2(b): Set Callback URL in the Jira OAuth 2.0 app").
WithText("It is important that you correctly set the Callback URL in the Jira OAuth 2.0 app. Follow the below instructions:\n\n" +
"1. In the Jira Developer console, click on the OAuth 2.0 app you had created and select **Authorization** in the left menu.\n" +
"2. Next to OAuth 2.0 (3LO), select **Configure** and set the Callback URL as follows:\n" +
" `{{.OAuthCompleteURL}}`\n" +
"3. Click **Save Changes**.\n").
OnRender(p.trackSetupWizard("setup_wizard_cloud_oauth2_complete", nil)).
WithButton(continueButton(stepInstalledJiraApp))
}

func (p *Plugin) stepInstalledJiraApp() flow.Step {
next := func(to flow.Name) func(*flow.Flow) (flow.Name, flow.State, error) {
return func(f *flow.Flow) (flow.Name, flow.State, error) {
Expand Down Expand Up @@ -641,6 +645,30 @@ func (p *Plugin) submitCreateCloudInstance(f *flow.Flow, submission map[string]i
}, nil, nil
}

func (p *Plugin) initCreateCloudOAuthInstance(f *flow.Flow, submission map[string]interface{}) (flow.Name, flow.State, map[string]string, error) {
jiraURL, _ := submission["url"].(string)
if jiraURL == "" {
return "", nil, nil, errors.New("no Jira cloud URL in the request")
}
jiraURL = strings.TrimSpace(jiraURL)
if jiraOrgRegexp.MatchString(jiraURL) {
jiraURL = fmt.Sprintf("https://%s.atlassian.net", jiraURL)
}

jiraURL, instance, err := p.installCloudOAuthInstance(jiraURL, "", "")
if err != nil {
return "", nil, nil, err
}

return stepCloudOAuthConfigure, flow.State{
keyEdition: string(CloudOAuthInstanceType),
keyJiraURL: jiraURL,
keyInstance: instance,
keyOAuthCompleteURL: p.GetPluginURL() + instancePath(routeOAuth2Complete, types.ID(jiraURL)),
keyConnectURL: p.GetPluginURL() + instancePath(routeUserConnect, types.ID(jiraURL)),
}, nil, nil
}

func (p *Plugin) submitCreateCloudOAuthInstance(f *flow.Flow, submission map[string]interface{}) (flow.Name, flow.State, map[string]string, error) {
jiraURL, _ := submission["url"].(string)
if jiraURL == "" {
Expand All @@ -666,7 +694,7 @@ func (p *Plugin) submitCreateCloudOAuthInstance(f *flow.Flow, submission map[str
return "", nil, nil, err
}

return stepCloudOAuthSetCallbackURL, flow.State{
return stepInstalledJiraApp, flow.State{
keyEdition: string(CloudOAuthInstanceType),
keyJiraURL: jiraURL,
keyInstance: instance,
Expand Down
3 changes: 1 addition & 2 deletions webapp/src/components/modals/oauth_config_modal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {bindActionCreators} from 'redux';

import {isOAuthConfigModalVisible} from 'selectors';

import {openOAuthConfigModal, closeOAuthConfigModal, configureCloudOAuthInstance, handleInstallOAuthFlow} from 'actions';
import {closeOAuthConfigModal, configureCloudOAuthInstance, handleInstallOAuthFlow} from 'actions';

import OAuthConfigModal from './oauth_config_modal';

Expand All @@ -17,7 +17,6 @@ const mapStateToProps = (state) => {
};

const mapDispatchToProps = (dispatch) => bindActionCreators({
open: openOAuthConfigModal,
closeModal: closeOAuthConfigModal,
configure: configureCloudOAuthInstance,
handleInstallOAuthFlow,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('components/OAuthConfigModalForm', () => {
installedInstances: [
{
instance_id: 'https://something.atlassian.net',
type: InstanceType.CLOUD_OATH,
type: InstanceType.CLOUD_OAUTH,
},
],
};
Expand Down
4 changes: 3 additions & 1 deletion webapp/src/components/modals/oauth_config_modal/props.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

import {Theme} from 'mattermost-redux/types/preferences';

import {APIResponse, OAuthConfig, Instance} from 'types/model';

export type Props = {
theme: {};
theme: Theme;
visible: boolean;
installedInstances: Instance[];
addValidate: (isValid: () => boolean) => void;
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ export const instanceIsInstalled = (state): boolean => getInstalledInstances(sta
export const getDefaultUserInstanceID = (state) => getPluginState(state).defaultUserInstanceID;

export const getPluginSettings = (state) => getPluginState(state).pluginSettings;
export const isOAuthConfigModalVisible = (state) => getPluginState(state).oauthConfigModalVisible;
export const isOAuthConfigModalVisible = (state) => getPluginState(state).oauthConfigModalVisible;
4 changes: 2 additions & 2 deletions webapp/src/types/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export type ChannelSubscription = {
export enum InstanceType {
CLOUD = 'cloud',
SERVER = 'server',
CLOUD_OATH = 'cloud_oauth'
CLOUD_OAUTH = 'cloud_oauth'
}
export type Instance = {
alias?: string;
Expand Down Expand Up @@ -222,4 +222,4 @@ export type OAuthConfig = {
instance_url: string;
client_id: string;
client_secret: string;
}
}

0 comments on commit 6b5cfe2

Please sign in to comment.