diff --git a/actions/marketplace.js b/actions/marketplace.js
index 4c568e03ace9..763a8df19cf7 100644
--- a/actions/marketplace.js
+++ b/actions/marketplace.js
@@ -2,7 +2,6 @@
// See LICENSE.txt for license information.
import {Client4} from 'mattermost-redux/client';
-import {installPluginFromUrl} from 'mattermost-redux/actions/admin';
import {getFilter, getPlugin} from 'selectors/views/marketplace';
import {ActionTypes} from 'utils/constants';
@@ -31,7 +30,7 @@ export function fetchPlugins() {
// installPlugin installs the latest version of the given plugin from the marketplace.
//
// On success, it also requests the current state of the plugins to reflect the newly installed plugin.
-export function installPlugin(id) {
+export function installPlugin(id, version) {
return async (dispatch, getState) => {
dispatch({
type: ActionTypes.INSTALLING_MARKETPLACE_PLUGIN,
@@ -50,9 +49,9 @@ export function installPlugin(id) {
return;
}
- const downloadUrl = marketplacePlugin.download_url;
- const {error} = await dispatch(installPluginFromUrl(downloadUrl, true));
- if (error) {
+ try {
+ await Client4.installMarketplacePlugin(id, version);
+ } catch (error) {
dispatch({
type: ActionTypes.INSTALLING_MARKETPLACE_PLUGIN_FAILED,
id,
diff --git a/components/admin_console/plugin_management/__snapshots__/plugin_management.test.jsx.snap b/components/admin_console/plugin_management/__snapshots__/plugin_management.test.jsx.snap
index ba3a471af319..3a33fb71e9b1 100644
--- a/components/admin_console/plugin_management/__snapshots__/plugin_management.test.jsx.snap
+++ b/components/admin_console/plugin_management/__snapshots__/plugin_management.test.jsx.snap
@@ -61,6 +61,40 @@ exports[`components/PluginManagement should match snapshot 1`] = `
}
value={true}
/>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -271,6 +305,40 @@ exports[`components/PluginManagement should match snapshot when \`Enable Plugins
id="PluginSettings"
show={true}
>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -454,6 +522,284 @@ exports[`components/PluginManagement should match snapshot when \`Enable Plugins
`;
+exports[`components/PluginManagement should match snapshot when \`Require Signature Plugin\` is true 1`] = `
+
+
+`;
+
exports[`components/PluginManagement should match snapshot, No installed plugins 1`] = `
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -741,15 +1121,49 @@ exports[`components/PluginManagement should match snapshot, allow insecure URL e
}
helpText={
+ }
+ id="enable"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={true}
+ />
+
+ }
+ helpText={
+
}
- id="enable"
+ id="requirePluginSignature"
label={
}
@@ -762,7 +1176,7 @@ exports[`components/PluginManagement should match snapshot, allow insecure URL e
values={Object {}}
/>
}
- value={true}
+ value={false}
/>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -1224,6 +1672,40 @@ exports[`components/PluginManagement should match snapshot, text entered into th
}
value={true}
/>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -1468,6 +1950,40 @@ exports[`components/PluginManagement should match snapshot, upload disabled 1`]
}
value={true}
/>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -1712,6 +2228,40 @@ exports[`components/PluginManagement should match snapshot, with installed plugi
}
value={true}
/>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -2019,6 +2569,40 @@ exports[`components/PluginManagement should match snapshot, with installed plugi
}
value={true}
/>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -2294,6 +2878,40 @@ exports[`components/PluginManagement should match snapshot, with installed plugi
}
value={true}
/>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -2569,6 +3187,40 @@ exports[`components/PluginManagement should match snapshot, with installed plugi
}
value={true}
/>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
@@ -2844,6 +3496,40 @@ exports[`components/PluginManagement should match snapshot, with installed plugi
}
value={true}
/>
+
+ }
+ helpText={
+
+ }
+ id="requirePluginSignature"
+ label={
+
+ }
+ onChange={[Function]}
+ setByEnv={false}
+ trueText={
+
+ }
+ value={false}
+ />
diff --git a/components/admin_console/plugin_management/plugin_management.jsx b/components/admin_console/plugin_management/plugin_management.jsx
index c0af83c453ab..a79ab72dda78 100644
--- a/components/admin_console/plugin_management/plugin_management.jsx
+++ b/components/admin_console/plugin_management/plugin_management.jsx
@@ -5,6 +5,8 @@ import PropTypes from 'prop-types';
import React from 'react';
import {FormattedHTMLMessage, FormattedMessage} from 'react-intl';
import {Link} from 'react-router-dom';
+import classNames from 'classnames';
+
import PluginState from 'mattermost-redux/constants/plugins';
import * as Utils from 'utils/utils.jsx';
@@ -435,6 +437,7 @@ export default class PluginManagement extends AdminSettings {
config.PluginSettings.AllowInsecureDownloadUrl = this.state.allowInsecureDownloadUrl;
config.PluginSettings.EnableMarketplace = this.state.enableMarketplace;
config.PluginSettings.MarketplaceUrl = this.state.marketplaceUrl;
+ config.PluginSettings.RequirePluginSignature = this.state.requirePluginSignature;
return config;
}
@@ -446,6 +449,7 @@ export default class PluginManagement extends AdminSettings {
allowInsecureDownloadUrl: config.PluginSettings.AllowInsecureDownloadUrl,
enableMarketplace: config.PluginSettings.EnableMarketplace,
marketplaceUrl: config.PluginSettings.MarketplaceUrl,
+ requirePluginSignature: config.PluginSettings.RequirePluginSignature,
};
return state;
@@ -916,7 +920,7 @@ export default class PluginManagement extends AdminSettings {
defaultMessage='Upload a plugin for your Mattermost server. See [documentation](!https://about.mattermost.com/default-plugin-uploads) to learn more.'
/>
);
- } else if (enable === true && enableUploads === false) {
+ } else if (enable && !enableUploads) {
uploadHelpText = (
{this.renderEnablePluginsSetting()}
+
+ }
+ helpText={
+
+ }
+ value={this.state.requirePluginSignature}
+ disabled={!this.state.enable}
+ onChange={this.handleChange}
+ setByEnv={this.isSetByEnv('PluginSettings.RequirePluginSignature')}
+ />
+
{
AllowInsecureDownloadUrl: false,
EnableMarketplace: true,
MarketplaceUrl: 'marketplace.example.com',
+ RequirePluginSignature: false,
},
ExperimentalSettings: {
RestrictSystemAdmin: false,
@@ -135,6 +136,21 @@ describe('components/PluginManagement', () => {
expect(wrapper).toMatchSnapshot();
});
+ test('should match snapshot when `Require Signature Plugin` is true', () => {
+ const props = {
+ ...defaultProps,
+ config: {
+ ...defaultProps.config,
+ PluginSettings: {
+ ...defaultProps.config.PluginSettings,
+ RequirePluginSignature: true,
+ },
+ },
+ };
+ const wrapper = shallow( );
+ expect(wrapper).toMatchSnapshot();
+ });
+
test('should match snapshot, upload disabled', () => {
const props = {
...defaultProps,
diff --git a/components/plugin_marketplace/marketplace_item/__snapshots__/marketplace_item.test.js.snap b/components/plugin_marketplace/marketplace_item/__snapshots__/marketplace_item.test.js.snap
index 883251431bf6..bd3f5739ae9c 100644
--- a/components/plugin_marketplace/marketplace_item/__snapshots__/marketplace_item.test.js.snap
+++ b/components/plugin_marketplace/marketplace_item/__snapshots__/marketplace_item.test.js.snap
@@ -657,7 +657,7 @@ exports[`components/MarketplaceItem UpdateConfirmationModal should add extra war
,
release notes to learn about the changes included in this update."
id="marketplace_modal.list.update_confirmation.message.current_with_release_notes"
tagName="span"
values={
@@ -671,10 +671,15 @@ exports[`components/MarketplaceItem UpdateConfirmationModal should add extra war
- release notes before upgrading."
id="marketplace_modal.list.update_confirmation.message.warning_major_version_with_release_notes"
- values={Object {}}
+ tagName="span"
+ values={
+ Object {
+ "releaseNotesUrl": "http://example.com/release",
+ }
+ }
/>
,
]
diff --git a/components/plugin_marketplace/marketplace_item/marketplace_item.js b/components/plugin_marketplace/marketplace_item/marketplace_item.js
index ea1613a08c79..09126ed4a71d 100644
--- a/components/plugin_marketplace/marketplace_item/marketplace_item.js
+++ b/components/plugin_marketplace/marketplace_item/marketplace_item.js
@@ -122,7 +122,7 @@ export const UpdateConfirmationModal = ({show, name, version, installedVersion,
Release Notes to learn about the changes included in this update.`}
+ defaultMessage={`You currently have ${installedVersion} installed. View the release notes to learn about the changes included in this update.`}
values={{installedVersion, releaseNotesUrl}}
/>
@@ -154,9 +154,10 @@ export const UpdateConfirmationModal = ({show, name, version, installedVersion,
className='alert alert-warning'
key='warning'
>
- release notes before upgrading.`}
+ defaultMessage={`This update may contain breaking changes. Consult the release notes before upgrading.`}
+ values={{releaseNotesUrl}}
/>
);
@@ -236,7 +237,7 @@ export default class MarketplaceItem extends React.Component {
onInstall = () => {
trackEvent('plugins', 'ui_marketplace_download');
- this.props.actions.installPlugin(this.props.id);
+ this.props.actions.installPlugin(this.props.id, this.props.version);
}
showUpdateConfirmationModal = () => {
@@ -250,7 +251,7 @@ export default class MarketplaceItem extends React.Component {
onUpdate = () => {
trackEvent('plugins', 'ui_marketplace_download_update');
this.hideUpdateConfirmationModal();
- this.props.actions.installPlugin(this.props.id);
+ this.props.actions.installPlugin(this.props.id, this.props.version);
}
onConfigure = () => {
diff --git a/i18n/en.json b/i18n/en.json
index e39b370e3960..457a5b66000a 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1149,6 +1149,8 @@
"admin.plugins.settings.marketplaceUrl": "Marketplace URL:",
"admin.plugins.settings.marketplaceUrlDesc": "URL of the marketplace server.",
"admin.plugins.settings.marketplaceUrlDesc.empty": " Marketplace URL is a required field.",
+ "admin.plugins.settings.requirePluginSignature": "Require Plugin Signature:",
+ "admin.plugins.settings.requirePluginSignatureDesc": "When true, uploading plugins is disabled and may only be installed through the Marketplace. Plugins are always verified during Mattermost server startup and initialization. See [documentation](https://about.mattermost.com/) to learn more.",
"admin.privacy.showEmailDescription": "When false, hides the email address of members from everyone except System Administrators.",
"admin.privacy.showEmailTitle": "Show Email Address: ",
"admin.privacy.showFullNameDescription": "When false, hides the full name of members from everyone except System Administrators. Username is shown in place of full name.",
@@ -2714,10 +2716,10 @@
"marketplace_modal.list.update_available": "Update available:",
"marketplace_modal.list.update_confirmation.confirm_button": "Update",
"marketplace_modal.list.update_confirmation.message.current": "You currently have {installedVersion} installed.",
- "marketplace_modal.list.update_confirmation.message.current_with_release_notes": "You currently have {installedVersion} installed. View the Release Notes to learn about the changes included in this update.",
+ "marketplace_modal.list.update_confirmation.message.current_with_release_notes": "You currently have {installedVersion} installed. View the release notes to learn about the changes included in this update.",
"marketplace_modal.list.update_confirmation.message.intro": "Are you sure you want to update the {name} plugin to {version}?",
"marketplace_modal.list.update_confirmation.message.warning_major_version": "This update may contain breaking changes.",
- "marketplace_modal.list.update_confirmation.message.warning_major_version_with_release_notes": "This update may contain breaking changes. Consult the release notes before upgrading.",
+ "marketplace_modal.list.update_confirmation.message.warning_major_version_with_release_notes": "This update may contain breaking changes. Consult the release notes before upgrading.",
"marketplace_modal.list.update_confirmation.title": "Confirm Plugin Update",
"marketplace_modal.no_plugins": "There are no plugins available at this time.",
"marketplace_modal.no_plugins_installed": "You do not have any plugins installed.",
diff --git a/package-lock.json b/package-lock.json
index f5b5e629e6c6..851171bb9c14 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14323,8 +14323,8 @@
"integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg=="
},
"mattermost-redux": {
- "version": "github:mattermost/mattermost-redux#174e4403d0b6f9911f55e57b04d0bba806e55d9e",
- "from": "github:mattermost/mattermost-redux#174e4403d0b6f9911f55e57b04d0bba806e55d9e",
+ "version": "github:mattermost/mattermost-redux#aec5d7c636be6c562e64f0977c6c53b40b67beae",
+ "from": "github:mattermost/mattermost-redux#aec5d7c636be6c562e64f0977c6c53b40b67beae",
"requires": {
"form-data": "2.5.1",
"gfycat-sdk": "1.4.18",
diff --git a/package.json b/package.json
index 73bde58c4bb6..ac17ce8ac977 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
"localforage": "1.7.3",
"localforage-observable": "2.0.0",
"mark.js": "8.11.1",
- "mattermost-redux": "github:mattermost/mattermost-redux#174e4403d0b6f9911f55e57b04d0bba806e55d9e",
+ "mattermost-redux": "github:mattermost/mattermost-redux#aec5d7c636be6c562e64f0977c6c53b40b67beae",
"marked": "github:mattermost/marked#8214e10918264fb88cec474196023949f7cb4b30",
"moment-timezone": "0.5.27",
"pdfjs-dist": "2.0.489",