from ldap3 import Connection from django import shortcuts from django.http import Http404 from django.db.models import Q from django.contrib.auth.models import User, Group from .decorators import buro_required from django.conf import settings class Clipper(object): def __init__(self, clipper, fullname): if fullname is None: fullname = "" assert isinstance(clipper, str) assert isinstance(fullname, str) self.clipper = clipper self.fullname = fullname @buro_required def autocomplete(request): if "q" not in request.GET: raise Http404 q = request.GET['q'] data = {'q': q} cof_members = Group.objects.get(name="cof_members") queries = {} bits = q.split() # Fetching data from User and Profile tables queries['members'] = User.objects.filter(groups=cof_members) queries['users'] = User.objects.exclude(groups=cof_members) for bit in bits: queries['members'] = queries['members'].filter( Q(first_name__icontains=bit) | Q(last_name__icontains=bit) | Q(username__icontains=bit) | Q(profile__login_clipper__icontains=bit)) queries['users'] = queries['users'].filter( Q(first_name__icontains=bit) | Q(last_name__icontains=bit) | Q(username__icontains=bit)) queries['members'] = queries['members'].distinct() queries['users'] = queries['users'].distinct() # Clearing redundancies usernames = ( set(queries['members'].values_list('profile__login_clipper', flat='True')) | set(queries['users'].values_list('profile__login_clipper', flat='True')) ) # Fetching data from the SPI if getattr(settings, 'LDAP_SERVER_URL', None): # Fetching ldap_query = '(&{:s})'.format(''.join( '(|(cn=*{bit:s}*)(uid=*{bit:s}*))'.format(bit=bit) for bit in bits if bit.isalnum() )) if ldap_query != "(&)": # If none of the bits were legal, we do not perform the query entries = None with Connection(settings.LDAP_SERVER_URL) as conn: conn.search( 'dc=spi,dc=ens,dc=fr', ldap_query, attributes=['uid', 'cn'] ) entries = conn.entries # Clearing redundancies queries['clippers'] = [ Clipper(entry.uid.value, entry.cn.value) for entry in entries if entry.uid.value and entry.uid.value not in usernames ] # Resulting data data.update(queries) data['options'] = any(bool(query) for query in queries.values()) return shortcuts.render(request, "cof/autocomplete_user.html", data)