The end of Clipper
GestioCOF fetches the clipper accounts from an LDAP database and doesn't need to store clippers in a table anymore.
This commit is contained in:
parent
6e5c3c8c33
commit
3c7558c853
13 changed files with 133 additions and 114 deletions
|
@ -9,10 +9,6 @@ For the full list of settings and their values, see
|
|||
https://docs.djangoproject.com/en/1.8/ref/settings/
|
||||
"""
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
import os
|
||||
|
||||
|
@ -165,6 +161,8 @@ AUTHENTICATION_BACKENDS = (
|
|||
'gestioncof.shared.COFCASBackend',
|
||||
)
|
||||
|
||||
# LDAP_SERVER_URL = 'ldaps://ldap.spi.ens.fr:636'
|
||||
|
||||
# EMAIL_HOST="nef.ens.fr"
|
||||
|
||||
RECAPTCHA_PUBLIC_KEY = "DUMMY"
|
||||
|
|
|
@ -4,10 +4,6 @@
|
|||
Fichier principal de configuration des urls du projet GestioCOF
|
||||
"""
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import autocomplete_light
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -61,7 +57,8 @@ urlpatterns = [
|
|||
name='password_change_done'),
|
||||
# Inscription d'un nouveau membre
|
||||
url(r'^registration$', gestioncof_views.registration),
|
||||
url(r'^registration/clipper/(?P<login_clipper>[\w-]+)$',
|
||||
url(r'^registration/clipper/(?P<login_clipper>[\w-]+)/'
|
||||
r'(?P<fullname>.*)$',
|
||||
gestioncof_views.registration_form2, name="clipper-registration"),
|
||||
url(r'^registration/user/(?P<username>.+)$',
|
||||
gestioncof_views.registration_form2, name="user-registration"),
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
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
|
||||
from gestioncof.models import CofProfile, Clipper
|
||||
from django.conf import settings
|
||||
|
||||
from gestioncof.models import CofProfile
|
||||
from gestioncof.decorators import buro_required
|
||||
|
||||
|
||||
|
@ -25,37 +24,49 @@ def autocomplete(request):
|
|||
queries = {}
|
||||
bits = q.split()
|
||||
|
||||
# Fetching data from User and CofProfile tables
|
||||
queries['members'] = CofProfile.objects.filter(Q(is_cof=True))
|
||||
queries['users'] = User.objects.filter(Q(profile__is_cof=False))
|
||||
queries['clippers'] = Clipper.objects
|
||||
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))
|
||||
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['clippers'] = queries['clippers'].filter(
|
||||
Q(fullname__icontains=bit)
|
||||
| Q(username__icontains=bit))
|
||||
Q(first_name__icontains=bit)
|
||||
| Q(last_name__icontains=bit)
|
||||
| Q(username__icontains=bit))
|
||||
queries['members'] = queries['members'].distinct()
|
||||
queries['users'] = queries['users'].distinct()
|
||||
usernames = list(queries['members'].values_list('login_clipper',
|
||||
flat='True')) \
|
||||
|
||||
# Clearing redundancies
|
||||
usernames = (
|
||||
list(queries['members'].values_list('login_clipper', flat='True'))
|
||||
+ list(queries['users'].values_list('profile__login_clipper',
|
||||
flat='True'))
|
||||
queries['clippers'] = queries['clippers'] \
|
||||
.exclude(username__in=usernames).distinct()
|
||||
# add clippers
|
||||
)
|
||||
|
||||
# Fetching data from the SPI
|
||||
if hasattr(settings, 'LDAP_SERVER_URL'):
|
||||
# Fetching
|
||||
ldap_query = '(|{:s})'.format(''.join(
|
||||
['(cn=*{:s}*)'.format(bit) for bit in bits]
|
||||
))
|
||||
with Connection(settings.LDAP_SERVER_URL) as conn:
|
||||
queries['clippers'] = conn.search(
|
||||
'dc=spi,dc=ens,dc=fr', query,
|
||||
attributes=['uid', 'cn']
|
||||
)
|
||||
# Clearing redundancies
|
||||
queries['clippers'] = [
|
||||
{'clipper': clipper.uid, 'fullname': clipper.cn}
|
||||
for clipper in queries['clippers']
|
||||
if clipper.uid not in usernames
|
||||
]
|
||||
|
||||
# Resulting data
|
||||
data.update(queries)
|
||||
|
||||
options = 0
|
||||
for query in queries.values():
|
||||
options += len(query)
|
||||
data['options'] = options
|
||||
data['options'] = sum([len(query) for query in queries])
|
||||
|
||||
return shortcuts.render(request, "autocomplete_user.html", data)
|
||||
|
|
17
gestioncof/migrations/0009_delete_clipper.py
Normal file
17
gestioncof/migrations/0009_delete_clipper.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('gestioncof', '0008_py3'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='Clipper',
|
||||
),
|
||||
]
|
|
@ -1,9 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
@ -258,15 +254,6 @@ class SurveyAnswer(models.Model):
|
|||
self.survey.title)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class Clipper(models.Model):
|
||||
username = models.CharField("Identifiant", max_length=20)
|
||||
fullname = models.CharField("Nom complet", max_length=200)
|
||||
|
||||
def __str__(self):
|
||||
return "Clipper %s" % self.username
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class CalendarSubscription(models.Model):
|
||||
token = models.UUIDField()
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
{% if clippers %}
|
||||
<li class="autocomplete-header">Utilisateurs <tt>clipper</tt></li>
|
||||
{% for clipper in clippers %}{% if forloop.counter < 5 %}
|
||||
<li class="autocomplete-value"><a href="{% url 'clipper-registration' clipper.username %}">{{ clipper|highlight_clipper:q }}</a></li>
|
||||
<li class="autocomplete-value"><a href="{% url 'clipper-registration' clipper.clipper clipper.fullname %}">{{ clipper|highlight_clipper:q }}</a></li>
|
||||
{% elif forloop.counter == 5 %}<li class="autocomplete-more">...</a>{% endif %}{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ def highlight_user(user, q):
|
|||
@register.filter
|
||||
def highlight_clipper(clipper, q):
|
||||
if clipper.fullname:
|
||||
text = "%s (<tt>%s</tt>)" % (clipper.fullname, clipper.username)
|
||||
text = "%s (<tt>%s</tt>)" % (clipper.fullname, clipper.clipper)
|
||||
else:
|
||||
text = clipper.username
|
||||
text = clipper.clipper
|
||||
return highlight_text(text, q)
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import unicodecsv
|
||||
import uuid
|
||||
from datetime import timedelta
|
||||
|
@ -25,7 +21,7 @@ from gestioncof.models import Event, EventRegistration, EventOption, \
|
|||
from gestioncof.models import EventCommentField, EventCommentValue, \
|
||||
CalendarSubscription
|
||||
from gestioncof.shared import send_custom_mail
|
||||
from gestioncof.models import CofProfile, Clipper, Club
|
||||
from gestioncof.models import CofProfile, Club
|
||||
from gestioncof.decorators import buro_required, cof_required
|
||||
from gestioncof.forms import UserProfileForm, EventStatusFilterForm, \
|
||||
SurveyForm, SurveyStatusFilterForm, RegistrationUserForm, \
|
||||
|
@ -321,11 +317,10 @@ def registration_set_ro_fields(user_form, profile_form):
|
|||
|
||||
|
||||
@buro_required
|
||||
def registration_form2(request, login_clipper=None, username=None):
|
||||
def registration_form2(request, login_clipper=None, username=None, fullname=None):
|
||||
events = Event.objects.filter(old=False).all()
|
||||
member = None
|
||||
if login_clipper:
|
||||
clipper = get_object_or_404(Clipper, username=login_clipper)
|
||||
try: # check if the given user is already registered
|
||||
member = User.objects.get(username=login_clipper)
|
||||
username = member.username
|
||||
|
@ -336,8 +331,8 @@ def registration_form2(request, login_clipper=None, username=None):
|
|||
user_form = RegistrationUserForm(initial={
|
||||
'username': login_clipper,
|
||||
'email': "%s@clipper.ens.fr" % login_clipper})
|
||||
if clipper.fullname:
|
||||
bits = clipper.fullname.split(" ")
|
||||
if fullname:
|
||||
bits = fullname.split(" ")
|
||||
user_form.fields['first_name'].initial = bits[0]
|
||||
if len(bits) > 1:
|
||||
user_form.fields['last_name'].initial = " ".join(bits[1:])
|
||||
|
@ -412,12 +407,12 @@ def registration(request):
|
|||
try:
|
||||
member = User.objects.get(username=username)
|
||||
user_form = RegistrationUserForm(request_dict, instance=member)
|
||||
except User.DoesNotExist:
|
||||
try:
|
||||
clipper = Clipper.objects.get(username=username)
|
||||
login_clipper = clipper.username
|
||||
except Clipper.DoesNotExist:
|
||||
if member.profile.login_clipper:
|
||||
login_clipper = member.profile.login_clipper
|
||||
else:
|
||||
user_form.force_long_username()
|
||||
except User.DoesNotExist:
|
||||
user_form.force_long_username()
|
||||
else:
|
||||
user_form.force_long_username()
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import (absolute_import, division,
|
||||
print_function, unicode_literals)
|
||||
from builtins import *
|
||||
import ldap3
|
||||
|
||||
from django.shortcuts import render
|
||||
from django.http import Http404
|
||||
from django.db.models import Q
|
||||
from gestioncof.models import User, Clipper
|
||||
from django.conf import settings
|
||||
|
||||
from gestioncof.models import User
|
||||
from kfet.decorators import teamkfet_required
|
||||
from kfet.models import Account
|
||||
|
||||
|
@ -25,58 +25,66 @@ def account_create(request):
|
|||
queries = {}
|
||||
search_words = q.split()
|
||||
|
||||
# Fetching data from User, CofProfile and Account tables
|
||||
queries['kfet'] = Account.objects
|
||||
queries['users_cof'] = User.objects.filter(Q(profile__is_cof = True))
|
||||
queries['users_notcof'] = User.objects.filter(Q(profile__is_cof = False))
|
||||
queries['clippers'] = Clipper.objects
|
||||
|
||||
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)
|
||||
)
|
||||
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)
|
||||
)
|
||||
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)
|
||||
)
|
||||
queries['clippers'] = queries['clippers'].filter(
|
||||
Q(username__icontains = word)
|
||||
| Q(fullname__icontains = word)
|
||||
)
|
||||
Q(username__icontains = word)
|
||||
| Q(first_name__icontains = word)
|
||||
| Q(last_name__icontains = word)
|
||||
)
|
||||
|
||||
# Clearing redundancies
|
||||
queries['kfet'] = queries['kfet'].distinct()
|
||||
|
||||
usernames = list( \
|
||||
usernames = list(
|
||||
queries['kfet'].values_list('cofprofile__user__username', flat=True))
|
||||
queries['kfet'] = [
|
||||
(account, account.cofprofile.user)
|
||||
for account in queries['kfet']
|
||||
]
|
||||
|
||||
queries['kfet'] = [ (account, account.cofprofile.user) \
|
||||
for account in queries['kfet'] ]
|
||||
|
||||
queries['users_cof'] = \
|
||||
queries['users_cof'] = \
|
||||
queries['users_cof'].exclude(username__in=usernames).distinct()
|
||||
queries['users_notcof'] = \
|
||||
queries['users_notcof'] = \
|
||||
queries['users_notcof'].exclude(username__in=usernames).distinct()
|
||||
|
||||
usernames += list( \
|
||||
usernames += list(
|
||||
queries['users_cof'].values_list('username', flat=True))
|
||||
usernames += list( \
|
||||
usernames += list(
|
||||
queries['users_notcof'].values_list('username', flat=True))
|
||||
|
||||
queries['clippers'] = \
|
||||
queries['clippers'].exclude(username__in=usernames).distinct()
|
||||
# Fetching data from the SPI
|
||||
if hasattr(settings, 'LDAP_SERVER_URL'):
|
||||
# Fetching
|
||||
ldap_query = '(|{:s})'.format(''.join(
|
||||
['(cn=*{:s}*)'.format(bit) for bit in bits]
|
||||
))
|
||||
with Connection(settings.LDAP_SERVER_URL) as conn:
|
||||
queries['clippers'] = conn.search(
|
||||
'dc=spi,dc=ens,dc=fr', ldap_query,
|
||||
attributes=['uid', 'cn']
|
||||
)
|
||||
# Clearing redundancies
|
||||
queries['clippers'] = [
|
||||
{'clipper': clipper.uid, 'fullname': clipper.cn}
|
||||
for clipper in queries['clippers']
|
||||
if clipper.uid not in usernames
|
||||
]
|
||||
|
||||
# Resulting data
|
||||
data.update(queries)
|
||||
|
||||
options = 0
|
||||
for query in queries.values():
|
||||
options += len(query)
|
||||
data['options'] = options
|
||||
data['options'] = sum([len(query) for query in queries])
|
||||
|
||||
return render(request, "kfet/account_create_autocomplete.html", data)
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<li class="user_category"><span class="text">Utilisateurs clipper</span></li>
|
||||
{% for clipper in clippers %}
|
||||
<li>
|
||||
<a href="{% url "kfet.account.create.fromclipper" clipper.username %}">
|
||||
<a href="{% url "kfet.account.create.fromclipper" clipper.clipper clipper.fullname%}">
|
||||
{{ clipper|highlight_clipper:q }}
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -35,7 +35,8 @@ urlpatterns = [
|
|||
name = 'kfet.account.create_special'),
|
||||
url(r'^accounts/new/user/(?P<username>.+)$', views.account_create_ajax,
|
||||
name = 'kfet.account.create.fromuser'),
|
||||
url(r'^accounts/new/clipper/(?P<login_clipper>.+)$', views.account_create_ajax,
|
||||
url(r'^accounts/new/clipper/(?P<login_clipper>[\w-]+)/(?P<fullname>.*)$',
|
||||
views.account_create_ajax,
|
||||
name = 'kfet.account.create.fromclipper'),
|
||||
url(r'^accounts/new/empty$', views.account_create_ajax,
|
||||
name = 'kfet.account.create.empty'),
|
||||
|
|
|
@ -22,7 +22,7 @@ from django.db.models import F, Sum, Prefetch, Count, Func
|
|||
from django.db.models.functions import Coalesce
|
||||
from django.utils import timezone
|
||||
from django.utils.crypto import get_random_string
|
||||
from gestioncof.models import CofProfile, Clipper
|
||||
from gestioncof.models import CofProfile
|
||||
from kfet.decorators import teamkfet_required
|
||||
from kfet.models import (Account, Checkout, Article, Settings, AccountNegative,
|
||||
CheckoutStatement, GenericTeamToken, Supplier, SupplierArticle, Inventory,
|
||||
|
@ -216,19 +216,20 @@ def account_form_set_readonly_fields(user_form, cof_form):
|
|||
cof_form.fields['login_clipper'].widget.attrs['readonly'] = True
|
||||
cof_form.fields['is_cof'].widget.attrs['disabled'] = True
|
||||
|
||||
def get_account_create_forms(request=None, username=None, login_clipper=None):
|
||||
def get_account_create_forms(request=None, username=None, login_clipper=None,
|
||||
fullname=None):
|
||||
user = None
|
||||
clipper = None
|
||||
clipper = False
|
||||
if login_clipper and (login_clipper == username or not username):
|
||||
# à partir d'un clipper
|
||||
# le user associé à ce clipper ne devrait pas encore exister
|
||||
clipper = get_object_or_404(Clipper, username = login_clipper)
|
||||
clipper = True
|
||||
try:
|
||||
# Vérification que clipper ne soit pas déjà dans User
|
||||
user = User.objects.get(username=login_clipper)
|
||||
# Ici, on nous a menti, le user existe déjà
|
||||
username = user.username
|
||||
clipper = None
|
||||
clipper = False
|
||||
except User.DoesNotExist:
|
||||
# Clipper (sans user déjà existant)
|
||||
|
||||
|
@ -236,9 +237,9 @@ def get_account_create_forms(request=None, username=None, login_clipper=None):
|
|||
user_initial = {
|
||||
'username' : login_clipper,
|
||||
'email' : "%s@clipper.ens.fr" % login_clipper}
|
||||
if clipper.fullname:
|
||||
if fullname:
|
||||
# Prefill du nom et prénom
|
||||
names = clipper.fullname.split()
|
||||
names = fullname.split()
|
||||
# Le premier, c'est le prénom
|
||||
user_initial['first_name'] = names[0]
|
||||
if len(names) > 1:
|
||||
|
@ -302,8 +303,11 @@ def get_account_create_forms(request=None, username=None, login_clipper=None):
|
|||
|
||||
@login_required
|
||||
@teamkfet_required
|
||||
def account_create_ajax(request, username=None, login_clipper=None):
|
||||
forms = get_account_create_forms(request=None, username=username, login_clipper=login_clipper)
|
||||
def account_create_ajax(request, username=None, login_clipper=None,
|
||||
fullname=None):
|
||||
forms = get_account_create_forms(
|
||||
request=None, username=username, login_clipper=login_clipper,
|
||||
fullname=fullname)
|
||||
return render(request, "kfet/account_create_form.html", {
|
||||
'account_form' : forms['account_form'],
|
||||
'cof_form' : forms['cof_form'],
|
||||
|
|
|
@ -18,3 +18,4 @@ git+https://github.com/Aureplop/channels.git#egg=channel
|
|||
statistics==1.0.3.5
|
||||
future==0.15.2
|
||||
django-widget-tweaks==1.4.1
|
||||
ldap3
|
||||
|
|
Loading…
Reference in a new issue