]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-13117 Handle 403 gracefully
authorJeremy Davis <jeremy.davis@sonarsource.com>
Mon, 24 Feb 2020 10:02:37 +0000 (11:02 +0100)
committerSonarTech <sonartech@sonarsource.com>
Wed, 26 Feb 2020 09:41:19 +0000 (10:41 +0100)
server/sonar-web/src/main/js/api/issues.ts
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewerWrapper.tsx
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/CrossComponentSourceViewerWrapper-test.tsx
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/__snapshots__/CrossComponentSourceViewerWrapper-test.tsx.snap

index a6b8b87c70c7e568823caedde53ac904773dbcac..d0756260502a53d08936219887f5ca3c59ba8557 100644 (file)
@@ -179,5 +179,5 @@ export function getIssueFlowSnippets(issueKey: string): Promise<T.Dict<T.Snippet
       }
     });
     return result;
-  }, throwGlobalError);
+  });
 }
index 6ad0277f98ff80774dc9e79a55ceb0ef6e05e2ef..0fd57eb1956da8e007ae8b36bb616b63ded9fbdd 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 import * as React from 'react';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
 import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
+import { translate } from 'sonar-ui-common/helpers/l10n';
 import { getDuplications } from '../../../api/components';
 import { getIssueFlowSnippets } from '../../../api/issues';
+import throwGlobalError from '../../../app/utils/throwGlobalError';
 import DuplicationPopup from '../../../components/SourceViewer/components/DuplicationPopup';
 import {
   filterDuplicationBlocksByLine,
@@ -59,6 +62,7 @@ interface State {
   issuePopup?: { issue: string; name: string };
   linePopup?: T.LinePopup & { component: string };
   loading: boolean;
+  notAccessible: boolean;
 }
 
 export default class CrossComponentSourceViewerWrapper extends React.PureComponent<Props, State> {
@@ -66,7 +70,8 @@ export default class CrossComponentSourceViewerWrapper extends React.PureCompone
   state: State = {
     components: {},
     duplicationsByLine: {},
-    loading: true
+    loading: true,
+    notAccessible: false
   };
 
   componentDidMount() {
@@ -122,9 +127,12 @@ export default class CrossComponentSourceViewerWrapper extends React.PureCompone
           }
         }
       },
-      () => {
+      (response: Response) => {
+        if (response.status !== 403) {
+          throwGlobalError(response);
+        }
         if (this.mounted) {
-          this.setState({ loading: false });
+          this.setState({ loading: false, notAccessible: response.status === 403 });
         }
       }
     );
@@ -197,7 +205,7 @@ export default class CrossComponentSourceViewerWrapper extends React.PureCompone
   };
 
   render() {
-    const { loading } = this.state;
+    const { loading, notAccessible } = this.state;
 
     if (loading) {
       return (
@@ -207,6 +215,14 @@ export default class CrossComponentSourceViewerWrapper extends React.PureCompone
       );
     }
 
+    if (notAccessible) {
+      return (
+        <Alert className="spacer-top" variant="warning">
+          {translate('code_viewer.no_source_code_displayed_due_to_security')}
+        </Alert>
+      );
+    }
+
     const { components, duplications, duplicationsByLine, linePopup } = this.state;
     const issuesByComponent = issuesByComponentAndLine(this.props.issues);
     const locationsByComponent = groupLocationsByComponent(this.props.locations, components);
index 2dcfa8f3ee939a72efbede96b0bc73bfddd61511..318e6646d6bcc988a8e9dadc0b4f69200ed3ef78 100644 (file)
@@ -66,6 +66,16 @@ it('Should fetch data', async () => {
   expect(getIssueFlowSnippets).toBeCalledWith('foo');
 });
 
+it('Should handle no access rights', async () => {
+  (getIssueFlowSnippets as jest.Mock).mockRejectedValueOnce({ status: 403 });
+
+  const wrapper = shallowRender();
+  await waitAndUpdate(wrapper);
+
+  expect(wrapper.state().notAccessible).toBe(true);
+  expect(wrapper).toMatchSnapshot();
+});
+
 it('should handle issue popup', () => {
   const wrapper = shallowRender();
   // open
index 5f6913c5ace958df7c57e80824efb5e672e9426e..c6362cb8a7167adaf501d064df583aaf0da276c7 100644 (file)
@@ -1,5 +1,14 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
+exports[`Should handle no access rights 1`] = `
+<Alert
+  className="spacer-top"
+  variant="warning"
+>
+  code_viewer.no_source_code_displayed_due_to_security
+</Alert>
+`;
+
 exports[`should handle duplication popup 1`] = `
 <Context.Consumer>
   [Function]