from django import shortcuts from django.conf import settings from django.contrib.auth.models import User from django.db.models import Q from django.http import Http404 from ldap3 import Connection from gestioncof.decorators import buro_required from gestioncof.models import CofProfile 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 def __str__(self): return "{} ({})".format(self.clipper, self.fullname) def __eq__(self, other): return self.clipper == other.clipper and self.fullname == other.fullname @buro_required def autocomplete(request): if "q" not in request.GET: raise Http404 q = request.GET["q"] data = {"q": q} queries = {} bits = q.split() # Fetching data from User and CofProfile tables queries["members"] = CofProfile.objects.filter(is_cof=True) queries["users"] = User.objects.filter(profile__is_cof=False) for bit in bits: queries["members"] = queries["members"].filter( Q(user__first_name__icontains=bit) | Q(user__last_name__icontains=bit) | Q(user__username__icontains=bit) | Q(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("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"] = sum(len(query) for query in queries) return shortcuts.render(request, "autocomplete_user.html", data)