mirror of https://github.com/rancher/dashboard.git
Merge pull request #14319 from torchiaf/14317-url-validation
Fleet improve Repository URL and OCI registry validation
This commit is contained in:
commit
68041cc26c
|
|
@ -6761,10 +6761,10 @@ validation:
|
|||
flowOutput:
|
||||
both: Requires "Output" or "Cluster Output" to be selected.
|
||||
global: Requires "Cluster Output" to be selected.
|
||||
git:
|
||||
url: URL must be a HTTP(s) or SSH url with no trailing spaces
|
||||
repository:
|
||||
url: It must be a valid HTTP(s) or SSH URL with no trailing spaces
|
||||
oci:
|
||||
url: URL must be an OCI url with no trailing spaces
|
||||
url: It must be a valid OCI URL with no trailing spaces
|
||||
output:
|
||||
logdna:
|
||||
apiKey: Required an "Api Key" to be set.
|
||||
|
|
|
|||
|
|
@ -107,10 +107,7 @@ export default {
|
|||
targetsCreated: '',
|
||||
fvFormRuleSets: [{
|
||||
path: 'spec.repo',
|
||||
rules: [
|
||||
'required',
|
||||
'urlRepository'
|
||||
],
|
||||
rules: ['urlRepository'],
|
||||
}],
|
||||
touched: null,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ export default {
|
|||
case SOURCE_TYPE.REPO:
|
||||
this.fvFormRuleSets = [{
|
||||
path: 'spec.helm.repo',
|
||||
rules: ['required', 'urlRepository'],
|
||||
rules: ['urlRepository'],
|
||||
}, {
|
||||
path: 'spec.helm.chart',
|
||||
rules: ['required'],
|
||||
|
|
@ -416,7 +416,7 @@ export default {
|
|||
case SOURCE_TYPE.OCI:
|
||||
this.fvFormRuleSets = [{
|
||||
path: 'spec.helm.repo',
|
||||
rules: ['required', 'ociRegistry'],
|
||||
rules: ['ociRegistry'],
|
||||
}, {
|
||||
path: 'spec.helm.version',
|
||||
rules: ['semanticVersion'],
|
||||
|
|
@ -425,7 +425,7 @@ export default {
|
|||
case SOURCE_TYPE.TARBALL:
|
||||
this.fvFormRuleSets = [{
|
||||
path: 'spec.helm.chart',
|
||||
rules: ['required', 'urlRepository'],
|
||||
rules: ['urlRepository'],
|
||||
}];
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,32 +97,54 @@ describe('formRules', () => {
|
|||
});
|
||||
|
||||
describe('urlRepository', () => {
|
||||
const message = JSON.stringify({ message: 'validation.git.url' });
|
||||
const message = JSON.stringify({ message: 'validation.repository.url' });
|
||||
const testCases = [
|
||||
// Valid HTTP(s)
|
||||
['https://github.com/rancher/dashboard.git', undefined],
|
||||
['http://github.com/rancher/dashboard.git', undefined],
|
||||
['https://github.com/rancher/dashboard', undefined],
|
||||
['https://github.com/rancher/dashboard/', undefined],
|
||||
['https://github.com/rancher/%20dashboard/', undefined],
|
||||
['https://github.com/rancher/dashboard/%20', undefined],
|
||||
['https://localhost:8005', undefined],
|
||||
|
||||
// Valid SSH
|
||||
['git@github.com:rancher/dashboard.git', undefined],
|
||||
['git@github.com:rancher/dashboard', undefined],
|
||||
['git@github.com:rancher/dashboard/', undefined],
|
||||
['git@github.com:rancher/%20dashboard/', undefined],
|
||||
['git@github.com:rancher/dashboard/%20', undefined],
|
||||
|
||||
// Not valid HTTP(s)
|
||||
['https://github.com/rancher/ dashboard.git', message],
|
||||
['http://github.com/rancher/ dashboard.git', message],
|
||||
['http://github.com/ rancher/dashboard.git', message],
|
||||
['http://github.com /rancher/dashboard.git', message],
|
||||
['https://github.com/rancher/dashboard ', message],
|
||||
['https%20://github.com/rancher/dashboard ', message],
|
||||
['ht%20tps://github.com/rancher/dashboard ', message],
|
||||
['https://git%20hub.com/rancher/dashboard/%20', message],
|
||||
['https://https://', message],
|
||||
['http:/ww.abc.com', message],
|
||||
['http:ww.abc.com', message],
|
||||
['foo://github.com/rancher/dashboard/', message],
|
||||
['github.com/rancher/dashboard/', message],
|
||||
|
||||
// Not valid SSH
|
||||
['git@github.com:rancher/ dashboard.git', message],
|
||||
['git@github.com:rancher/dashboard ', message],
|
||||
['git@github.com:rancher/ dashboard', message],
|
||||
['git @github.com:rancher/dashboard', message],
|
||||
['git@github.com: rancher/dashboard', message],
|
||||
['git@github.comrancher/dashboard', message],
|
||||
['git@githubcomrancher/dashboard', message],
|
||||
['%20git@github.comrancher/dashboard', message],
|
||||
['git@git%20hub.comrancher/dashboard', message],
|
||||
['git@.git', message],
|
||||
['git@', message],
|
||||
|
||||
[undefined, undefined]
|
||||
[undefined, message],
|
||||
['', message]
|
||||
];
|
||||
|
||||
it.each(testCases)(
|
||||
|
|
@ -139,20 +161,26 @@ describe('formRules', () => {
|
|||
const message = JSON.stringify({ message: 'validation.oci.url' });
|
||||
const testCases = [
|
||||
// Valid
|
||||
['oci://bucket/object', undefined],
|
||||
['oci://registry.example.com', undefined],
|
||||
['oci://myregistry.dev:5000', undefined],
|
||||
['oci://192.168.1.100', undefined],
|
||||
['oci://my.domain.com/my/image:tag', undefined],
|
||||
['oci://localhost:5000', undefined],
|
||||
['oci://region.objectstorage.example.com/n', undefined],
|
||||
['oci://a', undefined],
|
||||
['oci://UPPERCASE/path', undefined],
|
||||
|
||||
// Invalid
|
||||
['http://example.com/oci', message],
|
||||
['https://oci.cloud.com', message],
|
||||
['ftp://oci.server.net', message],
|
||||
['/path/to/oci', message],
|
||||
['path/to/oci', message],
|
||||
['oci://a', message],
|
||||
['oci:/missing/slash', message],
|
||||
['oci:', message],
|
||||
['oci://', message],
|
||||
['oci://space between', message],
|
||||
['oci://oci://duplicate/protocol', message],
|
||||
['oci ://registry.example.com/foo/bar', message],
|
||||
['oci://registry.example. com/foo/bar', message],
|
||||
['oci://registry.example.com/ foo/bar', message],
|
||||
['oci://resource multiple spaces', message],
|
||||
['', message],
|
||||
[undefined, message],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import semver from 'semver';
|
||||
import { parse } from '@shell/utils/url';
|
||||
import { RBAC } from '@shell/config/types';
|
||||
import { HCI } from '@shell/config/labels-annotations';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
|
@ -174,22 +175,82 @@ export default function(
|
|||
const genericUrl: Validator = (val: string) => val && !isUrl(val) ? t('validation.genericUrl') : undefined;
|
||||
|
||||
const urlRepository: Validator = (url: string) => {
|
||||
const regexPart1 = /^((http|git|ssh|http(s)|file|\/?)|(git@[\w\.]+))(:(\/\/)?)/gm;
|
||||
const regexPart2 = /^([\w\.@\:\/\-]+)([\d\/\w.-]+?)(.git){0,1}(\/)?$/gm;
|
||||
const message = t('validation.repository.url');
|
||||
|
||||
if (url) {
|
||||
const urlPart2 = url.replaceAll(regexPart1, '');
|
||||
if (!url) {
|
||||
return message;
|
||||
}
|
||||
|
||||
return !urlPart2 || url === urlPart2 || !regexPart2.test(urlPart2.replaceAll('%20', '')) ? t('validation.git.url') : undefined;
|
||||
if (url.includes(' ')) {
|
||||
return message;
|
||||
}
|
||||
|
||||
const {
|
||||
protocol,
|
||||
authority,
|
||||
host,
|
||||
path
|
||||
} = parse(url);
|
||||
|
||||
// Test duplicate protocol
|
||||
if (!host || protocol === host) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Test http(s) protocol
|
||||
if (protocol && (!/^(http|http(s))/gm.test(protocol) || (!url.startsWith('https://') && !url.startsWith('http://')))) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Test ssh, authority must be valid (SSH user + host)
|
||||
if (!protocol && !authority.endsWith(':')) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Encoded space characters (%20) are allowed only in the path
|
||||
const hostAndPath = `${ host }${ path.replaceAll('%20', '') }`;
|
||||
|
||||
// Test host/path
|
||||
if (!/^([\w\.@\:\/\-]+)([\d\/\w.-]+?)(.git){0,1}(\/)?$/gm.test(hostAndPath)) {
|
||||
return message;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const ociRegistry: Validator = (url: string) => {
|
||||
const regex = /^oci:\/\/\S+$/gm;
|
||||
const message = t('validation.oci.url');
|
||||
|
||||
return !regex.test(url) ? t('validation.oci.url') : undefined;
|
||||
if (!url) {
|
||||
return message;
|
||||
}
|
||||
|
||||
if (url.includes(' ')) {
|
||||
return message;
|
||||
}
|
||||
|
||||
const {
|
||||
protocol,
|
||||
host,
|
||||
path
|
||||
} = parse(url);
|
||||
|
||||
// Test duplicate protocol
|
||||
if (!host || protocol === host) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Test oci protocol
|
||||
if (!url.startsWith('oci://')) {
|
||||
return message;
|
||||
}
|
||||
|
||||
// Test host/path
|
||||
if (!/^([\w\.@\:\/\-]+)([\d\/\w.-]+?)(\/)?$/gm.test(`${ host }${ path }`)) {
|
||||
return message;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const version: Validator = (value: string) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue