- {formatClientCell(value, clients, autoClients)}
+ {formatClientCell(value, clients, autoClients, t)}
{isRewrite ? (
diff --git a/client/src/components/Settings/Clients/AutoClients.js b/client/src/components/Settings/Clients/AutoClients.js
index 1e8a9bdf..abfe8a0d 100644
--- a/client/src/components/Settings/Clients/AutoClients.js
+++ b/client/src/components/Settings/Clients/AutoClients.js
@@ -4,9 +4,12 @@ import { withNamespaces } from 'react-i18next';
import ReactTable from 'react-table';
import Card from '../../ui/Card';
-import WhoisCell from './WhoisCell';
import WrapCell from './WrapCell';
+import whoisCell from './whoisCell';
+
+const COLUMN_MIN_WIDTH = 200;
+
class AutoClients extends Component {
getStats = (ip, stats) => {
if (stats) {
@@ -21,26 +24,31 @@ class AutoClients extends Component {
{
Header: this.props.t('table_client'),
accessor: 'ip',
+ minWidth: COLUMN_MIN_WIDTH,
Cell: WrapCell,
},
{
Header: this.props.t('table_name'),
accessor: 'name',
+ minWidth: COLUMN_MIN_WIDTH,
Cell: WrapCell,
},
{
Header: this.props.t('source_label'),
accessor: 'source',
+ minWidth: COLUMN_MIN_WIDTH,
Cell: WrapCell,
},
{
Header: this.props.t('whois'),
accessor: 'whois_info',
- Cell: WhoisCell,
+ minWidth: COLUMN_MIN_WIDTH,
+ Cell: whoisCell(this.props.t),
},
{
Header: this.props.t('requests_count'),
accessor: 'statistics',
+ minWidth: COLUMN_MIN_WIDTH,
Cell: (row) => {
const clientIP = row.original.ip;
const clientStats = clientIP && this.getStats(clientIP, this.props.topClients);
diff --git a/client/src/components/Settings/Clients/ClientsTable.js b/client/src/components/Settings/Clients/ClientsTable.js
index 53b4414e..6fee7217 100644
--- a/client/src/components/Settings/Clients/ClientsTable.js
+++ b/client/src/components/Settings/Clients/ClientsTable.js
@@ -7,7 +7,8 @@ import { MODAL_TYPE, CLIENT_ID } from '../../../helpers/constants';
import Card from '../../ui/Card';
import Modal from './Modal';
import WrapCell from './WrapCell';
-import WhoisCell from './WhoisCell';
+
+import whoisCell from './whoisCell';
class ClientsTable extends Component {
handleFormAdd = (values) => {
@@ -138,11 +139,17 @@ class ClientsTable extends Component {
return (
- {value && value.length > 0 ? value.map(service => (
-
- )) : '–'}
+ {value && value.length > 0
+ ? value.map(service => (
+
+ ))
+ : '–'}
);
},
@@ -151,7 +158,7 @@ class ClientsTable extends Component {
Header: this.props.t('whois'),
accessor: 'whois_info',
minWidth: 200,
- Cell: WhoisCell,
+ Cell: whoisCell(this.props.t),
},
{
Header: this.props.t('requests_count'),
diff --git a/client/src/components/Settings/Clients/WhoisCell.js b/client/src/components/Settings/Clients/WhoisCell.js
deleted file mode 100644
index a41137fa..00000000
--- a/client/src/components/Settings/Clients/WhoisCell.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { Trans } from 'react-i18next';
-
-const getFormattedWhois = (value) => {
- const keys = Object.keys(value);
-
- if (keys.length > 0) {
- return (
- keys.map(key => (
-
- text]}
- >
- {key}
-
-
- ))
- );
- }
-
- return '–';
-};
-
-const WhoisCell = ({ value }) => (
-
-
- {getFormattedWhois(value)}
-
-
-);
-
-WhoisCell.propTypes = {
- value: PropTypes.object.isRequired,
-};
-
-export default WhoisCell;
diff --git a/client/src/components/Settings/Clients/WrapCell.js b/client/src/components/Settings/Clients/WrapCell.js
index efc3b100..2a5413b7 100644
--- a/client/src/components/Settings/Clients/WrapCell.js
+++ b/client/src/components/Settings/Clients/WrapCell.js
@@ -10,10 +10,7 @@ const WrapCell = ({ value }) => (
);
WrapCell.propTypes = {
- value: PropTypes.oneOfType([
- PropTypes.string,
- PropTypes.number,
- ]),
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};
export default WrapCell;
diff --git a/client/src/components/Settings/Clients/whoisCell.js b/client/src/components/Settings/Clients/whoisCell.js
new file mode 100644
index 00000000..45ad951b
--- /dev/null
+++ b/client/src/components/Settings/Clients/whoisCell.js
@@ -0,0 +1,43 @@
+import React, { Fragment } from 'react';
+
+import { normalizeWhois } from '../../../helpers/helpers';
+import { WHOIS_ICONS } from '../../../helpers/constants';
+
+const getFormattedWhois = (value, t) => {
+ const whoisInfo = normalizeWhois(value);
+ const whoisKeys = Object.keys(whoisInfo);
+
+ if (whoisKeys.length > 0) {
+ return whoisKeys.map((key) => {
+ const icon = WHOIS_ICONS[key];
+ return (
+
+ {icon && (
+
+
+
+
+ )}
+ {whoisInfo[key]}
+
+ );
+ });
+ }
+
+ return '–';
+};
+
+const whoisCell = t =>
+ function cell(row) {
+ const { value } = row;
+
+ return (
+
+ {getFormattedWhois(value, t)}
+
+ );
+ };
+
+export default whoisCell;
diff --git a/client/src/components/ui/Icons.js b/client/src/components/ui/Icons.js
index ef2fbf85..22346b9b 100644
Binary files a/client/src/components/ui/Icons.js and b/client/src/components/ui/Icons.js differ
diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js
index 997002fd..8c227dac 100644
--- a/client/src/helpers/constants.js
+++ b/client/src/helpers/constants.js
@@ -267,3 +267,10 @@ export const STATS_INTERVALS_DAYS = [1, 7, 30, 90];
export const QUERY_LOG_INTERVALS_DAYS = [1, 7, 30, 90];
export const FILTERS_INTERVALS_HOURS = [0, 1, 12, 24, 72, 168];
+
+export const WHOIS_ICONS = {
+ location: 'location',
+ orgname: 'network',
+ netname: 'network',
+ descr: '',
+};
diff --git a/client/src/helpers/formatClientCell.js b/client/src/helpers/formatClientCell.js
index 1facf7c9..054b41f6 100644
--- a/client/src/helpers/formatClientCell.js
+++ b/client/src/helpers/formatClientCell.js
@@ -1,32 +1,55 @@
import React, { Fragment } from 'react';
-import { getClientInfo } from './helpers';
+import { getClientInfo, normalizeWhois } from './helpers';
+import { WHOIS_ICONS } from './constants';
-export const formatClientCell = (value, clients, autoClients) => {
+const getFormattedWhois = (whois, t) => {
+ const whoisInfo = normalizeWhois(whois);
+ return (
+ Object.keys(whoisInfo).map((key) => {
+ const icon = WHOIS_ICONS[key];
+ return (
+
+ {icon && (
+
+
+
+ )}{whoisInfo[key]}
+
+ );
+ })
+ );
+};
+
+export const formatClientCell = (value, clients, autoClients, t) => {
const clientInfo = getClientInfo(clients, value) || getClientInfo(autoClients, value);
const { name, whois } = clientInfo;
+ let whoisContainer = '';
+ let nameContainer = value;
- if (whois && name) {
- return (
-
-
- {name} ({value})
-
-
- {whois}
-
-
- );
- } else if (name) {
- return (
+ if (name) {
+ nameContainer = (
{name} ({value})
);
}
+ if (whois) {
+ whoisContainer = (
+
+ {getFormattedWhois(whois, t)}
+
+ );
+ }
+
return (
-
- {value}
+
+
+ {nameContainer}
+ {whoisContainer}
+
);
};
diff --git a/client/src/helpers/helpers.js b/client/src/helpers/helpers.js
index 9b35c635..7ded995a 100644
--- a/client/src/helpers/helpers.js
+++ b/client/src/helpers/helpers.js
@@ -245,21 +245,6 @@ export const redirectToCurrentProtocol = (values, httpPort = 80) => {
export const normalizeTextarea = text => text && text.replace(/[;, ]/g, '\n').split('\n').filter(n => n);
-const formatWhois = (whois) => {
- if (!whois) {
- return '';
- }
-
- const keys = Object.keys(whois);
- if (keys.length > 0) {
- return (
- keys.map(key => whois[key])
- );
- }
-
- return '';
-};
-
export const getClientInfo = (clients, ip) => {
const client = clients.find(item => ip === item.ip);
@@ -268,8 +253,7 @@ export const getClientInfo = (clients, ip) => {
}
const { name, whois_info } = client;
- const formattedWhois = formatWhois(whois_info);
- const whois = formattedWhois && formattedWhois.length > 0 && formattedWhois.join(' | ');
+ const whois = Object.keys(whois_info).length > 0 ? whois_info : '';
return { name, whois };
};
@@ -308,3 +292,29 @@ export const normalizeRulesTextarea = text => text && text.replace(/^\n/g, '').r
export const isVersionGreater = (currentVersion, previousVersion) => (
versionCompare(currentVersion, previousVersion) === -1
);
+
+export const normalizeWhois = (whois) => {
+ if (Object.keys(whois).length > 0) {
+ const {
+ city, country, ...values
+ } = whois;
+ let location = (country && country) || '';
+
+ if (city && location) {
+ location = `${location}, ${city}`;
+ } else if (city) {
+ location = city;
+ }
+
+ if (location) {
+ return {
+ location,
+ ...values,
+ };
+ }
+
+ return { ...values };
+ }
+
+ return whois;
+};
diff --git a/home/clients.go b/home/clients.go
index 7fcfeed3..ad246171 100644
--- a/home/clients.go
+++ b/home/clients.go
@@ -206,6 +206,12 @@ func (clients *clientsContainer) Add(c Client) (bool, error) {
}
}
+ ch, ok := clients.ipHost[c.IP]
+ if ok {
+ c.WhoisInfo = ch.WhoisInfo
+ delete(clients.ipHost, c.IP)
+ }
+
clients.list[c.Name] = &c
if len(c.IP) != 0 {
clients.ipIndex[c.IP] = &c
@@ -287,12 +293,14 @@ func (clients *clientsContainer) SetWhoisInfo(ip string, info [][]string) {
if ok {
c.WhoisInfo = info
log.Debug("Clients: set WHOIS info for client %s: %v", c.Name, c.WhoisInfo)
+ return
}
ch, ok := clients.ipHost[ip]
if ok {
ch.WhoisInfo = info
log.Debug("Clients: set WHOIS info for auto-client %s: %v", ch.Host, ch.WhoisInfo)
+ return
}
ch = ClientHost{
@@ -310,6 +318,12 @@ func (clients *clientsContainer) AddHost(ip, host string, source clientSource) (
clients.lock.Lock()
defer clients.lock.Unlock()
+ // check index
+ _, ok := clients.ipIndex[ip]
+ if ok {
+ return false, nil
+ }
+
// check index
c, ok := clients.ipHost[ip]
if ok && c.Source > source {
diff --git a/home/whois.go b/home/whois.go
index f5dd2ab2..ccd5e51e 100644
--- a/home/whois.go
+++ b/home/whois.go
@@ -8,6 +8,8 @@ import (
whois "github.com/likexian/whois-go"
)
+const maxValueLength = 250
+
// Whois - module context
type Whois struct {
clients *clientsContainer
@@ -26,9 +28,19 @@ func initWhois(clients *clientsContainer) *Whois {
return &w
}
+// If the value is too large - cut it and append "..."
+func trimValue(s string) string {
+ if len(s) <= maxValueLength {
+ return s
+ }
+ return s[:maxValueLength-3] + "..."
+}
+
// Parse plain-text data from the response
func whoisParse(data string) map[string]string {
m := map[string]string{}
+ descr := ""
+ netname := ""
lines := strings.Split(data, "\n")
for _, ln := range lines {
ln = strings.TrimSpace(ln)
@@ -45,14 +57,31 @@ func whoisParse(data string) map[string]string {
k = strings.ToLower(k)
v := strings.TrimSpace(kv[1])
- if k == "orgname" || k == "org-name" {
- m["orgname"] = v
- } else if k == "city" {
- m["city"] = v
- } else if k == "country" {
- m["country"] = v
+ switch k {
+ case "org-name":
+ m["orgname"] = trimValue(v)
+ case "orgname":
+ fallthrough
+ case "city":
+ fallthrough
+ case "country":
+ m[k] = trimValue(v)
+
+ case "descr":
+ descr = v
+ case "netname":
+ netname = v
}
}
+
+ // descr or netname -> orgname
+ _, ok := m["orgname"]
+ if !ok && len(descr) != 0 {
+ m["orgname"] = trimValue(descr)
+ } else if !ok && len(netname) != 0 {
+ m["orgname"] = trimValue(netname)
+ }
+
return m
}