Skip to content

Commit

Permalink
Add IsIpRange validator (fix typestack#727)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ballinette committed Oct 6, 2023
1 parent ca2ff26 commit 5a5211d
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -860,6 +860,7 @@ isBoolean(value);
| `@IsOctal()` | Checks if the string is a octal number. |
| `@IsMACAddress(options?: IsMACAddressOptions)` | Checks if the string is a MAC Address. |
| `@IsIP(version?: "4"\|"6")` | Checks if the string is an IP (version 4 or 6). |
| `@IsIPRange(version?: "4"\|"6")` | Checks if the string is an IP Range (version 4 or 6). |
| `@IsPort()` | Checks if the string is a valid port number. |
| `@IsISBN(version?: "10"\|"13")` | Checks if the string is an ISBN (version 10 or 13). |
| `@IsEAN()` | Checks if the string is an if the string is an EAN (European Article Number). |
Expand Down
1 change: 1 addition & 0 deletions src/decorator/decorators.ts
Expand Up @@ -64,6 +64,7 @@ export * from './string/IsHexColor';
export * from './string/IsHexadecimal';
export * from './string/IsMacAddress';
export * from './string/IsIP';
export * from './string/IsIPRange';
export * from './string/IsPort';
export * from './string/IsISBN';
export * from './string/IsISIN';
Expand Down
35 changes: 35 additions & 0 deletions src/decorator/string/IsIPRange.ts
@@ -0,0 +1,35 @@
import { ValidationOptions } from '../ValidationOptions';
import { buildMessage, ValidateBy } from '../common/ValidateBy';
import isIPRangeValidator from 'validator/lib/isIPRange';

export type IsIpRangeVersion = '4' | '6' | 4 | 6;

export const IS_IP_RANGE = 'isIpRange';

/**
* Checks if the string is an IP Range (version 4 or 6).
* If given value is not a string, then it returns false.
*/
export function isIPRange(value: unknown, version?: IsIpRangeVersion): boolean {
/* eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion */
const versionStr = version ? (`${version}` as '4' | '6') : undefined;
return typeof value === 'string' && isIPRangeValidator(value, versionStr);
}

/**
* Checks if the string is an IP Range (version 4 or 6).
* If given value is not a string, then it returns false.
*/
export function IsIPRange(version?: IsIpRangeVersion, validationOptions?: ValidationOptions): PropertyDecorator {
return ValidateBy(
{
name: IS_IP_RANGE,
constraints: [version],
validator: {
validate: (value, args): boolean => isIP(value, args?.constraints[0]),
defaultMessage: buildMessage(eachPrefix => eachPrefix + '$property must be an ip range', validationOptions),
},
},
validationOptions
);
}
64 changes: 64 additions & 0 deletions test/functional/validation-functions-and-decorators.spec.ts
Expand Up @@ -29,6 +29,7 @@ import {
IsHexColor,
IsHexadecimal,
IsIP,
IsIPRange,
IsISBN,
IsISO8601,
IsIn,
Expand Down Expand Up @@ -108,6 +109,7 @@ import {
isISBN,
isISO8601,
isIP,
isIPRange,
isJSON,
isJWT,
isLowercase,
Expand Down Expand Up @@ -2857,6 +2859,68 @@ describe('IsIP', () => {
});
});

describe('IsIPRange', () => {
const validValues = [
'127.0.0.1/24',
'0.0.0.0/0',
'255.255.255.0/32',
'::/0',
'::/128',
'2001::/128',
'2001:800::/128',
'::ffff:127.0.0.1/128',
];
const invalidValues = [
null,
undefined,
'abc',
'127.200.230.1/35',
'127.200.230.1/-1',
'1.1.1.1/011',
'1.1.1/24.1',
'1.1.1.1/01',
'1.1.1.1/1.1',
'1.1.1.1/1.',
'1.1.1.1/1/1',
'1.1.1.1',
'::1',
'::1/164',
'2001::/240',
'2001::/-1',
'2001::/001',
'2001::/24.1',
'2001:db8:0000:1:1:1:1:1',
'::ffff:127.0.0.1',
];

class MyClass {
@IsIP()
someProperty: string;
}

it('should not fail if validator.validate said that its valid', () => {
return checkValidValues(new MyClass(), validValues);
});

it('should fail if validator.validate said that its invalid', () => {
return checkInvalidValues(new MyClass(), invalidValues);
});

it('should not fail if method in validator said that its valid', () => {
validValues.forEach(value => expect(isIPRange(value)).toBeTruthy());
});

it('should fail if method in validator said that its invalid', () => {
invalidValues.forEach(value => expect(isIPRange(value)).toBeFalsy());
});

it('should return error object with proper data', () => {
const validationType = 'isIpRange';
const message = 'someProperty must be an ip range';
return checkReturnedError(new MyClass(), invalidValues, validationType, message);
});
});

describe('IsISBN version 10', () => {
const validValues = [
'3836221195',
Expand Down

0 comments on commit 5a5211d

Please sign in to comment.