]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11012 Remove front end access checks on QP, QG and members page
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Tue, 10 Jul 2018 14:04:27 +0000 (16:04 +0200)
committerSonarTech <sonartech@sonarsource.com>
Wed, 11 Jul 2018 18:21:23 +0000 (20:21 +0200)
12 files changed:
server/sonar-web/src/main/js/app/components/NotFound.js [deleted file]
server/sonar-web/src/main/js/app/components/NotFound.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/apps/organizations/components/OrganizationAccessContainer.tsx
server/sonar-web/src/main/js/apps/organizations/components/OrganizationDelete.tsx
server/sonar-web/src/main/js/apps/organizations/components/OrganizationPage.tsx
server/sonar-web/src/main/js/apps/organizations/components/__tests__/OrganizationAccessContainer-test.tsx
server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationDelete-test.tsx.snap
server/sonar-web/src/main/js/apps/organizations/components/__tests__/__snapshots__/OrganizationPage-test.tsx.snap
server/sonar-web/src/main/js/apps/organizations/routes.ts
server/sonar-web/src/main/js/apps/quality-profiles/components/App.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/EvolutionRules.tsx
server/sonar-web/src/main/js/apps/quality-profiles/home/HomeContainer.tsx

diff --git a/server/sonar-web/src/main/js/app/components/NotFound.js b/server/sonar-web/src/main/js/app/components/NotFound.js
deleted file mode 100644 (file)
index 37e2a27..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- */
-import React from 'react';
-import { Link } from 'react-router';
-import SimpleContainer from './SimpleContainer';
-
-/*::
-type Props = {
-  withContainer?: boolean;
-};
-*/
-
-export default function NotFound({ withContainer = true } /*: Props*/) {
-  const Container = withContainer ? SimpleContainer : React.Fragment;
-  return (
-    <Container>
-      <div className="page-wrapper-simple" id="bd">
-        <div className="page-simple" id="nonav">
-          <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2>
-          <p className="spacer-bottom">
-            You may have mistyped the address or the page may have moved.
-          </p>
-          <p>
-            <Link to="/">Go back to the homepage</Link>
-          </p>
-        </div>
-      </div>
-    </Container>
-  );
-}
diff --git a/server/sonar-web/src/main/js/app/components/NotFound.tsx b/server/sonar-web/src/main/js/app/components/NotFound.tsx
new file mode 100644 (file)
index 0000000..ade1346
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+import * as React from 'react';
+import { Link } from 'react-router';
+import SimpleContainer from './SimpleContainer';
+
+interface Props {
+  withContainer?: boolean;
+}
+
+export default function NotFound({ withContainer = true }: Props) {
+  const Container = withContainer ? SimpleContainer : React.Fragment;
+  return (
+    <Container>
+      <div className="page-wrapper-simple" id="bd">
+        <div className="page-simple" id="nonav">
+          <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2>
+          <p className="spacer-bottom">
+            You may have mistyped the address or the page may have moved.
+          </p>
+          <p>
+            <Link to="/">Go back to the homepage</Link>
+          </p>
+        </div>
+      </div>
+    </Container>
+  );
+}
index 4cef029f3dfc0786c24425825aea6f918f233541..53941adef8ad55a279abbd5a48d36729f065a0be 100644 (file)
 import * as React from 'react';
 import { connect } from 'react-redux';
 import { RouterState } from 'react-router';
-import {
-  getCurrentUser,
-  getMyOrganizations,
-  getOrganizationByKey
-} from '../../../store/rootReducer';
+import { getCurrentUser, getOrganizationByKey } from '../../../store/rootReducer';
 import handleRequiredAuthorization from '../../../app/utils/handleRequiredAuthorization';
 import { Organization, CurrentUser, isLoggedIn } from '../../../app/types';
-import { isCurrentUserMemberOf, hasPrivateAccess } from '../../../helpers/organizations';
-import {} from '../../../store/organizations/duck';
 
 interface StateToProps {
   currentUser: CurrentUser;
   organization?: Organization;
-  userOrganizations: Organization[];
 }
 
 interface OwnProps extends RouterState {
@@ -72,36 +65,13 @@ export class OrganizationAccess extends React.PureComponent<Props> {
 
 const mapStateToProps = (state: any, ownProps: OwnProps) => ({
   currentUser: getCurrentUser(state),
-  organization: getOrganizationByKey(state, ownProps.params.organizationKey),
-  userOrganizations: getMyOrganizations(state)
+  organization: getOrganizationByKey(state, ownProps.params.organizationKey)
 });
 
 const OrganizationAccessContainer = connect<StateToProps, {}, OwnProps>(mapStateToProps)(
   OrganizationAccess
 );
 
-export function OrganizationPrivateAccess(props: OwnProps) {
-  return (
-    <OrganizationAccessContainer
-      hasAccess={({ currentUser, organization, userOrganizations }: StateToProps) =>
-        hasPrivateAccess(currentUser, organization, userOrganizations)
-      }
-      {...props}
-    />
-  );
-}
-
-export function OrganizationMembersAccess(props: OwnProps) {
-  return (
-    <OrganizationAccessContainer
-      hasAccess={({ currentUser, organization, userOrganizations }: StateToProps) =>
-        isCurrentUserMemberOf(currentUser, organization, userOrganizations)
-      }
-      {...props}
-    />
-  );
-}
-
 export function hasAdminAccess({
   currentUser,
   organization
index ce7ebfdaad9c3ab2e1b2be47399d4d20436271b3..4625032fcdda4efec08429616951c955e722fb11 100644 (file)
@@ -104,12 +104,12 @@ export class OrganizationDelete extends React.PureComponent<Props, State> {
             isDestructive={true}
             modalBody={
               <div>
-                {translate('organization.delete.question')}
                 {hasPaidPlan && (
-                  <p className="alert alert-warn big-spacer-top">
+                  <div className="alert alert-warning modal-alert">
                     {translate('organization.delete.sonarcloud.paid_plan_info')}
-                  </p>
+                  </div>
                 )}
+                <p>{translate('organization.delete.question')}</p>
               </div>
             }
             modalHeader={translate('organization.delete')}
index 8d135c8fede4b9fa3bf98fc1e32340fc5757265d..44daa37abeab565264a4ce1d5c2fe8e6e82d234c 100644 (file)
@@ -90,7 +90,7 @@ export class OrganizationPage extends React.PureComponent<Props, State> {
       if (this.state.loading) {
         return null;
       } else {
-        return <NotFound />;
+        return <NotFound withContainer={false} />;
       }
     }
 
index 8fcb64c11f34df9db4bd90e394e99046426021fc..17b1fd80bb1b8e2b4e7a7bef8c092c4fe6696f7c 100644 (file)
@@ -55,8 +55,7 @@ describe('component', () => {
           currentUser={loggedInUser}
           hasAccess={() => true}
           location={locationMock}
-          organization={adminOrganization}
-          userOrganizations={[]}>
+          organization={adminOrganization}>
           <div>hello</div>
         </OrganizationAccess>
       )
@@ -70,8 +69,7 @@ describe('component', () => {
           currentUser={loggedInUser}
           hasAccess={() => false}
           location={locationMock}
-          organization={adminOrganization}
-          userOrganizations={[]}>
+          organization={adminOrganization}>
           <div>hello</div>
         </OrganizationAccess>
       ).type()
index 62ab31e51d272b8b36774da763e442140fc7eaaa..a9184671428e7dccc9bd38915524b02ed040a404 100644 (file)
@@ -31,11 +31,13 @@ exports[`should show a info message for paying organization 1`] = `
       isDestructive={true}
       modalBody={
         <div>
-          organization.delete.question
-          <p
-            className="alert alert-warn big-spacer-top"
+          <div
+            className="alert alert-warning modal-alert"
           >
             organization.delete.sonarcloud.paid_plan_info
+          </div>
+          <p>
+            organization.delete.question
           </p>
         </div>
       }
@@ -77,7 +79,9 @@ exports[`smoke test 1`] = `
       isDestructive={true}
       modalBody={
         <div>
-          organization.delete.question
+          <p>
+            organization.delete.question
+          </p>
         </div>
       }
       modalHeader="organization.delete"
index c6b612738c1d9dcbd96411b598caa8baf587066a..7c58c886214853df37403fa3b00b5e87b5a834c6 100644 (file)
@@ -1,6 +1,10 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`not found 1`] = `<NotFound />`;
+exports[`not found 1`] = `
+<NotFound
+  withContainer={false}
+/>
+`;
 
 exports[`should correctly update when the organization changes 1`] = `
 Array [
index 24cd7999dcd7bca59ad0b033d86e9dacb35323e9..b6fa1ef378efc3e141f3c2adba151a2624fec921 100644 (file)
@@ -59,35 +59,17 @@ const routes = [
         childRoutes: codingRulesRoutes
       },
       {
-        component: lazyLoad(() =>
-          import('./components/OrganizationAccessContainer').then(lib => ({
-            default: lib.OrganizationMembersAccess
-          }))
-        ),
-        childRoutes: [
-          {
-            path: 'members',
-            component: lazyLoad(() => import('./components/OrganizationMembersContainer'))
-          }
-        ]
+        path: 'members',
+        component: lazyLoad(() => import('./components/OrganizationMembersContainer'))
       },
       {
-        component: lazyLoad(() =>
-          import('./components/OrganizationAccessContainer').then(lib => ({
-            default: lib.OrganizationPrivateAccess
-          }))
-        ),
-        childRoutes: [
-          {
-            path: 'quality_profiles',
-            childRoutes: qualityProfilesRoutes
-          },
-          {
-            path: 'quality_gates',
-            component: OrganizationContainer,
-            childRoutes: qualityGatesRoutes
-          }
-        ]
+        path: 'quality_profiles',
+        childRoutes: qualityProfilesRoutes
+      },
+      {
+        path: 'quality_gates',
+        component: OrganizationContainer,
+        childRoutes: qualityGatesRoutes
       },
       {
         component: lazyLoad(() =>
index 35fd9354bff4770dc8bad6a4e487bb5de0dfad6c..67697a9c4f852ea61df4cbe7a2b857b9de5df1a4 100644 (file)
@@ -99,7 +99,7 @@ export default class App extends React.PureComponent<Props, State> {
 
     return React.cloneElement(this.props.children, {
       actions: this.state.actions || {},
-      profiles: this.state.profiles,
+      profiles: this.state.profiles || [],
       languages: finalLanguages,
       exporters: this.state.exporters,
       updateProfiles: this.updateProfiles,
index dac9e1a71be377991b0cf7a8bfd7fe4107d16e7f..2842268340f6efe56c6d8c860108516915502106 100644 (file)
@@ -25,13 +25,13 @@ import { translateWithParameters, translate } from '../../../helpers/l10n';
 import { getRulesUrl } from '../../../helpers/urls';
 import { toShortNotSoISOString } from '../../../helpers/dates';
 import { formatMeasure } from '../../../helpers/measures';
+import { Rule, RuleActivation } from '../../../app/types';
 
 const RULES_LIMIT = 10;
 
-function parseRules(r: any) {
-  const { rules, actives } = r;
-  return rules.map((rule: any) => {
-    const activations = actives[rule.key];
+function parseRules(rules: Rule[], actives?: { [rule: string]: RuleActivation[] }): ExtendedRule[] {
+  return rules.map(rule => {
+    const activations = actives && actives[rule.key];
     return { ...rule, activations: activations ? activations.length : 0 };
   });
 }
@@ -40,15 +40,12 @@ interface Props {
   organization: string | null;
 }
 
-interface Rule {
+interface ExtendedRule extends Rule {
   activations: number;
-  key: string;
-  langName: string;
-  name: string;
 }
 
 interface State {
-  latestRules?: Array<Rule>;
+  latestRules?: ExtendedRule[];
   latestRulesTotal?: number;
 }
 
@@ -84,11 +81,11 @@ export default class EvolutionRules extends React.PureComponent<Props, State> {
     };
 
     searchRules(data).then(
-      (r: any) => {
+      ({ actives, rules, total }) => {
         if (this.mounted) {
           this.setState({
-            latestRules: sortBy<Rule>(parseRules(r), 'langName'),
-            latestRulesTotal: r.total
+            latestRules: sortBy(parseRules(rules, actives), 'langName'),
+            latestRulesTotal: total
           });
         }
       },
@@ -113,11 +110,11 @@ export default class EvolutionRules extends React.PureComponent<Props, State> {
         </div>
         <ul>
           {this.state.latestRules.map(rule => (
-            <li key={rule.key} className="spacer-top">
+            <li className="spacer-top" key={rule.key}>
               <div className="text-ellipsis">
                 <Link
-                  to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}
-                  className="link-no-underline">
+                  className="link-no-underline"
+                  to={getRulesUrl({ rule_key: rule.key }, this.props.organization)}>
                   {' '}
                   {rule.name}
                 </Link>
@@ -139,7 +136,7 @@ export default class EvolutionRules extends React.PureComponent<Props, State> {
         </ul>
         {this.state.latestRulesTotal > RULES_LIMIT && (
           <div className="spacer-top">
-            <Link to={newRulesUrl} className="small">
+            <Link className="small" to={newRulesUrl}>
               {translate('see_all')} {formatMeasure(this.state.latestRulesTotal, 'SHORT_INT', null)}
             </Link>
           </div>
index f4ae8356b27f83a2f01d1a2713eb199053ae76bc..af78f87f44e691fc77e03f4a29a5c28be80d03ae 100644 (file)
@@ -30,7 +30,7 @@ interface Props {
   location: { query: { [p: string]: string } };
   onRequestFail: (reason: any) => void;
   organization: string | null;
-  profiles: Array<Profile>;
+  profiles: Profile[];
   updateProfiles: () => Promise<void>;
 }