From 36efcfabb50b8fd9086ec906d733a159a41e5367 Mon Sep 17 00:00:00 2001 From: wouter-admiraal-sonarsource <45544358+wouter-admiraal-sonarsource@users.noreply.github.com> Date: Mon, 10 Dec 2018 08:47:36 +0100 Subject: [PATCH] Hardening dec 5 (#1030) * SONAR-11533 Drop obsolete bullet in 'How To Use' section for encryption * SONAR-11541 Give branch and PR names more room in dropdown * SONAR-11469 Display an Alert when redirected to login When a user is redirected to the login page after trying to access a page which she doesn't have sufficient permissions for, display an alert explaining why the user was redirected, and provide a link to go back to the homepage. --- .../components/nav/component/ComponentNav.css | 3 +- .../src/main/js/app/styles/init/misc.css | 18 ++ .../sessions/components/LoginSonarCloud.css | 13 ++ .../sessions/components/LoginSonarCloud.tsx | 99 +++++--- .../__tests__/LoginSonarCloud-test.tsx | 14 +- .../LoginSonarCloud-test.tsx.snap | 217 ++++++++++++------ .../encryption/GenerateSecretKeyForm.tsx | 2 +- .../resources/org/sonar/l10n/core.properties | 3 +- 8 files changed, 262 insertions(+), 107 deletions(-) diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.css b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.css index 50141bd6c0c..a9eaf7e918b 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.css +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.css @@ -31,6 +31,7 @@ .navbar-context-branches .popup { min-width: 430px; + max-width: 650px; } .navbar-context-meta-branch-menu-title { @@ -44,7 +45,7 @@ } .navbar-context-meta-branch-menu-item-name { - flex: 0 1 300px; /* Workaround for SONAR-10971 */ + flex: 0 1 550px; /* Workaround for SONAR-10971 */ min-width: 0; } diff --git a/server/sonar-web/src/main/js/app/styles/init/misc.css b/server/sonar-web/src/main/js/app/styles/init/misc.css index e8cc9b5fa24..6c7364ab3ec 100644 --- a/server/sonar-web/src/main/js/app/styles/init/misc.css +++ b/server/sonar-web/src/main/js/app/styles/init/misc.css @@ -372,6 +372,24 @@ td.big-spacer-top { color: rgba(68, 68, 68, 0.3); } +.horizontal-pipe-separator { + display: flex; + align-items: center; + margin-top: calc(4 * var(--gridSize)); + margin-bottom: calc(4 * var(--gridSize)); +} + +.horizontal-pipe-separator > .horizontal-separator { + margin: 0 4px; +} + +.horizontal-separator { + min-width: 16px; + height: 1px; + flex-grow: 1; + background-color: var(--barBorderColor); +} + .vertical-separator { width: 1px; min-height: 16px; diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginSonarCloud.css b/server/sonar-web/src/main/js/apps/sessions/components/LoginSonarCloud.css index 5f724dfc73d..aace3eb01ed 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginSonarCloud.css +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginSonarCloud.css @@ -17,6 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +.sonarcloud-login-alert { + margin: 10vh auto 5vh auto; + width: 256px; +} + .sonarcloud-login-page { margin-top: 15vh; width: 216px; @@ -25,6 +30,10 @@ padding: calc(4 * var(--gridSize)) 20px; } +.sonarcloud-login-alert ~ .sonarcloud-login-page { + margin-top: 0; +} + .sonarcloud-login-page-large { width: 300px; } @@ -48,3 +57,7 @@ .sonarcloud-oauth-providers.oauth-providers .oauth-providers-help { right: -22px; } + +.sonarcloud-login-cancel { + text-align: center; +} diff --git a/server/sonar-web/src/main/js/apps/sessions/components/LoginSonarCloud.tsx b/server/sonar-web/src/main/js/apps/sessions/components/LoginSonarCloud.tsx index ce758229acc..2f40d8724ab 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/LoginSonarCloud.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/LoginSonarCloud.tsx @@ -18,59 +18,92 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import { connect } from 'react-redux'; import * as classNames from 'classnames'; import LoginForm from './LoginForm'; import OAuthProviders from './OAuthProviders'; import { getBaseUrl } from '../../../helpers/urls'; import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { Alert } from '../../../components/ui/Alert'; import './LoginSonarCloud.css'; +import { Store } from '../../../store/rootReducer'; interface Props { identityProviders: T.IdentityProvider[]; onSubmit: (login: string, password: string) => Promise; returnTo: string; showForm?: boolean; + authorizationError?: boolean; + authenticationError?: boolean; } -export default function LoginSonarCloud({ +function formatLabel(name: string) { + return translateWithParameters('login.with_x', name); +} + +export function LoginSonarCloud({ + showForm, identityProviders, - onSubmit, returnTo, - showForm + onSubmit, + authorizationError, + authenticationError }: Props) { const displayForm = showForm || identityProviders.length <= 0; + const displayErrorAction = authorizationError || authenticationError; return ( -
-
- SonarCloud logo -

- {translate('login.login_or_signup_to_sonarcloud')} -

-
- - {displayForm ? ( - - ) : ( - + <> + {displayErrorAction && ( + + {translate('login.unauthorized_access_alert')} + )} -
+
+
+ SonarCloud logo +

+ {translate('login.login_or_signup_to_sonarcloud')} +

+
+ + {displayForm ? ( + + ) : ( + + )} + + {displayErrorAction && ( +
+
+
+ {translate('or')} +
+
+ {translate('go_back_to_homepage')} +
+ )} +
+ ); } -function formatLabel(name: string) { - return translateWithParameters('login.with_x', name); -} +const mapStateToProps = (state: Store) => ({ + authorizationError: state.appState.authorizationError, + authenticationError: state.appState.authenticationError +}); + +export default connect(mapStateToProps)(LoginSonarCloud); diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginSonarCloud-test.tsx b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginSonarCloud-test.tsx index f29a3d8b963..b2a00661ed4 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginSonarCloud-test.tsx +++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/LoginSonarCloud-test.tsx @@ -19,7 +19,7 @@ */ import * as React from 'react'; import { shallow } from 'enzyme'; -import LoginSonarCloud from '../LoginSonarCloud'; +import { LoginSonarCloud } from '../LoginSonarCloud'; const identityProvider = { backgroundColor: '#000', @@ -50,3 +50,15 @@ it('logs in with simple form', () => { shallow() ).toMatchSnapshot(); }); + +it("shows an warning message if there's an authorization error", () => { + const wrapper = shallow( + + ); + expect(wrapper).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginSonarCloud-test.tsx.snap b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginSonarCloud-test.tsx.snap index cd3b0f00ea8..56308c07525 100644 --- a/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginSonarCloud-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/sessions/components/__tests__/__snapshots__/LoginSonarCloud-test.tsx.snap @@ -1,93 +1,170 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`logs in with identity provider 1`] = ` -
+
- SonarCloud logo -

- login.login_or_signup_to_sonarcloud -

+ SonarCloud logo +

+ login.login_or_signup_to_sonarcloud +

+
+
- -
+ `; exports[`logs in with simple form 1`] = ` -
+
- SonarCloud logo -

- login.login_or_signup_to_sonarcloud -

+ SonarCloud logo +

+ login.login_or_signup_to_sonarcloud +

+
+
- -
+ `; exports[`logs in with simple form 2`] = ` -
+
- SonarCloud logo + SonarCloud logo +

+ login.login_or_signup_to_sonarcloud +

+
+ +
+ +`; + +exports[`shows an warning message if there's an authorization error 1`] = ` + + + login.unauthorized_access_alert + +
+
+ SonarCloud logo +

+ login.login_or_signup_to_sonarcloud +

+
+ -

- login.login_or_signup_to_sonarcloud -

+
+
+ + or + +
+
+ + go_back_to_homepage + +
- -
+
`; diff --git a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx index 1855fe22d32..7f1136ada2f 100644 --- a/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx +++ b/server/sonar-web/src/main/js/apps/settings/encryption/GenerateSecretKeyForm.tsx @@ -85,7 +85,7 @@ export default class GenerateSecretKeyForm extends React.PureComponent

  • Store the secret key in the file ~/.sonar/sonar-secret.txt of the server. This file can be relocated by defining the property sonar.secretKeyPath in conf/sonar.properties
  • Restrict access to this file by making it readable and by owner only
  • Restart the server if the property sonar.secretKeyPath has been set or changed.
  • Copy this file on all the machines that execute code inspection. Define the property sonar.secretKeyPath on those machines if the path is not ~/.sonar/sonar-secret.txt.
  • For each property that you want to encrypt, generate the encrypted value and replace the original value wherever it is stored (configuration files, command lines).
  • +encryption.how_to_use.content= #------------------------------------------------------------------------------ -- 2.39.5