]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14661 Restrict plugin installation to CE
authorJeremy Davis <jeremy.davis@sonarsource.com>
Mon, 12 Apr 2021 15:20:36 +0000 (17:20 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 15 Apr 2021 20:03:44 +0000 (20:03 +0000)
server/sonar-web/src/main/js/apps/marketplace/App.tsx
server/sonar-web/src/main/js/apps/marketplace/__tests__/App-test.tsx
server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/App-test.tsx.snap [new file with mode: 0644]

index 6c837133eb2d65d171689059b0007d809d0cc86f..bcb8929fcafd6ff24bce0defdb55e02b455c177c 100644 (file)
@@ -147,6 +147,15 @@ export class App extends React.PureComponent<Props, State> {
     const query = parseQuery(this.props.location.query);
     const filteredPlugins = filterPlugins(plugins, query.search);
 
+    /*
+     * standalone mode is true when cluster mode is not active. We preserve this
+     * condition if it ever becomes possible to have a community edition NOT in standalone mode.
+     */
+    const allowActions =
+      currentEdition === EditionKey.community &&
+      Boolean(standaloneMode) &&
+      riskConsent === RiskConsent.Accepted;
+
     return (
       <div className="page page-limited" id="marketplace-page">
         <Suggestions suggestions="marketplace" />
@@ -196,7 +205,7 @@ export class App extends React.PureComponent<Props, State> {
               <PluginsList
                 pending={pendingPlugins}
                 plugins={filteredPlugins}
-                readOnly={!standaloneMode || riskConsent !== RiskConsent.Accepted}
+                readOnly={!allowActions}
                 refreshPending={this.props.fetchPendingPlugins}
               />
               <Footer total={filteredPlugins.length} />
index e3e9e93bfd07040a67666db5a86d4f2e9bbebfe3..ea6e44561377c9e8f2c109061cc16a5cdbcf3f42 100644 (file)
@@ -28,6 +28,7 @@ import {
 } from '../../../api/plugins';
 import { getValues, setSimpleSettingValue } from '../../../api/settings';
 import { mockLocation, mockRouter } from '../../../helpers/testMocks';
+import { EditionKey } from '../../../types/editions';
 import { RiskConsent } from '../../../types/plugins';
 import { SettingsKey } from '../../../types/settings';
 import { App } from '../App';
@@ -56,6 +57,11 @@ it('should render correctly', async () => {
 
   await waitAndUpdate(wrapper);
   expect(wrapper).toMatchSnapshot('loaded');
+
+  wrapper.setProps({ currentEdition: EditionKey.community, standaloneMode: true });
+  wrapper.setState({ riskConsent: RiskConsent.Accepted });
+
+  expect(wrapper).toMatchSnapshot('not readonly');
 });
 
 it('should handle accepting the risk', async () => {
diff --git a/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/App-test.tsx.snap
new file mode 100644 (file)
index 0000000..495113f
--- /dev/null
@@ -0,0 +1,255 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: loaded 1`] = `
+<div
+  className="page page-limited"
+  id="marketplace-page"
+>
+  <Suggestions
+    suggestions="marketplace"
+  />
+  <Helmet
+    defer={true}
+    encodeSpecialCharacters={true}
+    title="marketplace.page"
+  />
+  <Header
+    currentEdition="developer"
+  />
+  <EditionBoxes
+    currentEdition="developer"
+  />
+  <header
+    className="page-header"
+  >
+    <h1
+      className="page-title"
+    >
+      marketplace.page.plugins
+    </h1>
+    <div
+      className="page-description"
+    >
+      <p>
+        marketplace.page.plugins.description
+      </p>
+      <p
+        className="spacer-top"
+      >
+        <FormattedMessage
+          defaultMessage="marketplace.page.plugins.description2"
+          id="marketplace.page.plugins.description2"
+          values={
+            Object {
+              "link": <Link
+                onlyActiveOnIndex={false}
+                style={Object {}}
+                target="_blank"
+                to="/documentation/instance-administration/marketplace/"
+              >
+                marketplace.page.plugins.description2.link
+              </Link>,
+            }
+          }
+        />
+      </p>
+    </div>
+  </header>
+  <PluginRiskConsentBox
+    acknowledgeRisk={[Function]}
+    currentEdition="developer"
+  />
+  <Search
+    query={
+      Object {
+        "filter": "all",
+        "search": "",
+      }
+    }
+    updateCenterActive={false}
+    updateQuery={[Function]}
+  />
+  <DeferredSpinner
+    loading={false}
+  >
+    <PluginsList
+      pending={
+        Object {
+          "installing": Array [],
+          "removing": Array [],
+          "updating": Array [],
+        }
+      }
+      plugins={
+        Array [
+          Object {
+            "key": "sonar-foo",
+            "name": "Sonar Foo",
+          },
+        ]
+      }
+      readOnly={true}
+      refreshPending={[MockFunction]}
+    />
+    <Footer
+      total={1}
+    />
+  </DeferredSpinner>
+</div>
+`;
+
+exports[`should render correctly: loading 1`] = `
+<div
+  className="page page-limited"
+  id="marketplace-page"
+>
+  <Suggestions
+    suggestions="marketplace"
+  />
+  <Helmet
+    defer={true}
+    encodeSpecialCharacters={true}
+    title="marketplace.page"
+  />
+  <Header
+    currentEdition="developer"
+  />
+  <EditionBoxes
+    currentEdition="developer"
+  />
+  <header
+    className="page-header"
+  >
+    <h1
+      className="page-title"
+    >
+      marketplace.page.plugins
+    </h1>
+    <div
+      className="page-description"
+    >
+      <p>
+        marketplace.page.plugins.description
+      </p>
+      <p
+        className="spacer-top"
+      >
+        <FormattedMessage
+          defaultMessage="marketplace.page.plugins.description2"
+          id="marketplace.page.plugins.description2"
+          values={
+            Object {
+              "link": <Link
+                onlyActiveOnIndex={false}
+                style={Object {}}
+                target="_blank"
+                to="/documentation/instance-administration/marketplace/"
+              >
+                marketplace.page.plugins.description2.link
+              </Link>,
+            }
+          }
+        />
+      </p>
+    </div>
+  </header>
+  <PluginRiskConsentBox
+    acknowledgeRisk={[Function]}
+    currentEdition="developer"
+  />
+  <Search
+    query={
+      Object {
+        "filter": "all",
+        "search": "",
+      }
+    }
+    updateCenterActive={false}
+    updateQuery={[Function]}
+  />
+  <DeferredSpinner
+    loading={true}
+  >
+    marketplace.plugin_list.no_plugins.all
+  </DeferredSpinner>
+</div>
+`;
+
+exports[`should render correctly: not readonly 1`] = `
+<div
+  className="page page-limited"
+  id="marketplace-page"
+>
+  <Suggestions
+    suggestions="marketplace"
+  />
+  <Helmet
+    defer={true}
+    encodeSpecialCharacters={true}
+    title="marketplace.page"
+  />
+  <Header
+    currentEdition="community"
+  />
+  <EditionBoxes
+    currentEdition="community"
+  />
+  <header
+    className="page-header"
+  >
+    <h1
+      className="page-title"
+    >
+      marketplace.page.plugins
+    </h1>
+    <div
+      className="page-description"
+    >
+      <p>
+        marketplace.page.plugins.description
+      </p>
+    </div>
+  </header>
+  <PluginRiskConsentBox
+    acknowledgeRisk={[Function]}
+    currentEdition="community"
+    riskConsent="ACCEPTED"
+  />
+  <Search
+    query={
+      Object {
+        "filter": "all",
+        "search": "",
+      }
+    }
+    updateCenterActive={false}
+    updateQuery={[Function]}
+  />
+  <DeferredSpinner
+    loading={false}
+  >
+    <PluginsList
+      pending={
+        Object {
+          "installing": Array [],
+          "removing": Array [],
+          "updating": Array [],
+        }
+      }
+      plugins={
+        Array [
+          Object {
+            "key": "sonar-foo",
+            "name": "Sonar Foo",
+          },
+        ]
+      }
+      readOnly={false}
+      refreshPending={[MockFunction]}
+    />
+    <Footer
+      total={1}
+    />
+  </DeferredSpinner>
+</div>
+`;