mirror of https://github.com/rancher/dashboard.git
245 lines
6.9 KiB
JavaScript
245 lines
6.9 KiB
JavaScript
import isEmpty from 'lodash/isEmpty';
|
|
import uniq from 'lodash/uniq';
|
|
import { get } from '@shell/utils/object';
|
|
import { camelToTitle } from '@shell/utils/string';
|
|
import { validateKubernetesName } from './kubernetes-name';
|
|
|
|
export function displayKeyFor(type, key, getters) {
|
|
const intlPrefix = `model.${ type }.${ key }`;
|
|
const intlPrefixLabel = `${ intlPrefix }.label`;
|
|
|
|
if ( getters['i18n/exists'](`${ intlPrefix }.label`) ) {
|
|
return getters['i18n/t'](intlPrefixLabel);
|
|
}
|
|
|
|
if ( getters['i18n/exists'](intlPrefix) ) {
|
|
return getters['i18n/t'](intlPrefix);
|
|
}
|
|
|
|
if ( key.match(/.Id$/) ) {
|
|
return camelToTitle(key.replace(/Id$/, ''));
|
|
}
|
|
|
|
return camelToTitle(key);
|
|
}
|
|
|
|
export function validateLength(val, field, displayKey, getters, errors = []) {
|
|
const {
|
|
nullable,
|
|
required,
|
|
type = '',
|
|
minLength,
|
|
maxLength,
|
|
min: fieldMin,
|
|
max: fieldMax,
|
|
} = field;
|
|
const len = val ? get(val, 'length') : 0;
|
|
|
|
if ( !nullable && required) {
|
|
if ((typeof val === 'object' && isEmpty(val)) || (!val && val !== 0)) {
|
|
errors.push(getters['i18n/t']('validation.required', { key: displayKey }));
|
|
|
|
return errors;
|
|
}
|
|
}
|
|
|
|
if ( val === null ) {
|
|
return errors;
|
|
}
|
|
|
|
// i18n-uses validation.*.exactly, validation.*.between, validation.*.min, validation.*.max
|
|
const lengthKey = (type.indexOf('array[') === 0 ? 'arrayLength' : 'stringLength');
|
|
|
|
// String and array length:
|
|
let min = minLength;
|
|
let max = maxLength;
|
|
|
|
if ( min && max ) {
|
|
if ( (len < min) || (len > max) ) {
|
|
if ( min === max ) {
|
|
errors.push(getters['i18n/t'](`validation.${ lengthKey }.exactly`, { key: displayKey, count: min }));
|
|
} else {
|
|
errors.push(getters['i18n/t'](`validation.${ lengthKey }.between`, {
|
|
key: displayKey, min, max
|
|
}));
|
|
}
|
|
}
|
|
} else if ( min && (len < min) ) {
|
|
errors.push(getters['i18n/t'](`validation.${ lengthKey }.min`, { key: displayKey, count: min }));
|
|
} else if ( max && (len > max) ) {
|
|
errors.push(getters['i18n/t'](`validation.${ lengthKey }.max`, { key: displayKey, count: max }));
|
|
}
|
|
|
|
// Number min/max
|
|
min = fieldMin;
|
|
max = fieldMax;
|
|
|
|
if ( val !== null && min && max ) {
|
|
if ( (val < min) || (val > max) ) {
|
|
if ( min === max ) {
|
|
errors.push(getters['i18n/t']('validation.number.exactly', { key: displayKey, val: max }));
|
|
} else {
|
|
errors.push(getters['i18n/t']('validation.number.between', {
|
|
key: displayKey, min, max
|
|
}));
|
|
}
|
|
}
|
|
} else if ( min && (val < min) ) {
|
|
errors.push(getters['i18n/t']('validation.number.min', { key: displayKey, val: min }));
|
|
} else if ( max && (val > max) ) {
|
|
errors.push(getters['i18n/t']('validation.number.max', { key: displayKey, val: max }));
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
export function validateChars(val, field, displayKey, getters, errors = []) {
|
|
const {
|
|
validChars,
|
|
invalidChars
|
|
} = field;
|
|
const test = [];
|
|
|
|
if ( validChars ) {
|
|
test.push(`[^${ field.validChars }]`);
|
|
}
|
|
|
|
if ( invalidChars ) {
|
|
test.push(`[${ field.invalidChars }]`);
|
|
}
|
|
|
|
if ( test.length ) {
|
|
const regex = new RegExp(`(${ test.join('|') })`, 'g');
|
|
let match = val.match(regex);
|
|
|
|
if ( match ) {
|
|
match = uniq(match).map((chr) => {
|
|
if ( chr === ' ' ) {
|
|
return '[space]';
|
|
} else {
|
|
return chr;
|
|
}
|
|
});
|
|
|
|
errors.push(getters['i18n/t']('validation.chars', {
|
|
key: displayKey, count: match.length, chars: match.join(' ')
|
|
}));
|
|
}
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
export function validateHostname(val, displayKey, getters, opts, errors = []) {
|
|
opts = opts || {};
|
|
|
|
const {
|
|
max = 253,
|
|
restricted = false,
|
|
} = opts;
|
|
|
|
// Hostname can not start with a dot
|
|
if (val.slice(0, 1) === '.') {
|
|
errors.push(getters['i18n/t']('validation.dns.hostname.startDot', { key: displayKey }));
|
|
}
|
|
|
|
// Hostname can not end with a dot in restricted mode
|
|
if ( restricted && val.length > 1 && val.slice(-1) === '.' ) {
|
|
errors.push(getters['i18n/t']('validation.dns.hostname.endDot', { key: displayKey }));
|
|
}
|
|
|
|
// Hostname can not be empty string
|
|
if (val.length === 0) {
|
|
errors.push(getters['i18n/t']('validation.dns.hostname.empty', { key: displayKey }));
|
|
}
|
|
|
|
// Total length of the hostname can be at most 253 characters
|
|
// (255 minus one for null-termination, and one for the trailing dot of a real FQDN)
|
|
if (val.length > max) {
|
|
errors.push(getters['i18n/t']('validation.dns.hostname.tooLong', { key: displayKey, max }));
|
|
}
|
|
|
|
// Split the hostname with the dot and validate the element as label
|
|
const labels = val.split(/\./);
|
|
let label;
|
|
|
|
for ( let i = 0 ; i < labels.length ; i++ ) {
|
|
label = labels[i];
|
|
|
|
// Already checked if Hostname starts with a dot
|
|
if ( i === 0 && label === '' ) {
|
|
continue;
|
|
}
|
|
|
|
// Hostname can end with a dot (this makes it an explicitly fully qualified domain name)
|
|
// so the last element of the labels can be empty string.
|
|
if (i === labels.length - 1 && label === '') {
|
|
continue;
|
|
}
|
|
|
|
validateDnsLabel(label, displayKey, getters, { forHostname: true }, errors);
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
export function validateDnsLabel(label, displayKey, getters, opts, errors = []) {
|
|
opts = opts || {};
|
|
|
|
const {
|
|
forHostname = false,
|
|
errorKey = (forHostname ? 'hostname' : 'label'),
|
|
ianaServiceName = false,
|
|
restricted = false,
|
|
} = opts;
|
|
|
|
validateKubernetesName(label, displayKey, getters, opts, errors);
|
|
|
|
// Restricted labels cannot begin with a number
|
|
if ( restricted && label.slice(0, 1).match(/[0-9]/) ) {
|
|
errors.push(getters['i18n/t'](`validation.dns.${ errorKey }.startNumber`, { key: displayKey }));
|
|
}
|
|
|
|
// Label cannot contain two consecutive hyphens at the 3rd & 4th characters, unless an IDN string
|
|
// If is of type ianaServiceName can not contain two consecutive hyphens in any position
|
|
if (
|
|
( label.substr(2, 2) === '--' && label.substr(0, 2) !== 'xn' ) ||
|
|
( ianaServiceName && label.includes('--') )
|
|
) {
|
|
errors.push(getters['i18n/t'](`validation.dns.doubleHyphen`, { key: displayKey }));
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
export function validateDnsLikeTypes(val, type, displayKey, getters, opts, errors = []) {
|
|
switch (type) {
|
|
case 'dnsLabel':
|
|
validateDnsLabel(val, displayKey, getters, { restricted: false }, errors);
|
|
break;
|
|
case 'dnsLabelRestricted':
|
|
validateDnsLabel(val, displayKey, getters, { restricted: true }, errors);
|
|
break;
|
|
case 'hostname':
|
|
validateHostname(val, displayKey, getters, { restricted: false }, errors);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
export function validateBoolean(val, field, displayKey, getters, errors = []) {
|
|
const { required } = field;
|
|
|
|
if (required && !val && val !== false) {
|
|
errors.push(getters['i18n/t']('validation.required', { key: displayKey }));
|
|
|
|
return;
|
|
}
|
|
if (typeof val !== 'boolean' && !!val) {
|
|
errors.push(getters['i18n/t']('validation.boolean', { key: displayKey }));
|
|
}
|
|
}
|