scripts/wiki/action/inscription.py
Antoine Durand-Gasselin 7e46d3e60c [wiki/inscription.py] bon choix d'etudes
darcs-hash:20090706170352-bd074-6b795b38663b331e6c41da9855fe34a304f9f4ca.gz
2009-07-06 19:03:52 +02:00

357 lines
14 KiB
Python

# -*- coding: iso-8859-1 -*-
u"""
_vi
<Ii _aa.
:I> aZ2^
v` .we^
. . .. + _2~
._auqXZZX ._auqXZZZ` ...._... ~ ._|ii~
.aXZZY""^~~ vX#Z?""~~~._=ii|+++++++ii=, _=|+~-
JXXX` )XXX' _|i+~ .__..._. +l= -~-
SXXo )XZX: |i> ._%i>~~+|ii| .i| ._s_ass,,. ._a%ssssssss
-SXZ6,,. )XZX: =l> _li+~` iii| .ii _uZZXX??YZ#Za, uXUX*?!!!!!!!
"!XZ#ZZZZZXZXZ` <i> =i: .|ii| .l|.dZXr 4XXo.XXXs,.
-~^^^^^^^` -||, +i|=. |ii| :i>:ZXZ( ]XZX.-"SXZUZUXoa,,
+l|, ~~|++|++i|||+~:ZXZ( ]ZZX ---~"?Z#m
.__;=- ~+l|=____.___, :ZXZ( ]ZXX_________auXX2
._||>+~- . -~+~++~~~- :ZXZ( ]ZXZZ#######UX*!"
-+-- .>` _
.<}` 3;
.<l> .Zc
.ii^ )Xo
]XX
MoinMoin - Formulaire d'inscription
Un formulaire de préinscription au Crans
Copyright 2009 Antoine Durand-Gasselin <adg@crans.org>
License: GPLv3
"""
import re, locale, base64, sys, unicodedata
from commands import getstatusoutput as gso
sys.path.append("/usr/scripts/gestion")
from iptools import AddrInNet
from MoinMoin import wikiutil
from MoinMoin.widget import html
from MoinMoin.Page import Page
from MoinMoin.PageEditor import PageEditor
from MoinMoin.formatter.text_html import Formatter
ETABLISSEMENTS = [ ("ENS", u"ENS Cachan"),
("IUT Cachan", u"IUT Cachan"),
("Maximilien Sorre", u"Maximilien Sorre"),
("Gustave Eiffel", u"Gustave Eiffel"),
("P1", u"Paris I"),
("P2", u"Paris II"),
("P3", u"Paris III"),
("P4", u"Paris IV"),
("P5", u"Paris V"),
("P6", u"Paris VI"),
("P7", u"Paris VII"),
("P8", u"Paris VIII"),
("P9", u"Paris IX"),
("P10", u"Paris X"),
("P11", u"Paris XI"),
("P12", u"Paris XII"),
("P13", u"Paris XIII"),
("IUFM", u"IUFM"),
("other", u"Autre...") ]
LABOS = [ ("CMLA", u"CMLA - Centre de Mathématiques et de Leurs Applications"),
("GAPP", u"GAPP - Groupe d'Analyse des Politiques Publiques"),
("IDHE", u"IDHE - Institutions et Dynamiques Historiques de l'Economie"),
("LBPA", u"LBPA - Laboratoire de Biotechnologies et Pharmacologie génétique Appliquées"),
("LMT", u"LMT - Laboratoire de Mécanique et Technologie"),
("LPQM", u"LPQM - Laboratoire de Photonique Quantique et Moléculaire"),
("LSV", u"LSV - Laboratoire de Spécification et Vérification"),
("LURPA", u"LURPA - Laboratoire Universitaire de Recherche en Production Automatisée"),
("PPSM", u"PPSM - Laboratoire de Photophysique et Photochimie Supramoléculaires et Macromoléculaires"),
("SATIE", u"SATIE - Systèmes et Applications des Technologies de l\'Information et de l'Energie"),
("STEF", u"STEF - Sciences Techniques Education Formation") ]
ANNEE_ENS = [ ("1", u"1A (license)"), ("2", u"2A (master 1)"),
("3", u"3A (agrégation)"), ("4", u"4A (master 2)"),
("5", u"5A (thèse 1)"), ("6", u"6A (thèse 2)"),
("7", u"7A (thèse 3)"), ("8", u"8A+") ]
ANNEE_ETUDE = [ ("-2", u"Seconde"), ("-1", u"Première"), ("0", u"Terminale"),
("1", u"BAC+1 (L1)"), ("2", u"BAC+2 (L2)"), ("3", u"BAC+3 (L3)"),
("4", u"BAC+4 (M1)"), ("5", u"BAC+5 (M2)"), ("6", u"BAC+6 (thèse 1)"),
("7", u"BAC+7 (thèse 2)"), ("8", u"BAC+8 (thèse 3)"), ("9", "Autre") ]
SECTIONS_ENS = [ ("A0", u"A0 - Informatique"),
("A1", u"A1 - Mathématiques"),
("A2", u"A2 - Physique fondamentale"),
("A'2", u"A'2 - Physique appliquée"),
("A''2", u"A''2 - Chimie"),
("A3", u"A3 - Biochimie"),
("EEA", u"EEA"),
("B123", u"B123 - Technologie mécanique"),
("B1", u"B1 - Mécanique"),
("B2", u"B2 - Génie civil"),
("B3", u"B3 - Génie mécanique"),
("B1", u"B1 - Mécanique"),
("B2", u"B2 - Génie civil"),
("B3", u"B3 - Génie mécanique"),
("B4", u"B4 - Génie électrique"),
("C", u"C - Art et création industrielle"),
("D2", u"D2 - Economie gestion"),
("D3", u"D3 - Sciences sociales"),
("E", u"E - Anglais") ]
class Field():
"""Une classe pour représenter les champs
Attention, elle ne permet que de rendre les champs en html, et
permet d'effectuer des tests unitaires"""
error_txt=''
error_msg=''
error_field=''
def __init__(self, id, prompt, default = "", input_type = "text",
check=None, CLASS="formulaire_field"):
self.id = id
self.prompt = html.Text(prompt)
self.default = default
self.input_type = input_type
self.CLASS= CLASS
if check != None: self.check_hook = check
else: self.check_hook = (lambda x: True)
def fill(self, post):
self.input = post.get(self.id, [''])[0]
def check(self):
self.error_txt= '' # Devrait pourtant être déjà vide
self.default = self.input
ok = self.check_hook(self)
if ok:
self.content = self.__dict__.get('content', self.input) # des fois qu'on ait oublié de le faire
if self.content != self.default and self.default == self.input:
self.default = self.content
if not self.error_txt and not ok:
self.error_txt = u'Valeur %s incorrecte pour le champ %s.' % (self.input, self.id)
return ok
def render(self, request, parser):
champ = html.UL(CLASS=self.CLASS)
champ.append(html.LI(CLASS="formulaire_id").append(self.prompt))
input = html.INPUT(type=self.input_type,name=self.id,value=self.default)
champ.append(html.LI(CLASS="formulaire_input").append(input))
if self.error_txt:
error = wikiutil.renderText(request, parser, self.error_txt)
champ.append(html.LI(CLASS="formulaire_error").append(error))
if self.error_msg:
request.add_msg(self.error_msg)
return champ
class MenuField(Field):
def __init__(self, id, prompt, fields):
Field.__init__(self, id, prompt)
self.fields = fields
def render(self, request, parser):
champ = html.UL(CLASS="formulaire_field_%s" % self.id)
champ.append(html.LI(CLASS="formulaire_id").append(self.prompt))
menu = html.SELECT(NAME=self.id, onchange='TestEtudes()')
for opt, legend in self.fields:
menu.append(html.OPTION(VALUE=opt).append(legend))
champ.append(menu)
if self.error_txt:
error = wikiutil.renderText(request, parser, self.error_txt)
champ.append(html.LI(CLASS="formulaire_error").append(error))
if self.error_msg:
request.add_msg(self.error_msg)
return champ
class PasswordField(Field):
def fill(self, post):
self.input = post.get(self.id, [''])[0]
self.input2 = post.get(self.id+'2',[''])[0]
def check(self):
self.error_txt= '' # Devrait pourtant être déjà vide
self.default = ''
if self.input == self.input2:
self.content = self.input
return True
else:
self.error_txt = u'Les deux mots de passe diffèrent'
return False
def render(self, request, parser):
champ = html.UL(CLASS="formulaire_field")
champ.append(html.LI(CLASS="formulaire_id").append(self.prompt))
input = html.INPUT(type=self.input_type,onchange="testPassword()", name=self.id)
champ.append(html.LI(CLASS="formulaire_input").append(input))
champ.append(html.LI().append('<img name="verdict" />'))
champ2 = html.UL(CLASS="formulaire_field")
champ2.append(html.LI(CLASS="formulaire_id").append('Retapez le mot de passe'))
input = html.INPUT(type=self.input_type, name=self.id+'2')
champ2.append(html.LI(CLASS="formulaire_input").append(input))
if self.error_txt:
error = wikiutil.renderText(request, parser, self.error_txt)
champ2.append(html.LI(CLASS="formulaire_error").append(error))
return u'%s\n%s\n' % (champ, champ2)
def is_name(self):
"""Vérifie que le champ input de l'objet passé en argument est un nom valide."""
analysed_content = unicodedata.normalize('NFKD', self.input)
try: stripped_content = analysed_content.encode('ASCII', 'ignore')
except UnicodeEncodeError: stripped_content = '<ugly utf-8>'
if re.match('[a-z][-a-z _]*', stripped_content.lower()):
return True
else:
self.error_txt = u"""Valeur %s incorrecte pour le champ %s.
Seules les lettres (éventuellement accentuées),
l'espace et le tiret '-' sont acceptés.""" % (self.input, self.id)
return False
def is_phonenumber(self):
chiffres = self.input.replace('.', '')
if re.match('(0|\+[0-9][0-9])[0-9]{9}', chiffres):
return True
else:
self.content = ''
return True
def is_dns(self):
dns = self.input.lower()
if re.match('[a-z][-a-z0-9_]*', dns):
return True
else:
return False
def get_mac(ip):
"Récupère la mac"
mac= 'XX' + ':XX'*5
if AddrInNet(ip, '138.231.136.0/21'):
status, mac = gso("/usr/sbin/arp %s | perl -nle '{print $& if /00(:[0-9a-f]{2}){5}/}'" % ip) # gruik, gruik, grUUIIIk !
mac= mac.strip()
return mac
def is_valid_mac(self):
mac = self.input.lower()
if re.search("00((:|-|)[a-f0-9][a-f0-9]){5}", mac):
return True
else:
self.default = get_mac(self.ip)
return False
class FormulaireInscription():
"""Une classe qui représente le formulaire d'inscription
Elle contient un champs ``champs'', qui contient une liste de
Fields, qui est la liste des champs qui doivent être demandés (dans
le bon ordre l'ordre).
"""
def __init__(self, request):
ip = request.remote_addr
mac_field = Field("mac", u"Adresse physique de votre carte réseau", check=is_valid_mac, default=get_mac(ip))
mac_field.ip = ip
self.champs = [
Field("nom", "Nom", check=is_name),
Field("prenom", u"Prénom", check=is_name),
Field("tel", u"Numéro de téléphone", check=is_phonenumber),
PasswordField("pass", u"Mot de passe", input_type='password'),
Field("dns", u"Nom de votre ordinateur", check=is_dns),
mac_field,
MenuField('etablissement', u"Établissement d'études", ETABLISSEMENTS),
Field("etablissement_autre", u"Précisez votre établissement d'études",
check=is_name, CLASS='formulaire_field_etablissement_autre'),
MenuField('annee_ens', u"Année scolaire à l'ENS", ANNEE_ENS),
MenuField('annee', u"Choisissez votre année scolaire", ANNEE_ETUDE),
MenuField('section_ens', u"Section", SECTIONS_ENS),
MenuField('labo', u"Laboratoire", LABOS),
Field("section", u"Précisez votre section", CLASS="formulaire_field_section")
]
def _create_form(request, parser, formulaire):
url = request.page.url(request)
ret = html.FORM(action=url, NAME="preinscription")
ret.append(html.INPUT(type='hidden', name='action', value='inscription'))
f = html.UL(CLASS="formulaire_preinscription")
for field in formulaire.champs:
champ = field.render(request, parser)
f.append(html.LI().append(champ))
ret.append(f)
ret.append(html.HR(CLASS= "invisiblesep"))
ret.append(html.INPUT(type="submit", name="inscrire", value=u"Me préinscrire"))
return unicode(ret)
def _check_form(post, formulaire):
u"""Vérifie les paramètres postés par l'utilisateur.
Vérifie que toutes les entrées du formulaire (formulaire.fields)
sont présentes et bien valides, (en appelant check() pour chaque
champs).
"""
errors = []
for field in formulaire.champs:
field.fill(post)
for field in formulaire.champs:
if not field.check():
errors.append(field.id)
return errors
def _perform_inscription(request, formulaire):
request.emit_http_headers(more_headers = ['Content-Type: text/plain'])
results = ''
for field in formulaire.champs:
results += '%(id)s: %(content)s\n' % field.__dict__
request.write(results)
def execute(pagename, request):
request.page = Page(request, pagename)
request.formatter.setPage(request.page)
request.loadTheme('crans-www')
formulaire = FormulaireInscription(request)
post = request.form
parser = wikiutil.searchAndImportPlugin(request.cfg, "parser", request.page.pi['format'])
if not request.dicts.has_member("GroupeAdmin", request.user.name) and not request.user == 'AntoineDurandGasselin':
request.theme.add_msg(u"Non, car tu es méchant", "error")
return(page.send_page())
if post.has_key('inscrire'):
if _check_form(post, formulaire) == []:
return(_perform_inscription(request, formulaire))
request.emit_http_headers()
request.theme.send_title(u"Formulaire de préinscription", pagename=pagename, html_head='<script type="text/javascript" src="/wiki/crans-www/js/passwd.js"></script>')
request.write(request.formatter.startContent("content"))
form = _create_form(request, parser, formulaire)
# THIS IS A BIG HACK. IT NEEDS TO BE CLEANED UP
request.write(form)
request.write(request.formatter.endContent())
request.theme.send_footer(pagename)
request.theme.send_closing_html()