Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/lib/isAfter.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import toDate from './toDate';

function resolveComparisonDate(options) {
if (options instanceof Date) {
return options;
}
if (typeof options === 'object' && options !== null) {
return options.comparisonDate;
}
return options;
}

export default function isAfter(date, options) {
// For backwards compatibility:
// isAfter(str [, date]), i.e. `options` could be used as argument for the legacy `date`
const comparisonDate = (typeof options === 'object' ? options.comparisonDate : options) || Date().toString();
const comparisonDate = resolveComparisonDate(options) || Date().toString();

const comparison = toDate(comparisonDate);
const comparison = comparisonDate instanceof Date
? comparisonDate
: toDate(comparisonDate);
const original = toDate(date);

return !!(original && comparison && original > comparison);
Expand Down
16 changes: 14 additions & 2 deletions src/lib/isBefore.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import toDate from './toDate';

function resolveComparisonDate(options) {
if (options instanceof Date) {
return options;
}
if (typeof options === 'object' && options !== null) {
return options.comparisonDate;
}
return options;
}

export default function isBefore(date, options) {
// For backwards compatibility:
// isBefore(str [, date]), i.e. `options` could be used as argument for the legacy `date`
const comparisonDate = (typeof options === 'object' ? options.comparisonDate : options) || Date().toString();
const comparisonDate = resolveComparisonDate(options) || Date().toString();

const comparison = toDate(comparisonDate);
const comparison = comparisonDate instanceof Date
? comparisonDate
: toDate(comparisonDate);
const original = toDate(date);

return !!(original && comparison && original < comparison);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/isByteLength.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default function isByteLength(str, options) {
assertString(str);
let min;
let max;
if (typeof (options) === 'object') {
if (options !== null && typeof (options) === 'object') {
min = options.min || 0;
max = options.max;
} else { // backwards compatibility: isByteLength(str, min [, max])
Expand Down
7 changes: 4 additions & 3 deletions src/lib/isCreditCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ export default function isCreditCard(card, options = {}) {
assertString(card);
const { provider } = options;
const sanitized = card.replace(/[- ]+/g, '');
if (provider && provider.toLowerCase() in cards) {
const providerName = provider && provider.toLowerCase();
if (providerName && Object.prototype.hasOwnProperty.call(cards, providerName)) {
// specific provider in the list
if (!(cards[provider.toLowerCase()].test(sanitized))) {
if (!(cards[providerName].test(sanitized))) {
return false;
}
} else if (provider && !(provider.toLowerCase() in cards)) {
} else if (providerName) {
/* specific provider not in the list */
throw new Error(`${provider} is not a valid credit card provider.`);
} else if (!allCards.some(cardProvider => cardProvider.test(sanitized))) {
Expand Down
10 changes: 6 additions & 4 deletions src/lib/isFloat.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import assertString from './util/assertString';
import isNullOrUndefined from './util/nullUndefinedCheck';
import { decimal } from './alpha';

const hasOwnProperty = Object.prototype.hasOwnProperty;

export default function isFloat(str, options) {
assertString(str);
options = options || {};
Expand All @@ -11,10 +13,10 @@ export default function isFloat(str, options) {
}
const value = parseFloat(str.replace(',', '.'));
return float.test(str) &&
(!options.hasOwnProperty('min') || isNullOrUndefined(options.min) || value >= options.min) &&
(!options.hasOwnProperty('max') || isNullOrUndefined(options.max) || value <= options.max) &&
(!options.hasOwnProperty('lt') || isNullOrUndefined(options.lt) || value < options.lt) &&
(!options.hasOwnProperty('gt') || isNullOrUndefined(options.gt) || value > options.gt);
(!hasOwnProperty.call(options, 'min') || isNullOrUndefined(options.min) || value >= options.min) &&
(!hasOwnProperty.call(options, 'max') || isNullOrUndefined(options.max) || value <= options.max) &&
(!hasOwnProperty.call(options, 'lt') || isNullOrUndefined(options.lt) || value < options.lt) &&
(!hasOwnProperty.call(options, 'gt') || isNullOrUndefined(options.gt) || value > options.gt);
}

export const locales = Object.keys(decimal);
4 changes: 2 additions & 2 deletions src/lib/isIn.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export default function isIn(str, options) {
}
}
return array.indexOf(str) >= 0;
} else if (typeof options === 'object') {
return options.hasOwnProperty(str);
} else if (options !== null && typeof options === 'object') {
return Object.prototype.hasOwnProperty.call(options, str);
} else if (options && typeof options.indexOf === 'function') {
return options.indexOf(str) >= 0;
}
Expand Down
10 changes: 6 additions & 4 deletions src/lib/isInt.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import assertString from './util/assertString';
import isNullOrUndefined from './util/nullUndefinedCheck';

const hasOwnProperty = Object.prototype.hasOwnProperty;

const int = /^(?:[-+]?(?:0|[1-9][0-9]*))$/;
const intLeadingZeroes = /^[-+]?[0-9]+$/;

Expand All @@ -13,10 +15,10 @@ export default function isInt(str, options) {
const regex = options.allow_leading_zeroes === false ? int : intLeadingZeroes;

// Check min/max/lt/gt
let minCheckPassed = (!options.hasOwnProperty('min') || isNullOrUndefined(options.min) || str >= options.min);
let maxCheckPassed = (!options.hasOwnProperty('max') || isNullOrUndefined(options.max) || str <= options.max);
let ltCheckPassed = (!options.hasOwnProperty('lt') || isNullOrUndefined(options.lt) || str < options.lt);
let gtCheckPassed = (!options.hasOwnProperty('gt') || isNullOrUndefined(options.gt) || str > options.gt);
let minCheckPassed = (!hasOwnProperty.call(options, 'min') || isNullOrUndefined(options.min) || str >= options.min);
let maxCheckPassed = (!hasOwnProperty.call(options, 'max') || isNullOrUndefined(options.max) || str <= options.max);
let ltCheckPassed = (!hasOwnProperty.call(options, 'lt') || isNullOrUndefined(options.lt) || str < options.lt);
let gtCheckPassed = (!hasOwnProperty.call(options, 'gt') || isNullOrUndefined(options.gt) || str > options.gt);

return regex.test(str) && minCheckPassed && maxCheckPassed && ltCheckPassed && gtCheckPassed;
}
26 changes: 26 additions & 0 deletions test/validators.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4435,6 +4435,10 @@ describe('Validators', () => {
});

it('should validate integers', () => {
const options = Object.create(null);
options.min = 10;
assert.strictEqual(validator.isInt('10', options), true);
assert.strictEqual(validator.isInt('9', options), false);
test({
validator: 'isInt',
valid: [
Expand Down Expand Up @@ -4631,6 +4635,10 @@ describe('Validators', () => {
});

it('should validate floats', () => {
const options = Object.create(null);
options.min = 1.5;
assert.strictEqual(validator.isFloat('1.5', options), true);
assert.strictEqual(validator.isFloat('1.4', options), false);
test({
validator: 'isFloat',
valid: [
Expand Down Expand Up @@ -5755,6 +5763,11 @@ describe('Validators', () => {
valid: [''],
invalid: ['g', 'a'],
});
test({
validator: 'isByteLength',
args: [null],
valid: ['', 'a'],
});
});

it('should validate ULIDs', () => {
Expand Down Expand Up @@ -6148,6 +6161,12 @@ describe('Validators', () => {
valid: ['1', '2', '3'],
invalid: ['4', ''],
});
test({
validator: 'isIn',
args: [Object.create(null, { foo: { value: 1, enumerable: true } })],
valid: ['foo'],
invalid: ['bar', ''],
});
});

it('should validate ABA routing number', () => {
Expand Down Expand Up @@ -6418,6 +6437,13 @@ describe('Validators', () => {
});
});

it('rejects inherited credit card provider names', () => {
assert.throws(
() => validator.isCreditCard('375556917985515', { provider: '__proto__' }),
/__proto__ is not a valid credit card provider/
);
});


it('should validate AmEx provided credit cards', () => {
test({
Expand Down
19 changes: 19 additions & 0 deletions test/validators/isAfter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,22 @@ describe('isAfter', () => {
});
});
});
describe('(legacy syntax with Date object)', () => {
it('should accept a Date object as the second argument and use it as the comparison date', () => {
// Regression: previously `typeof options === 'object' && options.comparisonDate === undefined`
// meant the Date argument was silently ignored and the comparison fell back to "now".
test({
validator: 'isAfter',
args: [new Date('2010-01-01T00:00:00Z')],
valid: ['2010-01-02', '2011-08-04', '2030-01-01', new Date(2020, 0, 1).toString()],
invalid: ['2009-12-31', '2010-01-01', new Date(0).toString()],
});

test({
validator: 'isAfter',
args: [new Date('2030-01-01T00:00:00Z')],
valid: ['2030-01-02', '2050-06-15'],
invalid: ['2025-06-26', '2029-12-31', new Date(2025, 0, 1).toString()],
});
});
});
19 changes: 19 additions & 0 deletions test/validators/isBefore.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,22 @@ describe('isBefore', () => {
});
});
});
describe('legacy syntax with Date object', () => {
it('should accept a Date object as the second argument and use it as the comparison date', () => {
// Regression: previously `typeof options === 'object' && options.comparisonDate === undefined`
// meant the Date argument was silently ignored and the comparison fell back to "now".
test({
validator: 'isBefore',
args: [new Date('2010-01-01T00:00:00Z')],
valid: ['2009-12-31', '1999-12-31', new Date(0).toString()],
invalid: ['2010-01-02', '2011-08-04', '2030-01-01'],
});

test({
validator: 'isBefore',
args: [new Date('2030-01-01T00:00:00Z')],
valid: ['2025-06-26', '2029-12-31', new Date(2025, 0, 1).toString()],
invalid: ['2030-01-02', '2050-06-15'],
});
});
});
Loading