Просмотр исходного кода

SONAR-13004 Validate Bitbucket personal access token when saving

tags/8.2.0.32929
Wouter Admiraal 4 лет назад
Родитель
Сommit
6585cb5495
14 измененных файлов: 385 добавлений и 182 удалений
  1. 18
    1
      server/sonar-web/src/main/js/apps/create/project/BitbucketImportRepositoryForm.tsx
  2. 23
    13
      server/sonar-web/src/main/js/apps/create/project/BitbucketPersonalAccessTokenForm.tsx
  3. 25
    10
      server/sonar-web/src/main/js/apps/create/project/BitbucketProjectAccordion.tsx
  4. 18
    10
      server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx
  5. 4
    1
      server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx
  6. 11
    3
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketPersonalAccessTokenForm-test.tsx
  7. 8
    1
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx
  8. 1
    0
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx
  9. 23
    1
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap
  10. 115
    2
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketPersonalAccessTokenForm-test.tsx.snap
  11. 133
    136
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap
  12. 1
    0
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap
  13. 1
    0
      server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap
  14. 4
    4
      sonar-core/src/main/resources/org/sonar/l10n/core.properties

+ 18
- 1
server/sonar-web/src/main/js/apps/create/project/BitbucketImportRepositoryForm.tsx Просмотреть файл

@@ -18,6 +18,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
import SearchBox from 'sonar-ui-common/components/controls/SearchBox';
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
@@ -28,6 +30,7 @@ import {
} from '../../../types/alm-integration';
import BitbucketRepositories from './BitbucketRepositories';
import BitbucketSearchResults from './BitbucketSearchResults';
import { CreateProjectModes } from './types';

export interface BitbucketImportRepositoryFormProps {
disableRepositories: boolean;
@@ -53,7 +56,21 @@ export default function BitbucketImportRepositoryForm(props: BitbucketImportRepo
if (projects.length === 0) {
return (
<Alert className="spacer-top" variant="warning">
{translate('onboarding.create_project.no_bbs_projects')}
<FormattedMessage
defaultMessage={translate('onboarding.create_project.no_bbs_projects')}
id="onboarding.create_project.no_bbs_projects"
values={{
link: (
<Link
to={{
pathname: '/projects/create',
query: { mode: CreateProjectModes.BitbucketServer, resetPat: 1 }
}}>
{translate('onboarding.create_project.update_your_token')}
</Link>
)
}}
/>
</Alert>
);
}

+ 23
- 13
server/sonar-web/src/main/js/apps/create/project/BitbucketPersonalAccessTokenForm.tsx Просмотреть файл

@@ -32,6 +32,7 @@ export interface BitbucketPersonalAccessTokenFormProps {
bitbucketSetting: AlmSettingsInstance;
onPersonalAccessTokenCreate: (token: string) => void;
submitting?: boolean;
validationFailed: boolean;
}

export default function BitbucketPersonalAccessTokenForm(
@@ -39,17 +40,24 @@ export default function BitbucketPersonalAccessTokenForm(
) {
const {
bitbucketSetting: { url },
submitting = false
submitting = false,
validationFailed
} = props;
const [personalAccessToken, setPersonalAccessToken] = React.useState('');
const isValid = personalAccessToken.length > 0;
const [touched, setTouched] = React.useState(false);

React.useEffect(() => {
setTouched(false);
}, [submitting]);

const isInvalid = validationFailed && !touched;

return (
<div className="display-flex-start">
<form
onSubmit={(e: React.SyntheticEvent<HTMLFormElement>) => {
e.preventDefault();
props.onPersonalAccessTokenCreate(personalAccessToken);
const value = new FormData(e.currentTarget).get('personal_access_token') as string;
props.onPersonalAccessTokenCreate(value);
}}>
<h2 className="big">{translate('onboarding.create_project.grant_access_to_bbs.title')}</h2>
<p className="big-spacer-top big-spacer-bottom">
@@ -57,28 +65,30 @@ export default function BitbucketPersonalAccessTokenForm(
</p>

<ValidationInput
error={undefined}
error={isInvalid ? translate('onboarding.create_project.pat_incorrect') : undefined}
id="personal_access_token"
isInvalid={false}
isValid={isValid}
isInvalid={isInvalid}
isValid={false}
label={translate('onboarding.create_project.enter_pat')}
required={true}>
<input
autoFocus={true}
className={classNames('input-super-large', {
'is-valid': isValid
'is-invalid': isInvalid
})}
id="personal_access_token"
minLength={1}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setPersonalAccessToken(e.currentTarget.value)
}
name="personal_access_token"
onChange={() => {
setTouched(true);
}}
type="text"
value={personalAccessToken}
/>
</ValidationInput>

<SubmitButton disabled={!isValid || submitting}>{translate('save')}</SubmitButton>
<SubmitButton disabled={isInvalid || submitting || !touched}>
{translate('save')}
</SubmitButton>
<DeferredSpinner className="spacer-left" loading={submitting} />
</form>


+ 25
- 10
server/sonar-web/src/main/js/apps/create/project/BitbucketProjectAccordion.tsx Просмотреть файл

@@ -19,16 +19,17 @@
*/
import * as classNames from 'classnames';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router';
import BoxedGroupAccordion from 'sonar-ui-common/components/controls/BoxedGroupAccordion';
import Radio from 'sonar-ui-common/components/controls/Radio';
import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
import CheckIcon from 'sonar-ui-common/components/icons/CheckIcon';
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
import { colors } from '../../../app/theme';
import { getProjectUrl } from '../../../helpers/urls';
import { BitbucketProject, BitbucketRepository } from '../../../types/alm-integration';
import { CreateProjectModes } from './types';

export interface BitbucketProjectAccordionProps {
disableRepositories: boolean;
@@ -73,7 +74,23 @@ export default function BitbucketProjectAccordion(props: BitbucketProjectAccordi
{open && (
<div className="display-flex-wrap">
{repositoryCount === 0 && (
<Alert variant="warning">{translate('onboarding.create_project.no_bbs_repos')}</Alert>
<Alert variant="warning">
<FormattedMessage
defaultMessage={translate('onboarding.create_project.no_bbs_repos')}
id="onboarding.create_project.no_bbs_repos"
values={{
link: (
<Link
to={{
pathname: '/projects/create',
query: { mode: CreateProjectModes.BitbucketServer, resetPat: 1 }
}}>
{translate('onboarding.create_project.update_your_token')}
</Link>
)
}}
/>
</Alert>
)}

{repositories.map(repo =>
@@ -84,11 +101,9 @@ export default function BitbucketProjectAccordion(props: BitbucketProjectAccordi
<CheckIcon className="spacer-right" fill={colors.green} size={14} />
<div className="overflow-hidden">
<div className="little-spacer-bottom text-ellipsis">
<Tooltip overlay={repo.name}>
<strong>
<Link to={getProjectUrl(repo.sqProjectKey)}>{repo.name}</Link>
</strong>
</Tooltip>
<strong title={repo.name}>
<Link to={getProjectUrl(repo.sqProjectKey)}>{repo.name}</Link>
</strong>
</div>
<em>{translate('onboarding.create_project.repository_imported')}</em>
</div>
@@ -107,9 +122,9 @@ export default function BitbucketProjectAccordion(props: BitbucketProjectAccordi
key={repo.id}
onCheck={() => props.onSelectRepository(repo)}
value={String(repo.id)}>
<Tooltip overlay={repo.name}>
<strong className="text-ellipsis">{repo.name}</strong>
</Tooltip>
<strong className="text-ellipsis" title={repo.name}>
{repo.name}
</strong>
</Radio>
)
)}

+ 18
- 10
server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreate.tsx Просмотреть файл

@@ -55,6 +55,7 @@ interface State {
searchResults?: BitbucketRepository[];
selectedRepository?: BitbucketRepository;
submittingToken?: boolean;
tokenValidationFailed: boolean;
}

export class BitbucketProjectCreate extends React.PureComponent<Props, State> {
@@ -68,7 +69,8 @@ export class BitbucketProjectCreate extends React.PureComponent<Props, State> {
bitbucketSetting: props.bitbucketSettings[0],
importing: false,
loading: false,
searching: false
searching: false,
tokenValidationFailed: false
};
}

@@ -79,8 +81,9 @@ export class BitbucketProjectCreate extends React.PureComponent<Props, State> {

componentDidUpdate(prevProps: Props) {
if (prevProps.bitbucketSettings.length === 0 && this.props.bitbucketSettings.length > 0) {
this.setState({ bitbucketSetting: this.props.bitbucketSettings[0] });
this.fetchInitialData();
this.setState({ bitbucketSetting: this.props.bitbucketSettings[0] }, () =>
this.fetchInitialData()
);
}
}

@@ -169,12 +172,15 @@ export class BitbucketProjectCreate extends React.PureComponent<Props, State> {
return;
}

this.setState({ submittingToken: true });
this.setState({ submittingToken: true, tokenValidationFailed: false });
setAlmPersonalAccessToken(bitbucketSetting.key, token)
.then(() => {
.then(this.checkPersonalAccessToken)
.then(patIsValid => {
if (this.mounted) {
this.setState({ submittingToken: false });
this.fetchInitialData();
this.setState({ submittingToken: false, patIsValid, tokenValidationFailed: !patIsValid });
if (patIsValid) {
this.fetchInitialData();
}
}
})
.catch(() => {
@@ -241,7 +247,7 @@ export class BitbucketProjectCreate extends React.PureComponent<Props, State> {
};

render() {
const { canAdmin, loadingBindings } = this.props;
const { canAdmin, loadingBindings, location } = this.props;
const {
bitbucketSetting,
importing,
@@ -252,7 +258,8 @@ export class BitbucketProjectCreate extends React.PureComponent<Props, State> {
searching,
searchResults,
selectedRepository,
submittingToken
submittingToken,
tokenValidationFailed
} = this.state;

return (
@@ -271,8 +278,9 @@ export class BitbucketProjectCreate extends React.PureComponent<Props, State> {
searchResults={searchResults}
searching={searching}
selectedRepository={selectedRepository}
showPersonalAccessTokenForm={!patIsValid}
showPersonalAccessTokenForm={!patIsValid || Boolean(location.query.resetPat)}
submittingToken={submittingToken}
tokenValidationFailed={tokenValidationFailed}
/>
);
}

+ 4
- 1
server/sonar-web/src/main/js/apps/create/project/BitbucketProjectCreateRenderer.tsx Просмотреть файл

@@ -53,6 +53,7 @@ export interface BitbucketProjectCreateRendererProps {
selectedRepository?: BitbucketRepository;
showPersonalAccessTokenForm?: boolean;
submittingToken?: boolean;
tokenValidationFailed: boolean;
}

export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCreateRendererProps) {
@@ -67,7 +68,8 @@ export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCr
searching,
searchResults,
showPersonalAccessTokenForm,
submittingToken
submittingToken,
tokenValidationFailed
} = props;

return (
@@ -133,6 +135,7 @@ export default function BitbucketProjectCreateRenderer(props: BitbucketProjectCr
bitbucketSetting={bitbucketSetting}
onPersonalAccessTokenCreate={props.onPersonalAccessTokenCreate}
submitting={submittingToken}
validationFailed={tokenValidationFailed}
/>
) : (
<BitbucketImportRepositoryForm

+ 11
- 3
server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketPersonalAccessTokenForm-test.tsx Просмотреть файл

@@ -21,7 +21,7 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import { SubmitButton } from 'sonar-ui-common/components/controls/buttons';
import { change, submit, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { change, submit } from 'sonar-ui-common/helpers/testUtils';
import { mockAlmSettingsInstance } from '../../../../helpers/mocks/alm-settings';
import { AlmKeys } from '../../../../types/alm-settings';
import BitbucketPersonalAccessTokenForm, {
@@ -31,9 +31,10 @@ import BitbucketPersonalAccessTokenForm, {
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ submitting: true })).toMatchSnapshot('submitting');
expect(shallowRender({ validationFailed: true })).toMatchSnapshot('validation failed');
});

it('should correctly handle form interactions', async () => {
it('should correctly handle form interactions', () => {
const onPersonalAccessTokenCreate = jest.fn();
const wrapper = shallowRender({ onPersonalAccessTokenCreate });

@@ -46,8 +47,14 @@ it('should correctly handle form interactions', async () => {

// Expect correct calls to be made when submitting.
submit(wrapper.find('form'));
await waitAndUpdate(wrapper);
expect(onPersonalAccessTokenCreate).toBeCalled();

// If validation fails, we toggle the submitting flag and call useEffect()
// to set the `touched` flag to false again. Trigger a re-render, and mock
// useEffect(). This should de-activate the submit button again.
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f());
wrapper.setProps({ submitting: false });
expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true);
});

function shallowRender(props: Partial<BitbucketPersonalAccessTokenFormProps> = {}) {
@@ -58,6 +65,7 @@ function shallowRender(props: Partial<BitbucketPersonalAccessTokenFormProps> = {
url: 'http://www.example.com'
})}
onPersonalAccessTokenCreate={jest.fn()}
validationFailed={false}
{...props}
/>
);

+ 8
- 1
server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreate-test.tsx Просмотреть файл

@@ -92,10 +92,17 @@ it('should correctly handle an invalid PAT', async () => {
expect(wrapper.state().patIsValid).toBe(false);
});

it('should correctly handle setting a new PAT', () => {
it('should correctly handle setting a new PAT', async () => {
const wrapper = shallowRender();
wrapper.instance().handlePersonalAccessTokenCreate('token');
expect(setAlmPersonalAccessToken).toBeCalledWith('foo', 'token');
expect(wrapper.state().submittingToken).toBe(true);

(checkPersonalAccessTokenIsValid as jest.Mock).mockResolvedValueOnce(false);
await waitAndUpdate(wrapper);
expect(checkPersonalAccessTokenIsValid).toBeCalled();
expect(wrapper.state().submittingToken).toBe(false);
expect(wrapper.state().tokenValidationFailed).toBe(true);
});

it('should correctly fetch projects and repos', async () => {

+ 1
- 0
server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectCreateRenderer-test.tsx Просмотреть файл

@@ -60,6 +60,7 @@ function shallowRender(props: Partial<BitbucketProjectCreateRendererProps> = {})
projectRepositories={{ foo: { allShown: true, repositories: [mockBitbucketRepository()] } }}
projects={[mockBitbucketProject({ key: 'foo' })]}
searching={false}
tokenValidationFailed={false}
{...props}
/>
);

+ 23
- 1
server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketImportRepositoryForm-test.tsx.snap Просмотреть файл

@@ -56,7 +56,29 @@ exports[`should render correctly: no projects 1`] = `
className="spacer-top"
variant="warning"
>
onboarding.create_project.no_bbs_projects
<FormattedMessage
defaultMessage="onboarding.create_project.no_bbs_projects"
id="onboarding.create_project.no_bbs_projects"
values={
Object {
"link": <Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/projects/create",
"query": Object {
"mode": "bbs",
"resetPat": 1,
},
}
}
>
onboarding.create_project.update_your_token
</Link>,
}
}
/>
</Alert>
`;


+ 115
- 2
server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketPersonalAccessTokenForm-test.tsx.snap Просмотреть файл

@@ -29,9 +29,9 @@ exports[`should render correctly: default 1`] = `
className="input-super-large"
id="personal_access_token"
minLength={1}
name="personal_access_token"
onChange={[Function]}
type="text"
value=""
/>
</ValidationInput>
<SubmitButton
@@ -141,9 +141,9 @@ exports[`should render correctly: submitting 1`] = `
className="input-super-large"
id="personal_access_token"
minLength={1}
name="personal_access_token"
onChange={[Function]}
type="text"
value=""
/>
</ValidationInput>
<SubmitButton
@@ -223,3 +223,116 @@ exports[`should render correctly: submitting 1`] = `
</Alert>
</div>
`;

exports[`should render correctly: validation failed 1`] = `
<div
className="display-flex-start"
>
<form
onSubmit={[Function]}
>
<h2
className="big"
>
onboarding.create_project.grant_access_to_bbs.title
</h2>
<p
className="big-spacer-top big-spacer-bottom"
>
onboarding.create_project.grant_access_to_bbs.help
</p>
<ValidationInput
error="onboarding.create_project.pat_incorrect"
id="personal_access_token"
isInvalid={true}
isValid={false}
label="onboarding.create_project.enter_pat"
required={true}
>
<input
autoFocus={true}
className="input-super-large is-invalid"
id="personal_access_token"
minLength={1}
name="personal_access_token"
onChange={[Function]}
type="text"
/>
</ValidationInput>
<SubmitButton
disabled={true}
>
save
</SubmitButton>
<DeferredSpinner
className="spacer-left"
loading={false}
timeout={100}
/>
</form>
<Alert
className="big-spacer-left big-spacer-top"
display="block"
variant="info"
>
<h3>
onboarding.create_project.pat_help.title
</h3>
<p
className="big-spacer-top big-spacer-bottom"
>
onboarding.create_project.pat_help.bbs_help_1
</p>
<div
className="text-middle"
>
<img
alt=""
className="spacer-right"
height="16"
src="/images/alm/bitbucket.svg"
/>
<a
href="http://www.example.com/plugins/servlet/access-tokens/add"
rel="noopener noreferrer"
target="_blank"
>
onboarding.create_project.pat_help.link
</a>
</div>
<p
className="big-spacer-top big-spacer-bottom"
>
onboarding.create_project.pat_help.bbs_help_2
</p>
<ul>
<li>
<FormattedMessage
defaultMessage="onboarding.create_project.pat_help.bbs_permission_projects"
id="onboarding.create_project.pat_help.bbs_permission_projects"
values={
Object {
"perm": <strong>
onboarding.create_project.pat_help.read_permission
</strong>,
}
}
/>
</li>
<li>
<FormattedMessage
defaultMessage="onboarding.create_project.pat_help.bbs_permission_repos"
id="onboarding.create_project.pat_help.bbs_permission_repos"
values={
Object {
"perm": <strong>
onboarding.create_project.pat_help.read_permission
</strong>,
}
}
/>
</li>
</ul>
</Alert>
</div>
`;

+ 133
- 136
server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectAccordion-test.tsx.snap Просмотреть файл

@@ -36,15 +36,12 @@ exports[`should render correctly: default 1`] = `
onCheck={[Function]}
value="1"
>
<Tooltip
overlay="Repo"
<strong
className="text-ellipsis"
title="Repo"
>
<strong
className="text-ellipsis"
>
Repo
</strong>
</Tooltip>
Repo
</strong>
</Radio>
<div
className="display-flex-start spacer-right spacer-bottom create-project-import-bbs-repo"
@@ -61,27 +58,25 @@ exports[`should render correctly: default 1`] = `
<div
className="little-spacer-bottom text-ellipsis"
>
<Tooltip
overlay="Bar"
<strong
title="Bar"
>
<strong>
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
>
Bar
</Link>
</strong>
</Tooltip>
}
>
Bar
</Link>
</strong>
</div>
<em>
onboarding.create_project.repository_imported
@@ -114,15 +109,12 @@ exports[`should render correctly: disable options 1`] = `
onCheck={[Function]}
value="1"
>
<Tooltip
overlay="Repo"
<strong
className="text-ellipsis"
title="Repo"
>
<strong
className="text-ellipsis"
>
Repo
</strong>
</Tooltip>
Repo
</strong>
</Radio>
<div
className="display-flex-start spacer-right spacer-bottom create-project-import-bbs-repo"
@@ -139,27 +131,25 @@ exports[`should render correctly: disable options 1`] = `
<div
className="little-spacer-bottom text-ellipsis"
>
<Tooltip
overlay="Bar"
<strong
title="Bar"
>
<strong>
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
>
Bar
</Link>
</strong>
</Tooltip>
}
>
Bar
</Link>
</strong>
</div>
<em>
onboarding.create_project.repository_imported
@@ -192,15 +182,12 @@ exports[`should render correctly: no click handler 1`] = `
onCheck={[Function]}
value="1"
>
<Tooltip
overlay="Repo"
<strong
className="text-ellipsis"
title="Repo"
>
<strong
className="text-ellipsis"
>
Repo
</strong>
</Tooltip>
Repo
</strong>
</Radio>
<div
className="display-flex-start spacer-right spacer-bottom create-project-import-bbs-repo"
@@ -217,27 +204,25 @@ exports[`should render correctly: no click handler 1`] = `
<div
className="little-spacer-bottom text-ellipsis"
>
<Tooltip
overlay="Bar"
<strong
title="Bar"
>
<strong>
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
>
Bar
</Link>
</strong>
</Tooltip>
}
>
Bar
</Link>
</strong>
</div>
<em>
onboarding.create_project.repository_imported
@@ -266,7 +251,29 @@ exports[`should render correctly: no repos 1`] = `
<Alert
variant="warning"
>
onboarding.create_project.no_bbs_repos
<FormattedMessage
defaultMessage="onboarding.create_project.no_bbs_repos"
id="onboarding.create_project.no_bbs_repos"
values={
Object {
"link": <Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/projects/create",
"query": Object {
"mode": "bbs",
"resetPat": 1,
},
}
}
>
onboarding.create_project.update_your_token
</Link>,
}
}
/>
</Alert>
</div>
</BoxedGroupAccordion>
@@ -294,15 +301,12 @@ exports[`should render correctly: not showing all repos 1`] = `
onCheck={[Function]}
value="1"
>
<Tooltip
overlay="Repo"
<strong
className="text-ellipsis"
title="Repo"
>
<strong
className="text-ellipsis"
>
Repo
</strong>
</Tooltip>
Repo
</strong>
</Radio>
<div
className="display-flex-start spacer-right spacer-bottom create-project-import-bbs-repo"
@@ -319,27 +323,25 @@ exports[`should render correctly: not showing all repos 1`] = `
<div
className="little-spacer-bottom text-ellipsis"
>
<Tooltip
overlay="Bar"
<strong
title="Bar"
>
<strong>
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
>
Bar
</Link>
</strong>
</Tooltip>
}
>
Bar
</Link>
</strong>
</div>
<em>
onboarding.create_project.repository_imported
@@ -377,15 +379,12 @@ exports[`should render correctly: selected repo 1`] = `
onCheck={[Function]}
value="1"
>
<Tooltip
overlay="Repo"
<strong
className="text-ellipsis"
title="Repo"
>
<strong
className="text-ellipsis"
>
Repo
</strong>
</Tooltip>
Repo
</strong>
</Radio>
<div
className="display-flex-start spacer-right spacer-bottom create-project-import-bbs-repo"
@@ -402,27 +401,25 @@ exports[`should render correctly: selected repo 1`] = `
<div
className="little-spacer-bottom text-ellipsis"
>
<Tooltip
overlay="Bar"
<strong
title="Bar"
>
<strong>
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
<Link
onlyActiveOnIndex={false}
style={Object {}}
to={
Object {
"pathname": "/dashboard",
"query": Object {
"branch": undefined,
"id": "bar",
},
}
>
Bar
</Link>
</strong>
</Tooltip>
}
>
Bar
</Link>
</strong>
</div>
<em>
onboarding.create_project.repository_imported

+ 1
- 0
server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreate-test.tsx.snap Просмотреть файл

@@ -17,5 +17,6 @@ exports[`should render correctly 1`] = `
onSelectRepository={[Function]}
searching={false}
showPersonalAccessTokenForm={true}
tokenValidationFailed={false}
/>
`;

+ 1
- 0
server/sonar-web/src/main/js/apps/create/project/__tests__/__snapshots__/BitbucketProjectCreateRenderer-test.tsx.snap Просмотреть файл

@@ -316,6 +316,7 @@ exports[`should render correctly: pat form 1`] = `
}
}
onPersonalAccessTokenCreate={[MockFunction]}
validationFailed={false}
/>
</Fragment>
`;

+ 4
- 4
sonar-core/src/main/resources/org/sonar/l10n/core.properties Просмотреть файл

@@ -3114,6 +3114,7 @@ onboarding.create_project.bbs_not_configured=This feature isn't available
onboarding.create_project.no_bbs_binding=You must have exactly at least 1 Bitbucket Server instance configured in order to use this method, but none were found. Either create the project manually, or contact your system administrator.
onboarding.create_project.no_bbs_binding.admin=You must have exactly at least 1 Bitbucket Server instance configured in order to use this method. You can configure instances under {url}.
onboarding.create_project.enter_pat=Enter personal access token
onboarding.create_project.pat_incorrect=Your personal access token failed to validate.
onboarding.create_project.pat_help.title=How to create a personal access token?
onboarding.create_project.pat_help.bbs_help_1=Click the following link to generate a token in Bitbucket Server, and copy-paste it into the personal access token field.
onboarding.create_project.pat_help.bbs_help_2=Set a name, for example "SonarQube", and select the following permissions:
@@ -3121,10 +3122,9 @@ onboarding.create_project.pat_help.link=Create personal access token
onboarding.create_project.pat_help.bbs_permission_projects=Projects: {perm}
onboarding.create_project.pat_help.bbs_permission_repos=Repositories: {perm}
onboarding.create_project.pat_help.read_permission=Read
onboarding.create_project.error_fetching_bbs_projects=There was an error fetching the projects from Bitbucket Server. Contact your system administrator, or check your personal access token.
onboarding.create_project.error_fetching_bbs_repos=There was an error fetching the repositories from Bitbucket Server. Contact your system administrator, or check your personal access token.
onboarding.create_project.no_bbs_projects=No projects could be fetched from Bitbucket Server. Contact your system administrator, or check your personal access token.
onboarding.create_project.no_bbs_repos=No repositories were found for this project. Contact your system administrator, or check your personal access token.
onboarding.create_project.no_bbs_projects=No projects could be fetched from Bitbucket Server. Contact your system administrator, or {link}.
onboarding.create_project.no_bbs_repos=No repositories were found for this project. Contact your system administrator, or {link}.
onboarding.create_project.update_your_token=update your personal access token
onboarding.create_project.no_bbs_repos.filter=No repositories match your filter.
onboarding.create_project.only_showing_X_first_repos=We're only displaying the first {0} repositories. If you're looking for a repository that's not in this list, use the search above.
onboarding.create_project.import_selected_repo=Set up selected repository

Загрузка…
Отмена
Сохранить