from django.conf import settings from django.db.models import Q from django.http import Http404 from django.shortcuts import render from gestioncof.models import User from kfet.decorators import teamkfet_required from kfet.models import Account if getattr(settings, "LDAP_SERVER_URL", None): from ldap3 import Connection else: # shared.tests.testcases.TestCaseMixin.mockLDAP needs # Connection to be defined in order to mock it. Connection = None 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 @teamkfet_required def account_create(request): if "q" not in request.GET: raise Http404 q = request.GET.get("q") if len(q) == 0: return render(request, "kfet/account_create_autocomplete.html") data = {"q": q} queries = {} search_words = q.split() # Fetching data from User, CofProfile and Account tables queries["kfet"] = Account.objects queries["users_cof"] = User.objects.filter(profile__is_cof=True) queries["users_notcof"] = User.objects.filter(profile__is_cof=False) for word in search_words: queries["kfet"] = queries["kfet"].filter( Q(cofprofile__user__username__icontains=word) | Q(cofprofile__user__first_name__icontains=word) | Q(cofprofile__user__last_name__icontains=word) ) queries["users_cof"] = queries["users_cof"].filter( Q(username__icontains=word) | Q(first_name__icontains=word) | Q(last_name__icontains=word) ) queries["users_notcof"] = queries["users_notcof"].filter( Q(username__icontains=word) | Q(first_name__icontains=word) | Q(last_name__icontains=word) ) # Clearing redundancies queries["kfet"] = queries["kfet"].distinct() usernames = set( queries["kfet"].values_list("cofprofile__user__username", flat=True) ) queries["kfet"] = [ (account, account.cofprofile.user) for account in queries["kfet"] ] queries["users_cof"] = ( queries["users_cof"].exclude(username__in=usernames).distinct() ) queries["users_notcof"] = ( queries["users_notcof"].exclude(username__in=usernames).distinct() ) usernames |= set(queries["users_cof"].values_list("username", flat=True)) usernames |= set(queries["users_notcof"].values_list("username", 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=word) for word in search_words if word.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 render(request, "kfet/account_create_autocomplete.html", data) @teamkfet_required def account_search(request): if "q" not in request.GET: raise Http404 q = request.GET.get("q") words = q.split() data = {"q": q} for word in words: query = Account.objects.filter( Q(cofprofile__user__username__icontains=word) | Q(cofprofile__user__first_name__icontains=word) | Q(cofprofile__user__last_name__icontains=word) ).distinct() query = [ (account.trigramme, account.cofprofile.user.get_full_name()) for account in query ] data["accounts"] = query return render(request, "kfet/account_search_autocomplete.html", data)