diff --git a/domains/dipan.json b/domains/dipan.json index 617f3f79d..1e7956dd9 100644 --- a/domains/dipan.json +++ b/domains/dipan.json @@ -6,6 +6,6 @@ "email": "dipanroy@mindwebs.org" }, "record": { - "A": "115.187.62.14" + "A": ["115.187.62.14"] } -} \ No newline at end of file +} diff --git a/tests/validations.test.js b/tests/validations.test.js index 2971b82a7..be0199f7a 100644 --- a/tests/validations.test.js +++ b/tests/validations.test.js @@ -1,4 +1,4 @@ -const { validateDomainData } = require('../utils/validations'); +const { validateDomainData, isValidDomain } = require('../utils/validations'); const defaultDomain = { name: 'aaa', @@ -13,6 +13,25 @@ const defaultDomain = { const getstroflen = len => Array(len).fill('a').join(''); +describe('isValidMX', () => { + it('should be valid mx record', () => { + const cases = [ + { mx: 'foobar.com', result: true }, + { mx: 'as.as', result: true }, + { mx: 'ASPMX.L.GOOGLE.COM', result: true }, + { mx: 'ALT4.ASPMX.L.GOOGLE.COM', result: true }, + { mx: 'hello', result: false }, + { mx: 'helalsds-asd5sjdsd.com', result: true }, + { mx: 'helalsds?asd5sjdsd.com', result: false }, + { mx: 'helalsds_asd5sjdsd.com', result: false }, + ]; + + cases.forEach(({ mx, result }) => { + expect(isValidDomain(mx)).toBe(result); + }); + }); +}); + describe('validateDomainData', () => { const invalidCases = [ {}, @@ -32,6 +51,7 @@ describe('validateDomainData', () => { { ...defaultDomain, record: { CNAME: 'http://foobar.com' } }, { ...defaultDomain, record: { CNAME: 'https://foobar.com' } }, { ...defaultDomain, record: { URL: 'foobar.com' } }, + { ...defaultDomain, record: { CNAME: 'foobar.com', A: ['11.22.22.33'] } }, ]; const validCases = [ @@ -44,9 +64,10 @@ describe('validateDomainData', () => { ...defaultDomain, description: getstroflen(99), }, - { ...defaultDomain, record: { CNAME: 'aa.sd', URL: '121,3213' } }, + { ...defaultDomain, record: { CNAME: 'aa.sd' } }, { ...defaultDomain, record: { URL: 'https://foobar.com' } }, { ...defaultDomain, record: { URL: 'http://foobar.com/foobar/' } }, + { ...defaultDomain, record: { CNAME: 'foobar.com', MX: ['ALT4.ASPMX.L.GOOGLE.COM'] } }, ]; it('should return false for invalid data', () => { @@ -60,7 +81,7 @@ describe('validateDomainData', () => { it('should return true if the name is valid', () => { validCases.forEach(data => { const { valid, errors } = validateDomainData(data); - if (!valid) console.log(errors); + if (!valid) console.log(JSON.stringify(errors, null, 2)); expect(valid).toBe(true); expect(errors).toEqual([]); }); diff --git a/utils/constants.js b/utils/constants.js index f3ef2b6ac..5d125b172 100644 --- a/utils/constants.js +++ b/utils/constants.js @@ -21,12 +21,12 @@ const DOMAINS_PATH = require('path').resolve('domains'); module.exports = { ENV, IS_TEST, - VALID_RECORD_TYPES: ['CNAME', 'A', 'URL'], + VALID_RECORD_TYPES: ['CNAME', 'A', 'URL', 'MX'], DOMAIN_DOMAIN: DOMAIN_DOMAIN || 'booboo.xyz', DOMAIN_USER: IS_TEST ? 'testuser' : DOMAIN_USER, DOMAIN_API_KEY: IS_TEST ? 'testkey' : DOMAIN_API_KEY, DOMAIN_API_HOST: IS_TEST ? 'example.com' : DOMAIN_API_HOST, DOMAIN_API_PORT: IS_TEST ? 6969 : DOMAIN_API_PORT, DOMAINS_PATH, - TTL: 5*60*60, + TTL: 5 * 60 * 60, }; diff --git a/utils/validations.js b/utils/validations.js index 7365a2ab0..c37a68925 100644 --- a/utils/validations.js +++ b/utils/validations.js @@ -4,16 +4,33 @@ const { or, and, validate, between, testRegex, withLengthEq, withLengthGte } = r const isValidURL = testRegex(/^https?:\/\//ig); +const isValidDomain = testRegex(/^(([a-z0-9\-]+)\.)+[a-z]+$/ig) + +// TODO: Add priority to records + +const allowMXRecord = R.compose( + R.ifElse(R.includes('MX'), withLengthEq(2), withLengthEq(1)), + R.keys, +); + const validateCnameRecord = key => and([ R.propSatisfies(R.is(String), key), - R.compose(withLengthEq(1), R.reject(R.equals('URL')), R.keys), - R.propSatisfies(withLengthGte(3), key), - R.propSatisfies(R.complement(isValidURL), key), + allowMXRecord, + R.propSatisfies(withLengthGte(4), key), + R.propSatisfies(isValidDomain, key), + //R.propSatisfies(R.complement(isValidURL), key), ]); const validateARecord = key => and([ - R.compose(withLengthEq(1), R.keys), + allowMXRecord, R.propSatisfies(withLengthGte(1), key), + R.propIs(Array, key), +]); + +const validateMXRecord = key => and([ + R.propSatisfies(withLengthGte(1), key), + R.propSatisfies(R.all(isValidDomain), key), + R.propIs(Array, key), ]); const validateDomainData = validate({ @@ -35,7 +52,7 @@ const validateDomainData = validate({ R.is(Object), R.complement(R.isEmpty), R.where({ - username: and([ R.is(String), withLengthGte(1) ]), + username: and([R.is(String), withLengthGte(1)]), email: R.is(String), }), ]), @@ -46,13 +63,14 @@ const validateDomainData = validate({ R.is(Object), R.compose(R.isEmpty, R.difference(R.__, VALID_RECORD_TYPES), R.keys), R.cond([ - [R.has('CNAME'), validateCnameRecord('CNAME')], - [R.has('A'), validateARecord('A')], - [R.has('URL'), R.propSatisfies(isValidURL, 'URL')], + [R.has('CNAME'), validateCnameRecord('CNAME')], + [R.has('A'), validateARecord('A')], + [R.has('URL'), R.propSatisfies(isValidURL, 'URL')], + [R.has('MX'), validateMXRecord('MX')], [R.T, R.T], ]), ]), }, }); -module.exports = { validateDomainData }; +module.exports = { validateDomainData, isValidDomain };