diff --git a/plugins/display/filter_users.py b/plugins/display/filter_users.py index 8151106..ddc3a2a 100644 --- a/plugins/display/filter_users.py +++ b/plugins/display/filter_users.py @@ -33,20 +33,8 @@ Plugin requirements : None Conf values needed : - filtered_users : list of filters - filtered_ip : list of ip (string) create_filtered_page* -Filter is a list of filter description combined by AND operator -Filter description is a list of 3 elements : - - * Field to match in visits - * Operator '=', '==', '!=', '>', '>=', '<', '<=' for int value - * Operator '=', '==', '!=', 'in', 'match' for str value - * Target value - -For easiest config, you can indicate both 'remote_addr' or 'ip' in field element - Output files : OUTPUT_ROOT/year/month/index.html OUTPUT_ROOT/year/month/filtered_users.html @@ -65,82 +53,20 @@ class IWLADisplayFilterUsers(IPlugin): def __init__(self, iwla): super(IWLADisplayFilterUsers, self).__init__(iwla) self.API_VERSION = 1 - - def _check_filter(self, _filter): - if len(_filter) != 3: - raise Exception('Bad filter ' + ' '.join(_filter)) - (field, operator, value) = _filter - try: - if type(value) == str: - value = int(value, 10) - _filter[2] = value - if operator not in ('=', '==', '!=', '>', '>=', '<', '<='): - raise Exception('Bad filter ' + ' '.join(_filter)) - except Exception as e: - if field == 'ip': - _filter[0] = 'remote_addr' - if operator not in ('=', '==', '!=', 'in', 'match'): - raise Exception('Bad filter ' + ' '.join(_filter)) - if operator == 'match': - _filter[2] = re.compile(value) def load(self): self.create_filtered_page = self.iwla.getConfValue('create_filtered_page', True) - self.filters = self.iwla.getConfValue('filtered_users', []) - self.ip_filters = self.iwla.getConfValue('filtered_ip', []) - for _filter in self.filters: - for sub_filter in _filter: - self._check_filter(sub_filter) return True - def __do_filter(self, hit, _filter): - (field, operator, value) = _filter - if not field in hit.keys(): return False - hit_value = hit[field] - # In dict, we have something like : {dayX : value} were day0 is total - if type(value) == int and type(hit_value) == dict: - hit_value = list(hit_value.values())[0] - if operator == '=' or operator == '==': - return hit_value == value - elif operator == 'in': - return hit_value in value - elif operator == 'match': - return re.match(value, hit_value) - elif operator == '!=': - return hit_value != value - elif operator == '<': - return hit_value < value - elif operator == '<=': - return hit_value <= value - elif operator == '>': - return hit_value > value - elif operator == '>=': - return hit_value >= value - - def _do_filter(self, ip, hits): - if ip in self.ip_filters: - return True - - for _filter in self.filters: - filtered = True - for sub_filter in _filter: - if not self.__do_filter(hits[ip], sub_filter): - filtered = False - break - if filtered: - return True - return False - def hook(self): display = self.iwla.getDisplay() hits = self.iwla.getValidVisitors() stats = {} self.filtered_users = [] - if len(self.filters) or len(self.ip_filters): - for (key,value) in hits.items(): - if self._do_filter(key, hits): - self.filtered_users.append(hits[key]) + for (key,value) in hits.items(): + if value.get('filtered', False): + self.filtered_users.append(value) # All in a page if self.create_filtered_page: diff --git a/plugins/post_analysis/filter_users.py b/plugins/post_analysis/filter_users.py new file mode 100644 index 0000000..048db1e --- /dev/null +++ b/plugins/post_analysis/filter_users.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- +# +# Copyright Grégory Soutadé 2020 + +# This file is part of iwla + +# iwla is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# iwla is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with iwla. If not, see . +# + +import re + +from iwla import IWLA +from iplugin import IPlugin +from display import * + +""" +Post analysis hook + +Filter users with given user conditions + +Plugin requirements : + None + +Conf values needed : + filtered_users : list of filters + filtered_ip : list of ip (string) + create_filtered_page* + +Filter is a list of filter description combined by AND operator +Filter description is a list of 3 elements : + + * Field to match in visits + * Operator '=', '==', '!=', '>', '>=', '<', '<=' for int value + * Operator '=', '==', '!=', 'in', 'match' for str value + * Target value + +For easiest config, you can indicate both 'remote_addr' or 'ip' in field element + +Output files : + None + +Statistics creation : +visits : + remote_addr => + filtered + +Statistics update : +visits : + remote_addr => + keep_requests + +Statistics deletion : + None +""" + +class IWLAPostAnalysisFilterUsers(IPlugin): + def __init__(self, iwla): + super(IWLAPostAnalysisFilterUsers, self).__init__(iwla) + self.API_VERSION = 1 + + def _check_filter(self, _filter): + if len(_filter) != 3: + raise Exception('Bad filter ' + ' '.join(_filter)) + (field, operator, value) = _filter + try: + if type(value) == str: + value = int(value, 10) + _filter[2] = value + if operator not in ('=', '==', '!=', '>', '>=', '<', '<='): + raise Exception('Bad filter ' + ' '.join(_filter)) + except Exception as e: + if field == 'ip': + _filter[0] = 'remote_addr' + if operator not in ('=', '==', '!=', 'in', 'match'): + raise Exception('Bad filter ' + ' '.join(_filter)) + if operator == 'match': + _filter[2] = re.compile(value) + + def load(self): + self.filters = self.iwla.getConfValue('filtered_users', []) + self.ip_filters = self.iwla.getConfValue('filtered_ip', []) + for _filter in self.filters: + for sub_filter in _filter: + self._check_filter(sub_filter) + return True + + def __do_filter(self, hit, _filter): + (field, operator, value) = _filter + if not field in hit.keys(): return False + hit_value = hit[field] + # In dict, we have something like : {dayX : value} were day0 is total + if type(value) == int and type(hit_value) == dict: + hit_value = list(hit_value.values())[0] + if operator == '=' or operator == '==': + return hit_value == value + elif operator == 'in': + return hit_value in value + elif operator == 'match': + return re.match(value, hit_value) + elif operator == '!=': + return hit_value != value + elif operator == '<': + return hit_value < value + elif operator == '<=': + return hit_value <= value + elif operator == '>': + return hit_value > value + elif operator == '>=': + return hit_value >= value + + def _do_filter(self, ip, hits): + if ip in self.ip_filters: + return True + + for _filter in self.filters: + filtered = True + for sub_filter in _filter: + if not self.__do_filter(hits[ip], sub_filter): + filtered = False + break + if filtered: + return True + return False + + def hook(self): + hits = self.iwla.getValidVisitors() + + if len(self.filters) or len(self.ip_filters): + for (key,value) in hits.items(): + if self._do_filter(key, hits): + print('Keep for {}'.format(key)) + value['filtered'] = True + value['keep_requests'] = True +