Skip to content

Commit

Permalink
Allow more protocols in URL fields.
Browse files Browse the repository at this point in the history
Allow repositories with ssh:// (and its short git form),
git://, svn://, svn+ssh:// as protocol in URL fields, via
a new "repourl" field type.

Also, use https:// as the placeholder for URL fields, to
drop a hint to the user about the nature of such fields.
  • Loading branch information
bfabio committed Nov 8, 2019
1 parent 1613c56 commit 549e0f1
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/app/contents/fields/generic.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const fields = async () => {
type: "string",
description:
"A unique identifier for this software. This string must be a URL to the source code repository (git, svn, ...) in which the software is published. If the repository is available under multiple protocols, prefer HTTP/HTTPS URLs which don't require user authentication.",
widget: "url",
widget: "repourl",
section: 1,
required: true
},
Expand Down Expand Up @@ -218,7 +218,7 @@ const fields = async () => {
description:
"In case this software is a variant or a fork of another software, which might or might not contain a publiccode.yml file, this key will contain the url of the original project(s). The existence of this key identifies the fork as a software variant, descending from the specified repositories.",
section: 2,
widget: "url"
widget: "repourl"
},

{
Expand Down
2 changes: 1 addition & 1 deletion src/app/form/widgets/UrlWidget.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import BaseInputWidget from "./BaseInputWidget";

const UrlWidget = props => {
return <BaseInputWidget type="url" {...props} />;
return <BaseInputWidget type="url" placeholder="https://" {...props} />;
};

export default UrlWidget;
1 change: 1 addition & 0 deletions src/app/form/widgets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default {
password: PasswordWidget,
search: SearchWidget,
url: UrlWidget,
repourl: UrlWidget,
color: ColorWidget,
choice: ChoiceWidget,
"choice-expanded": ChoiceExpandedWidget,
Expand Down
14 changes: 13 additions & 1 deletion src/app/utils/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,19 @@ export const checkField = (field, obj, value, required) => {
return "This property is required.";

if (widget == "url" && !validator.isURL(value, {require_protocol: true})) {
return "Not a valid Url";
return "Not a valid URL";
}
if (widget == "repourl"
&& !validator.isURL(value, {require_protocol: true})
// Eg. ssh://example.com/repo.git
// git://example.com/repo.git
// svn://example.com/repo
// svn+ssh://example.com/repo
&& !value.match(/^(ssh|git|svn|svn\+ssh):\/\/(\w+@?)\w+\.\w+.*/)
// Eg. [email protected]:foo/bar.git
// github.com:/foo/bar.git
&& !value.match(/^(\w+@?)\w+\.\w+:.*/)) {
return "Not a valid repository URL";
}
if (widget == "email" && !validator.isEmail(value)) {
return "Not a valid email";
Expand Down
98 changes: 91 additions & 7 deletions src/test/unit.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,40 +78,124 @@ test('URL test', () => {
expect(val.checkField('', {
widget: 'url'
}, 'hppp://google.it', true))
.toBe('Not a valid Url');
.toBe('Not a valid URL');

expect(val.checkField('', {
widget: 'url'
}, 'http://google', true))
.toBe('Not a valid Url');
.toBe('Not a valid URL');

expect(val.checkField('', {
widget: 'url'
}, 'httpz://google.it', true))
.toBe('Not a valid Url');
.toBe('Not a valid URL');

expect(val.checkField('', {
widget: 'url'
}, 'http:/google.it', true))
.toBe('Not a valid Url');
.toBe('Not a valid URL');

expect(val.checkField('', {
widget: 'url'
}, 'https:///google.it', true))
.toBe('Not a valid Url');
.toBe('Not a valid URL');

expect(val.checkField('', {
widget: 'url'
}, 'http//google.it', true))
.toBe('Not a valid Url');
.toBe('Not a valid URL');

expect(val.checkField('', {
widget: 'url'
}, 'http:/googleit', true))
.toBe('Not a valid Url');
.toBe('Not a valid URL');

expect(val.checkField('', {
widget: 'url'
}, 'https://google.it', true))
.toBeNull();
});

test('repourl validation', () => {
expect(val.checkField('', {
widget: 'repourl'
}, 'hppp://google.it', true))
.toBe('Not a valid repository URL');

expect(val.checkField('', {
widget: 'repourl'
}, 'http://google', true))
.toBe('Not a valid repository URL');

expect(val.checkField('', {
widget: 'repourl'
}, 'httpz://google.it', true))
.toBe('Not a valid repository URL');

expect(val.checkField('', {
widget: 'repourl'
}, 'http:/google.it', true))
.toBe('Not a valid repository URL');

expect(val.checkField('', {
widget: 'repourl'
}, 'https:///google.it', true))
.toBe('Not a valid repository URL');

expect(val.checkField('', {
widget: 'repourl'
}, 'http//google.it', true))
.toBe('Not a valid repository URL');

expect(val.checkField('', {
widget: 'repourl'
}, 'http:/googleit', true))
.toBe('Not a valid repository URL');

expect(val.checkField('', {
widget: 'repourl'
}, 'https://google.it', true))
.toBeNull();

// Valid git scp-like syntax
expect(val.checkField('', {
widget: 'repourl'
}, '[email protected]:foobar/baz.git', true))
.toBeNull();

// Invalid syntax, the username is empty
expect(val.checkField('', {
widget: 'repourl'
}, '@example.com:foobar/baz.git', true))
.toBe('Not a valid repository URL');

// Valid git:// URL
expect(val.checkField('', {
widget: 'repourl'
}, 'git://example.com/foobar/baz.git', true))
.toBeNull();

// Invalid syntax, the match is not at the beginning
expect(val.checkField('', {
widget: 'repourl'
}, 'junk at beginning git://example.com:foobar/baz.git', true))
.toBe('Not a valid repository URL');

// Valid svn:// URL
expect(val.checkField('', {
widget: 'repourl'
}, 'svn://example.com/foobar/baz/', true))
.toBeNull();

// Valid ssh:// URL
expect(val.checkField('', {
widget: 'repourl'
}, 'ssh://example.com/foobar/baz.git', true))
.toBeNull();

// Valid svn+ssh:// URL
expect(val.checkField('', {
widget: 'repourl'
}, 'svn+ssh://example.com/foobar/baz/', true))
.toBeNull();
});

0 comments on commit 549e0f1

Please sign in to comment.