Browse Source

Hardening 28-03 (#72)

tags/7.5
Pascal Mugnier 6 years ago
parent
commit
d7c413a1e7

+ 32
- 29
server/sonar-web/public/index.html View File

<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge">


<link rel="apple-touch-icon" href="%WEB_CONTEXT%/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="57x57" href="%WEB_CONTEXT%/apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="%WEB_CONTEXT%/apple-touch-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="%WEB_CONTEXT%/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="%WEB_CONTEXT%/apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="%WEB_CONTEXT%/apple-touch-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="%WEB_CONTEXT%/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="%WEB_CONTEXT%/apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="%WEB_CONTEXT%/apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="%WEB_CONTEXT%/apple-touch-icon-180x180.png">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">


<link rel="icon" type="image/x-icon" href="%WEB_CONTEXT%/favicon.ico">
<link rel="apple-touch-icon" href="%WEB_CONTEXT%/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="57x57" href="%WEB_CONTEXT%/apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="%WEB_CONTEXT%/apple-touch-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="%WEB_CONTEXT%/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="%WEB_CONTEXT%/apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="%WEB_CONTEXT%/apple-touch-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="%WEB_CONTEXT%/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="%WEB_CONTEXT%/apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="%WEB_CONTEXT%/apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="%WEB_CONTEXT%/apple-touch-icon-180x180.png">


<meta name="application-name" content="SonarQube"/>
<link rel="icon" type="image/x-icon" href="%WEB_CONTEXT%/favicon.ico">


<meta name="msapplication-TileColor" content="#FFFFFF" />
<meta name="msapplication-TileImage" content="%WEB_CONTEXT%/mstile-512x512.png" />
<meta name="application-name" content="SonarQube" />


<% for (var css in htmlWebpackPlugin.files.css) { %>
<meta name="msapplication-TileColor" content="#FFFFFF" />
<meta name="msapplication-TileImage" content="%WEB_CONTEXT%/mstile-512x512.png" />

<% for (var css in htmlWebpackPlugin.files.css) { %>
<link href="%WEB_CONTEXT%/<%= htmlWebpackPlugin.files.css[css] %>" rel="stylesheet"> <link href="%WEB_CONTEXT%/<%= htmlWebpackPlugin.files.css[css] %>" rel="stylesheet">
<% } %> <% } %>
<title>SonarQube</title>
</head>
<body>
<div id="content">
<div class="global-loading">
<i class="spinner global-loading-spinner"></i>
<span class="global-loading-text">Loading...</span>
</div>
<title>Loading...</title>
</head>
<body>
<div id="content">
<div class="global-loading">
<i class="spinner global-loading-spinner"></i>
<span class="global-loading-text">Loading...</span>
</div> </div>
<script>window.baseUrl = '%WEB_CONTEXT%';</script>
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
</div>
<script>window.baseUrl = '%WEB_CONTEXT%';</script>
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
<script src="%WEB_CONTEXT%/<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script> <script src="%WEB_CONTEXT%/<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<% } %> <% } %>
</body>
</body>

</html> </html>

+ 0
- 1
server/sonar-web/src/main/js/api/components.ts View File

} }


export function createProject(data: { export function createProject(data: {
branch?: string;
name: string; name: string;
project: string; project: string;
organization?: string; organization?: string;

+ 11
- 11
server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBranchesMenuItem.tsx View File



return ( return (
<li key={getBranchLikeKey(branchLike)} onMouseEnter={handleMouseEnter}> <li key={getBranchLikeKey(branchLike)} onMouseEnter={handleMouseEnter}>
<Tooltip mouseEnterDelay={0.5} overlay={displayName} placement="right">
<Link
className={classNames('navbar-context-meta-branch-menu-item', {
active: props.selected
})}
to={getBranchLikeUrl(props.component.key, branchLike)}>
<Link
className={classNames('navbar-context-meta-branch-menu-item', {
active: props.selected
})}
to={getBranchLikeUrl(props.component.key, branchLike)}>
<Tooltip mouseEnterDelay={0.5} overlay={displayName} placement="left">
<div className="navbar-context-meta-branch-menu-item-name text-ellipsis"> <div className="navbar-context-meta-branch-menu-item-name text-ellipsis">
<BranchIcon <BranchIcon
branchLike={branchLike} branchLike={branchLike}
<div className="outline-badge spacer-left">{translate('branches.main_branch')}</div> <div className="outline-badge spacer-left">{translate('branches.main_branch')}</div>
)} )}
</div> </div>
<div className="big-spacer-left note">
<BranchStatus branchLike={branchLike} concise={true} />
</div>
</Link>
</Tooltip>
</Tooltip>
<div className="big-spacer-left note">
<BranchStatus branchLike={branchLike} concise={true} />
</div>
</Link>
</li> </li>
); );
} }

+ 111
- 111
server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/ComponentNavBranchesMenuItem-test.tsx.snap View File

key="branch-master" key="branch-master"
onMouseEnter={[Function]} onMouseEnter={[Function]}
> >
<Tooltip
mouseEnterDelay={0.5}
overlay="master"
placement="right"
>
<Link
className="navbar-context-meta-branch-menu-item"
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"id": "component",
},
}
<Link
className="navbar-context-meta-branch-menu-item"
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"id": "component",
},
} }
}
>
<Tooltip
mouseEnterDelay={0.5}
overlay="master"
placement="left"
> >
<div <div
className="navbar-context-meta-branch-menu-item-name text-ellipsis" className="navbar-context-meta-branch-menu-item-name text-ellipsis"
branches.main_branch branches.main_branch
</div> </div>
</div> </div>
<div
className="big-spacer-left note"
>
<BranchStatus
branchLike={
Object {
"isMain": true,
"name": "master",
}
</Tooltip>
<div
className="big-spacer-left note"
>
<BranchStatus
branchLike={
Object {
"isMain": true,
"name": "master",
} }
concise={true}
/>
</div>
</Link>
</Tooltip>
}
concise={true}
/>
</div>
</Link>
</li> </li>
`; `;


key="branch-foo" key="branch-foo"
onMouseEnter={[Function]} onMouseEnter={[Function]}
> >
<Tooltip
mouseEnterDelay={0.5}
overlay="foo"
placement="right"
>
<Link
className="navbar-context-meta-branch-menu-item"
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/project/issues",
"query": Object {
"branch": "foo",
"id": "component",
"resolved": "false",
},
}
<Link
className="navbar-context-meta-branch-menu-item"
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/project/issues",
"query": Object {
"branch": "foo",
"id": "component",
"resolved": "false",
},
} }
}
>
<Tooltip
mouseEnterDelay={0.5}
overlay="foo"
placement="left"
> >
<div <div
className="navbar-context-meta-branch-menu-item-name text-ellipsis" className="navbar-context-meta-branch-menu-item-name text-ellipsis"
/> />
foo foo
</div> </div>
<div
className="big-spacer-left note"
>
<BranchStatus
branchLike={
Object {
"isMain": false,
"mergeBranch": "master",
"name": "foo",
"status": Object {
"bugs": 1,
"codeSmells": 2,
"qualityGateStatus": "ERROR",
"vulnerabilities": 3,
},
"type": "SHORT",
}
</Tooltip>
<div
className="big-spacer-left note"
>
<BranchStatus
branchLike={
Object {
"isMain": false,
"mergeBranch": "master",
"name": "foo",
"status": Object {
"bugs": 1,
"codeSmells": 2,
"qualityGateStatus": "ERROR",
"vulnerabilities": 3,
},
"type": "SHORT",
} }
concise={true}
/>
</div>
</Link>
</Tooltip>
}
concise={true}
/>
</div>
</Link>
</li> </li>
`; `;


key="branch-foo" key="branch-foo"
onMouseEnter={[Function]} onMouseEnter={[Function]}
> >
<Tooltip
mouseEnterDelay={0.5}
overlay="foo"
placement="right"
>
<Link
className="navbar-context-meta-branch-menu-item"
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/project/issues",
"query": Object {
"branch": "foo",
"id": "component",
"resolved": "false",
},
}
<Link
className="navbar-context-meta-branch-menu-item"
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/project/issues",
"query": Object {
"branch": "foo",
"id": "component",
"resolved": "false",
},
} }
}
>
<Tooltip
mouseEnterDelay={0.5}
overlay="foo"
placement="left"
> >
<div <div
className="navbar-context-meta-branch-menu-item-name text-ellipsis" className="navbar-context-meta-branch-menu-item-name text-ellipsis"
/> />
foo foo
</div> </div>
<div
className="big-spacer-left note"
>
<BranchStatus
branchLike={
Object {
"isMain": false,
"isOrphan": true,
"mergeBranch": "master",
"name": "foo",
"status": Object {
"bugs": 1,
"codeSmells": 2,
"qualityGateStatus": "ERROR",
"vulnerabilities": 3,
},
"type": "SHORT",
}
</Tooltip>
<div
className="big-spacer-left note"
>
<BranchStatus
branchLike={
Object {
"isMain": false,
"isOrphan": true,
"mergeBranch": "master",
"name": "foo",
"status": Object {
"bugs": 1,
"codeSmells": 2,
"qualityGateStatus": "ERROR",
"vulnerabilities": 3,
},
"type": "SHORT",
} }
concise={true}
/>
</div>
</Link>
</Tooltip>
}
concise={true}
/>
</div>
</Link>
</li> </li>
`; `;

+ 0
- 34
server/sonar-web/src/main/js/apps/projectsManagement/CreateProjectForm.tsx View File

} }


interface State { interface State {
advanced: boolean;
branch: string;
createdProject?: { key: string; name: string }; createdProject?: { key: string; name: string };
key: string; key: string;
loading: boolean; loading: boolean;
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
this.state = { this.state = {
advanced: false,
branch: '',
key: '', key: '',
loading: false, loading: false,
name: '', name: '',
this.mounted = false; this.mounted = false;
} }


handleAdvancedClick = (event: React.SyntheticEvent<HTMLAnchorElement>) => {
event.preventDefault();
event.currentTarget.blur();
this.setState(state => ({ advanced: !state.advanced }));
};

handleInputChange = (event: React.SyntheticEvent<HTMLInputElement>) => { handleInputChange = (event: React.SyntheticEvent<HTMLInputElement>) => {
const { name, value } = event.currentTarget; const { name, value } = event.currentTarget;
this.setState({ [name]: value }); this.setState({ [name]: value });


const data = { const data = {
name: this.state.name, name: this.state.name,
branch: this.state.branch,
organization: this.props.organization && this.props.organization.key, organization: this.props.organization && this.props.organization.key,
project: this.state.key, project: this.state.key,
visibility: this.state.visibility visibility: this.state.visibility
</div> </div>
)} )}
</div> </div>
{this.state.advanced ? (
<div className="modal-field big-spacer-top">
<label htmlFor="create-project-branch">{translate('branch')}</label>
<input
autoFocus={true}
id="create-project-branch"
maxLength={200}
name="branch"
onChange={this.handleInputChange}
type="text"
value={this.state.branch}
/>
</div>
) : (
<div className="modal-field big-spacer-top">
<a
className="js-more text-muted note"
href="#"
onClick={this.handleAdvancedClick}>
{translate('more')}
</a>
</div>
)}
</div> </div>


<footer className="modal-foot"> <footer className="modal-foot">

+ 1
- 16
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/CreateProjectForm-test.tsx View File

import * as React from 'react'; import * as React from 'react';
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import CreateProjectForm from '../CreateProjectForm'; import CreateProjectForm from '../CreateProjectForm';
import { change, submit, click, waitAndUpdate } from '../../../helpers/testUtils';
import { change, submit, waitAndUpdate } from '../../../helpers/testUtils';
import { Visibility } from '../../../app/types'; import { Visibility } from '../../../app/types';


const createProject = require('../../../api/components').createProject as jest.Mock<any>; const createProject = require('../../../api/components').createProject as jest.Mock<any>;


submit(wrapper.find('form')); submit(wrapper.find('form'));
expect(createProject).toBeCalledWith({ expect(createProject).toBeCalledWith({
branch: '',
name: 'name', name: 'name',
organization: 'org', organization: 'org',
project: 'key', project: 'key',
await waitAndUpdate(wrapper); await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });

it('shows more', () => {
const wrapper = shallow(
<CreateProjectForm
onClose={jest.fn()}
onProjectCreated={jest.fn()}
organization={organization}
/>
);
expect(wrapper).toMatchSnapshot();

click(wrapper.find('.js-more'));
expect(wrapper).toMatchSnapshot();
});

+ 0
- 274
server/sonar-web/src/main/js/apps/projectsManagement/__tests__/__snapshots__/CreateProjectForm-test.tsx.snap View File

/> />
</div> </div>
</div> </div>
<div
className="modal-field big-spacer-top"
>
<a
className="js-more text-muted note"
href="#"
onClick={[Function]}
>
more
</a>
</div>
</div> </div>
<footer <footer
className="modal-foot" className="modal-foot"
/> />
</div> </div>
</div> </div>
<div
className="modal-field big-spacer-top"
>
<a
className="js-more text-muted note"
href="#"
onClick={[Function]}
>
more
</a>
</div>
</div> </div>
<footer <footer
className="modal-foot" className="modal-foot"
/> />
</div> </div>
</div> </div>
<div
className="modal-field big-spacer-top"
>
<a
className="js-more text-muted note"
href="#"
onClick={[Function]}
>
more
</a>
</div>
</div> </div>
<footer <footer
className="modal-foot" className="modal-foot"
</div> </div>
</Modal> </Modal>
`; `;

exports[`shows more 1`] = `
<Modal
contentLabel="modal form"
onRequestClose={[MockFunction]}
>
<form
id="create-project-form"
onSubmit={[Function]}
>
<header
className="modal-head"
>
<h2>
qualifiers.create.TRK
</h2>
</header>
<div
className="modal-body"
>
<div
className="modal-field"
>
<label
htmlFor="create-project-name"
>
name
<em
className="mandatory"
>
*
</em>
</label>
<input
autoFocus={true}
id="create-project-name"
maxLength={2000}
name="name"
onChange={[Function]}
required={true}
type="text"
value=""
/>
</div>
<div
className="modal-field"
>
<label
htmlFor="create-project-key"
>
key
<em
className="mandatory"
>
*
</em>
</label>
<input
id="create-project-key"
maxLength={400}
name="key"
onChange={[Function]}
required={true}
type="text"
value=""
/>
</div>
<div
className="modal-field"
>
<label>
visibility
</label>
<VisibilitySelector
className="little-spacer-top"
onChange={[Function]}
visibility="public"
/>
<div
className="spacer-top"
>
<UpgradeOrganizationBox
organization="org"
/>
</div>
</div>
<div
className="modal-field big-spacer-top"
>
<a
className="js-more text-muted note"
href="#"
onClick={[Function]}
>
more
</a>
</div>
</div>
<footer
className="modal-foot"
>
<SubmitButton
disabled={false}
id="create-project-submit"
>
create
</SubmitButton>
<ResetButtonLink
id="create-project-cancel"
onClick={[MockFunction]}
>
cancel
</ResetButtonLink>
</footer>
</form>
</Modal>
`;

exports[`shows more 2`] = `
<Modal
contentLabel="modal form"
onRequestClose={[MockFunction]}
>
<form
id="create-project-form"
onSubmit={[Function]}
>
<header
className="modal-head"
>
<h2>
qualifiers.create.TRK
</h2>
</header>
<div
className="modal-body"
>
<div
className="modal-field"
>
<label
htmlFor="create-project-name"
>
name
<em
className="mandatory"
>
*
</em>
</label>
<input
autoFocus={true}
id="create-project-name"
maxLength={2000}
name="name"
onChange={[Function]}
required={true}
type="text"
value=""
/>
</div>
<div
className="modal-field"
>
<label
htmlFor="create-project-key"
>
key
<em
className="mandatory"
>
*
</em>
</label>
<input
id="create-project-key"
maxLength={400}
name="key"
onChange={[Function]}
required={true}
type="text"
value=""
/>
</div>
<div
className="modal-field"
>
<label>
visibility
</label>
<VisibilitySelector
className="little-spacer-top"
onChange={[Function]}
visibility="public"
/>
<div
className="spacer-top"
>
<UpgradeOrganizationBox
organization="org"
/>
</div>
</div>
<div
className="modal-field big-spacer-top"
>
<label
htmlFor="create-project-branch"
>
branch
</label>
<input
autoFocus={true}
id="create-project-branch"
maxLength={200}
name="branch"
onChange={[Function]}
type="text"
value=""
/>
</div>
</div>
<footer
className="modal-foot"
>
<SubmitButton
disabled={false}
id="create-project-submit"
>
create
</SubmitButton>
<ResetButtonLink
id="create-project-cancel"
onClick={[MockFunction]}
>
cancel
</ResetButtonLink>
</footer>
</form>
</Modal>
`;

+ 18
- 8
server/sonar-web/src/main/js/components/common/BranchStatus.tsx View File

import { BranchLike } from '../../app/types'; import { BranchLike } from '../../app/types';
import { isShortLivingBranch, isPullRequest, isLongLivingBranch } from '../../helpers/branches'; import { isShortLivingBranch, isPullRequest, isLongLivingBranch } from '../../helpers/branches';
import { translateWithParameters } from '../../helpers/l10n'; import { translateWithParameters } from '../../helpers/l10n';
import { formatMeasure } from '../../helpers/measures';
import './BranchStatus.css'; import './BranchStatus.css';


interface Props { interface Props {


const totalIssues = const totalIssues =
branchLike.status.bugs + branchLike.status.vulnerabilities + branchLike.status.codeSmells; branchLike.status.bugs + branchLike.status.vulnerabilities + branchLike.status.codeSmells;
const indicatorColor = getQualityGateColor(branchLike.status.qualityGateStatus);
const shouldDisplayHelper = branchLike.status.qualityGateStatus === 'OK' && totalIssues > 0;
const status = branchLike.status.qualityGateStatus;
const indicatorColor = getQualityGateColor(status);
const shouldDisplayHelper = status === 'OK' && totalIssues > 0;

const label =
translateWithParameters('overview.quality_gate_x', formatMeasure(status, 'LEVEL')) +
(status !== 'OK'
? ' ' + translateWithParameters('overview.quality_gate_failed_with_x', totalIssues)
: '');


return concise ? ( return concise ? (
<ul className="branch-status">
<li>{totalIssues}</li>
<li className="spacer-left">
<StatusIndicator color={indicatorColor} size="small" />
</li>
</ul>
<Tooltip overlay={label} placement="right">
<ul className="branch-status">
<li>{totalIssues}</li>
<li className="spacer-left">
<StatusIndicator color={indicatorColor} size="small" />
</li>
</ul>
</Tooltip>
) : ( ) : (
<ul className="branch-status"> <ul className="branch-status">
<li className="little-spacer-right"> <li className="little-spacer-right">

+ 1
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
overview.quality_gate=Quality Gate overview.quality_gate=Quality Gate
overview.quality_gate_x=Quality Gate: {0} overview.quality_gate_x=Quality Gate: {0}
overview.quality_gate_failed_with_x=with {0} errors
overview.you_should_define_quality_gate=You should define a quality gate on this project. overview.you_should_define_quality_gate=You should define a quality gate on this project.
overview.quality_gate.ignored_conditions=Some Quality Gate conditions on New Code were ignored because of the small number of New Lines overview.quality_gate.ignored_conditions=Some Quality Gate conditions on New Code were ignored because of the small number of New Lines
overview.quality_gate.ignored_conditions.tooltip=At the start of a leak period, if very few lines have been added or modified, it might be difficult to reach the desired level of code coverage or duplications. To prevent Quality Gate failure when there's little that can be done about it, Quality Gate conditions about duplications in new code and coverage on new code are ignored until the number of new lines is at least 20. overview.quality_gate.ignored_conditions.tooltip=At the start of a leak period, if very few lines have been added or modified, it might be difficult to reach the desired level of code coverage or duplications. To prevent Quality Gate failure when there's little that can be done about it, Quality Gate conditions about duplications in new code and coverage on new code are ignored until the number of new lines is at least 20.

Loading…
Cancel
Save