- client: Match client IP strictly: Merge pull request in DNS/adguard-home from fix/1687 to master

Close 

Squashed commit of the following:

commit 5287da0b98d154d4243abdb4b9021006499c225f
Merge: c6b50c70 83b9b701
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Fri May 29 12:47:23 2020 +0300

    Merge branch 'master' into fix/1687

commit c6b50c70a5089fcadfd2606b07b3b84769db2760
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Fri May 29 12:42:12 2020 +0300

    minor

commit dab9fa9ee0502838b4e10aef93d037c2fb5bf41b
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Thu May 28 16:56:08 2020 +0300

    Add support for exact matching of long and short ipv6 notations, add tests

commit e72e86cda81af2c5e54f93abb2890438fd3648b0
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Thu May 28 13:57:22 2020 +0300

    Update helper, write tests

commit 92f4c34224ab7927b02edde829f2d9653a00a854
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed May 27 18:35:05 2020 +0300

    Make variable names more expressive

commit 3d38f21281237e9cccbba26afc1ab641947c5dc0
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Wed May 27 17:09:08 2020 +0300

    Add ipv6 cidr support

commit 7db0a2fb18ccd96d8d1def73f12138e4f4e37f71
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Tue May 26 12:48:57 2020 +0300

    Minor

commit 65e87f3899aab3417cac57bab0a8fa371cafd4ec
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Tue May 26 12:46:30 2020 +0300

    Add breaks between helpers

commit 3f38bdfe7bc17e019bf048c79c9e8f1336b6f3d3
Author: ArtemBaskal <a.baskal@adguard.com>
Date:   Thu May 21 20:17:27 2020 +0300

    - client: Match client IP strictly
This commit is contained in:
Artem Baskal 2020-05-29 12:53:40 +03:00
parent 83b9b70166
commit 72f253f62b
11 changed files with 4151 additions and 71 deletions
client/src/helpers

View file

@ -1,3 +1,4 @@
/* eslint-disable no-bitwise */
import 'url-polyfill';
import dateParse from 'date-fns/parse';
import dateFormat from 'date-fns/format';
@ -10,6 +11,7 @@ import round from 'lodash/round';
import axios from 'axios';
import i18n from 'i18next';
import uniqBy from 'lodash/uniqBy';
import ipaddr from 'ipaddr.js';
import versionCompare from './versionCompare';
import {
@ -24,6 +26,7 @@ import {
DEFAULT_LANGUAGE,
FILTERED_STATUS,
FILTERED,
IP_MATCH_LIST_STATUS,
} from './constants';
/**
@ -167,7 +170,10 @@ export const getPercent = (amount, number) => {
return 0;
};
export const captitalizeWords = (text) => text.split(/[ -_]/g).map((str) => str.charAt(0).toUpperCase() + str.substr(1)).join(' ');
export const captitalizeWords = (text) => text.split(/[ -_]/g)
.map((str) => str.charAt(0)
.toUpperCase() + str.substr(1))
.join(' ');
export const getInterfaceIp = (option) => {
const onlyIPv6 = option.ip_addresses.every((ip) => ip.includes(':'));
@ -187,9 +193,10 @@ export const getInterfaceIp = (option) => {
export const getIpList = (interfaces) => {
let list = [];
Object.keys(interfaces).forEach((item) => {
list = [...list, ...interfaces[item].ip_addresses];
});
Object.keys(interfaces)
.forEach((item) => {
list = [...list, ...interfaces[item].ip_addresses];
});
return list.sort();
};
@ -283,7 +290,9 @@ export const normalizeTextarea = (text) => {
return [];
}
return text.replace(/[;, ]/g, '\n').split('\n').filter((n) => n);
return text.replace(/[;, ]/g, '\n')
.split('\n')
.filter((n) => n);
};
/**
@ -307,7 +316,10 @@ export const normalizeTopClients = (topClients) => topClients.reduce(
// eslint-disable-next-line no-param-reassign
nameToCountMap.configured[infoName] = count;
return nameToCountMap;
}, { auto: {}, configured: {} },
}, {
auto: {},
configured: {},
},
);
export const getClientInfo = (clients, ip) => {
@ -321,7 +333,10 @@ export const getClientInfo = (clients, ip) => {
const { name, whois_info } = client;
const whois = Object.keys(whois_info).length > 0 ? whois_info : '';
return { name, whois };
return {
name,
whois,
};
};
export const getAutoClientInfo = (clients, ip) => {
@ -334,7 +349,10 @@ export const getAutoClientInfo = (clients, ip) => {
const { name, whois_info } = client;
const whois = Object.keys(whois_info).length > 0 ? whois_info : '';
return { name, whois };
return {
name,
whois,
};
};
export const sortClients = (clients) => {
@ -344,7 +362,8 @@ export const sortClients = (clients) => {
if (nameA > nameB) {
return 1;
} if (nameA < nameB) {
}
if (nameA < nameB) {
return -1;
}
@ -366,7 +385,8 @@ export const secondsToMilliseconds = (seconds) => {
return seconds;
};
export const normalizeRulesTextarea = (text) => text && text.replace(/^\n/g, '').replace(/\n\s*\n/g, '\n');
export const normalizeRulesTextarea = (text) => text && text.replace(/^\n/g, '')
.replace(/\n\s*\n/g, '\n');
export const isVersionGreater = (currentVersion, previousVersion) => (
versionCompare(currentVersion, previousVersion) === -1
@ -449,10 +469,17 @@ export const getCurrentFilter = (url, filters) => {
if (filter) {
const { enabled, name, url } = filter;
return { enabled, name, url };
return {
enabled,
name,
url,
};
}
return { name: '', url: '' };
return {
name: '',
url: '',
};
};
/**
@ -463,3 +490,59 @@ export const formatNumber = (num) => {
const currentLanguage = i18n.languages[0] || DEFAULT_LANGUAGE;
return num.toLocaleString(currentLanguage);
};
export const normalizeMultiline = (multiline) => `${normalizeTextarea(multiline)
.map((line) => line.trim())
.join('\n')}\n`;
/**
* @param parsedIp {object} ipaddr.js IPv4 or IPv6 object
* @param cidr {array} ipaddr.js CIDR array
* @returns {boolean}
*/
export const isIpMatchCidr = (parsedIp, parsedCidr) => {
try {
const cidrIpVersion = parsedCidr[0].kind();
const ipVersion = parsedIp.kind();
return ipVersion === cidrIpVersion && parsedIp.match(parsedCidr);
} catch (e) {
return false;
}
};
/**
* @param ip {string}
* @param list {string}
* @returns {'EXACT' | 'CIDR' | 'NOT_FOND'}
*/
export const getIpMatchListStatus = (ip, list) => {
if (!ip || !list) {
return IP_MATCH_LIST_STATUS.NOT_FOUND;
}
const listArr = list.trim()
.split('\n');
try {
for (let i = 0; i < listArr.length; i += 1) {
const listItem = listArr[i];
const parsedIp = ipaddr.parse(ip);
const isItemAnIp = ipaddr.isValid(listItem);
const parsedItem = isItemAnIp ? ipaddr.parse(listItem) : ipaddr.parseCIDR(listItem);
if (isItemAnIp && parsedIp.toString() === parsedItem.toString()) {
return IP_MATCH_LIST_STATUS.EXACT;
}
if (!isItemAnIp && isIpMatchCidr(parsedIp, parsedItem)) {
return IP_MATCH_LIST_STATUS.CIDR;
}
}
return IP_MATCH_LIST_STATUS.NOT_FOUND;
} catch (e) {
return IP_MATCH_LIST_STATUS.NOT_FOUND;
}
};