diff --git a/search/forms.py b/search/forms.py index fa43be55..c01629f5 100644 --- a/search/forms.py +++ b/search/forms.py @@ -22,19 +22,76 @@ from __future__ import unicode_literals -from django.db.models import Q -from simple_search import BaseSearchForm +from django.db import models +from django import forms +from django.forms import Form +from django.forms import ModelForm -from users.models import User, School +CHOICES_USER = ( + ('0', 'Actifs'), + ('1', 'Désactivés'), + ('2', 'Archivés'), +) -class UserSearchForm(BaseSearchForm): - class Meta: - base_qs = User.objects - search_fields = ('^name', 'description', 'specifications', '=id') +CHOICES_AFF = ( + ('0', 'Utilisateurs'), + ('1', 'Machines'), + ('2', 'Factures'), + ('3', 'Bannissements'), + ('4', 'Accès à titre gracieux'), + ('6', 'Switchs'), + ('5', 'Ports'), +) - # assumes a fulltext index has been defined on the fields - # 'name,description,specifications,id' - fulltext_indexes = ( - ('name', 2), # name matches are weighted higher - ('name,description,specifications,id', 1), - ) +def initial_choices(c): + return [i[0] for i in c] + + +class SearchForm(Form): + q = forms.CharField(label = 'Search', max_length = 100) + + def clean(self): + cleaned_data = super(SearchForm, self).clean() + q = cleaned_data.get('q', '') + + +class SearchFormPlus(Form): + q = forms.CharField( + label = 'Search', + max_length = 100, + required=False + ) + u = forms.MultipleChoiceField( + label="Filtre utilisateurs", + required=False, + widget=forms.CheckboxSelectMultiple, + choices=CHOICES_USER, + initial=initial_choices(CHOICES_USER) + ) + a = forms.MultipleChoiceField( + label="Filtre affichage", + required=False, + widget=forms.CheckboxSelectMultiple, + choices=CHOICES_AFF, + initial=initial_choices(CHOICES_AFF) + ) + s = forms.DateField( + required=False, + label="Date de début", + help_text='DD/MM/YYYY', + input_formats=['%d/%m/%Y'] + ) + e = forms.DateField( + required=False, + help_text='DD/MM/YYYY', + input_formats=['%d/%m/%Y'], + label="Date de fin" + ) + + def clean(self): + cleaned_data = super(SearchFormPlus, self).clean() + q = cleaned_data.get('q') + u = cleaned_data.get('u') + a = cleaned_data.get('a') + s = cleaned_data.get('s') + e = cleaned_data.get('e') diff --git a/search/models.py b/search/models.py deleted file mode 100644 index f0900728..00000000 --- a/search/models.py +++ /dev/null @@ -1,62 +0,0 @@ -# -*- mode: python; coding: utf-8 -*- -# Re2o est un logiciel d'administration développé initiallement au rezometz. Il -# se veut agnostique au réseau considéré, de manière à être installable en -# quelques clics. -# -# Copyright © 2017 Gabriel Détraz -# Copyright © 2017 Goulven Kermarec -# Copyright © 2017 Augustin Lemesle -# -# This program 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 2 of the License, or -# (at your option) any later version. -# -# This program 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 this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -from __future__ import unicode_literals - -from django.db import models -from django import forms -from django.forms import Form -from django.forms import ModelForm - -CHOICES_USER = ( - ('0', 'Actifs'), - ('1', 'Désactivés'), - ('2', 'Archivés'), -) - -CHOICES_CO = ( - (1, 'Active'), - ("", 'Désactivée'), -) - -CHOICES_AFF = ( - ('0', 'Utilisateurs'), - ('1', 'Machines'), - ('2', 'Factures'), - ('3', 'Bannissements'), - ('4', 'Accès à titre gracieux'), - ('6', 'Switchs'), - ('5', 'Ports'), -) - - -class SearchForm(Form): - query = forms.CharField(label = 'Search', max_length = 100) - -class SearchFormPlus(Form): - query = forms.CharField(label = 'Search', max_length = 100, required=False) - user_state = forms.MultipleChoiceField(label="Filtre utilisateurs", required=False, widget =forms.CheckboxSelectMultiple,choices=CHOICES_USER) - co_state = forms.MultipleChoiceField(label="Filtre connexion", required=False, widget =forms.CheckboxSelectMultiple,choices=CHOICES_CO) - aff = forms.MultipleChoiceField(label="Filtre affichage", required=False, widget =forms.CheckboxSelectMultiple,choices=CHOICES_AFF) - start = forms.DateField(required=False, label="Date de début", help_text='DD/MM/YYYY', input_formats=['%d/%m/%Y']) - end = forms.DateField(required=False, help_text='DD/MM/YYYY', input_formats=['%d/%m/%Y'], label="Date de fin") diff --git a/search/views.py b/search/views.py index 34421ac1..c1e06b98 100644 --- a/search/views.py +++ b/search/views.py @@ -37,93 +37,191 @@ from users.models import User, Ban, Whitelist from machines.models import Machine, Interface from topologie.models import Port, Switch from cotisations.models import Facture -from search.models import SearchForm, SearchFormPlus from preferences.models import GeneralOption +from search.forms import ( + SearchForm, + SearchFormPlus, + CHOICES_USER, + CHOICES_AFF, + initial_choices +) -def search_result(search_form, type, request): - start = None - end = None - user_state = [] - co_state = [] - aff = [] - if(type): - aff = search_form.cleaned_data['aff'] - co_state = search_form.cleaned_data['co_state'] - user_state = search_form.cleaned_data['user_state'] - start = search_form.cleaned_data['start'] - end = search_form.cleaned_data['end'] - date_query = Q() - if aff==[]: - aff = ['0','1','2','3','4','5','6'] - if start != None: - date_query = date_query & Q(date__gte=start) - if end != None: - date_query = date_query & Q(date__lte=end) - search = search_form.cleaned_data['query'] - query1 = Q() +def get_results(query, request, filters={}): + start = filters.get('s', None) + end = filters.get('e', None) + user_state = filters.get('u', initial_choices(CHOICES_USER)) + aff = filters.get('a', initial_choices(CHOICES_AFF)) + + options, created = GeneralOption.objects.get_or_create() + max_result = options.search_display_page + + user_state_filter = Q() for s in user_state: - query1 = query1 | Q(state = s) + user_state_filter |= Q(state = s) connexion = [] - recherche = {'users_list': None, 'machines_list' : [], 'facture_list' : None, 'ban_list' : None, 'white_list': None, 'port_list': None, 'switch_list': None} + results = { + 'users_list': User.objects.none(), + 'machines_list' : Machine.objects.none(), + 'facture_list' : Facture.objects.none(), + 'ban_list' : Ban.objects.none(), + 'white_list': Whitelist.objects.none(), + 'port_list': Port.objects.none(), + 'switch_list': Switch.objects.none() + } - if request.user.has_perms(('cableur',)): - query = Q(user__pseudo__icontains = search) | Q(user__adherent__name__icontains = search) | Q(user__surname__icontains = search) - else: - query = (Q(user__pseudo__icontains = search) | Q(user__adherent__name__icontains = search) | Q(user__surname__icontains = search)) & Q(user = request.user) + users_filter = Q( + user__pseudo__icontains = query + ) | Q( + user__adherent__name__icontains = query + ) | Q( + user__surname__icontains = query + ) + if not request.user.has_perms(('cableur',)): + users_filter &= Q(user = request.user) + # Users + if '0' in aff: + filter_user_list = Q( + adherent__room__name__icontains = query + ) | Q( + club__room__name__icontains = query + ) | Q( + pseudo__icontains = query + ) | Q( + adherent__name__icontains = query + ) | Q( + surname__icontains = query + ) & user_state_filter + if not request.user.has_perms(('cableur',)): + filter_user_list &= Q(id=request.user.id) + results['users_list'] = User.objects.filter( + filter_user_list + ).order_by('state', 'surname').distinct()[:max_result] - for i in aff: - if i == '0': - query_user_list = Q(adherent__room__name__icontains = search) | Q(club__room__name__icontains = search) | Q(pseudo__icontains = search) | Q(adherent__name__icontains = search) | Q(surname__icontains = search) & query1 - if request.user.has_perms(('cableur',)): - recherche['users_list'] = User.objects.filter(query_user_list).order_by('state', 'surname').distinct() - else : - recherche['users_list'] = User.objects.filter(query_user_list & Q(id=request.user.id)).order_by('state', 'surname').distinct() - if i == '1': - query_machine_list = Q(machine__user__pseudo__icontains = search) | Q(machine__user__adherent__name__icontains = search) | Q(machine__user__surname__icontains = search) | Q(mac_address__icontains = search) | Q(ipv4__ipv4__icontains = search) | Q(domain__name__icontains = search) | Q(domain__related_domain__name__icontains = search) - if request.user.has_perms(('cableur',)): - data = Interface.objects.filter(query_machine_list).distinct() - else: - data = Interface.objects.filter(query_machine_list & Q(machine__user__id = request.user.id)).distinct() - for d in data: - recherche['machines_list'].append(d.machine) - if i == '2': - recherche['facture_list'] = Facture.objects.filter(query & date_query).distinct() - if i == '3': - recherche['ban_list'] = Ban.objects.filter(query).distinct() - if i == '4': - recherche['white_list'] = Whitelist.objects.filter(query).distinct() - if i == '5': - recherche['port_list'] = Port.objects.filter(details__icontains = search).distinct() - if not request.user.has_perms(('cableur',)): - recherche['port_list'] = None - if i == '6': - recherche['switch_list'] = Switch.objects.filter(details__icontains = search).distinct() - if not request.user.has_perms(('cableur',)): - recherche['switch_list'] = None - options, created = GeneralOption.objects.get_or_create() - search_display_page = options.search_display_page + # Machines + if '1' in aff: + filter_machine_list = Q( + user__pseudo__icontains = query + ) | Q( + user__adherent__name__icontains = query + ) | Q( + user__surname__icontains = query + ) | Q( + interface__mac_address__icontains = query + ) | Q( + interface__ipv4__ipv4__icontains = query + ) | Q( + interface__domain__name__icontains = query + ) | Q( + interface__domain__related_domain__name__icontains = query + ) + if not request.user.has_perms(('cableur',)): + filter_machine_list &= Q(machine__user__id=request.user.id) + results['machines_list'] = Machine.objects.filter( + filter_machine_list + ).order_by('name').distinct()[:max_result] - for r in recherche: - if recherche[r] != None: - recherche[r] = recherche[r][:search_display_page] + # Factures + if '2' in aff: + date_filter = Q() + if start != None: + date_filter &= Q(date__gte=start) + if end != None: + date_filter &= Q(date__lte=end) + results['facture_list'] = Facture.objects.filter( + users_filter & date_filter + ).order_by('date').distinct()[:max_result] - recherche.update({'max_result': search_display_page}) + # Bans + if '3' in aff: + date_filter = Q() + if start != None: + date_filter &= ( + Q(date_start__gte=start) & Q(date_end__gte=start) + ) | ( + Q(date_start__lte=start) & Q(date_end__gte=start) + ) | ( + Q(date_start__gte=start) & Q(date_end__lte=start) + ) + if end != None: + date_filter &= ( + Q(date_start__lte=end) & Q(date_end__lte=end) + ) | ( + Q(date_start__lte=end) & Q(date_end__gte=end) + ) | ( + Q(date_start__gte=end) & Q(date_end__lte=end) + ) + results['ban_list'] = Ban.objects.filter( + users_filter & date_filter + ).order_by('date_end').distinct()[:max_result] - return recherche + # Whitelists + if '4' in aff: + date_filter = Q() + if start != None: + date_filter &= ( + Q(date_start__gte=start) & Q(date_end__gte=start) + ) | ( + Q(date_start__lte=start) & Q(date_end__gte=start) + ) | ( + Q(date_start__gte=start) & Q(date_end__lte=start) + ) + if end != None: + date_filter &= ( + Q(date_start__lte=end) & Q(date_end__lte=end) + ) | ( + Q(date_start__lte=end) & Q(date_end__gte=end) + ) | ( + Q(date_start__gte=end) & Q(date_end__lte=end) + ) + results['white_list'] = Whitelist.objects.filter( + users_filter & date_filter + ).order_by('date_end').distinct()[:max_result] + + # Switch ports + if '5' in aff and request.user.has_perms(('cableur',)): + results['port_list'] = Port.objects.filter( + details__icontains=query + ).order_by('switch', 'port').distinct()[:max_result] + + # Switches + if '6' in aff and request.user.has_perms(('cableur')): + results['switch_list'] = Switch.objects.filter( + details__icontains=query + ).order_by('stack', 'stack_member_id').distinct()[:max_result] + + results.update({'max_result': max_result}) + + return results @login_required def search(request): search_form = SearchForm(request.GET or None) if search_form.is_valid(): - return render(request, 'search/index.html', search_result(search_form, False, request)) + return render( + request, + 'search/index.html', + get_results( + search_form.cleaned_data.get('q', ''), + request, + search_form.cleaned_data + ) + ) return render(request, 'search/search.html', {'search_form' : search_form}) @login_required def searchp(request): search_form = SearchFormPlus(request.GET or None) if search_form.is_valid(): - return render(request, 'search/index.html', search_result(search_form, True, request)) + return render( + request, + 'search/index.html', + get_results( + search_form.cleaned_data.get('q', ''), + request, + search_form.cleaned_data + ) + ) return render(request, 'search/search.html', {'search_form' : search_form})