Commit 145b0ea9 authored by Daniel STAN's avatar Daniel STAN

[voip] génération de la conf et pass confirm

parent bb1b3603
......@@ -7,6 +7,9 @@ Pour faire marcher l'intranet :
* changer la ligne ROOT_PATH correspondante
* exécuter ./manage.py syncdb
* exécuter ./manage.py collectstatic si vous mettez à jour
la version de prod
Dépendances Debian (à installer si vous voulez tester en local):
* python-django
* python-django-reversion
from django.forms import ModelForm
# -*- coding: utf-8 -*-
from django.forms import ModelForm, PasswordInput, CharField, ValidationError
from models import Profile
class ProfileForm(ModelForm):
""" Formulaire d'édition de profil Cr@ns, avec confirmation de changement de
mot de passe. Basé sur le modèle, il l'étend légèrement. """
class Meta:
model = Profile
exclude = ('user',)
"""user et num ne doivent pas être modifiés à la main. (l'un dépend de
l'autre, et cela n'est pas au choix de l'utilisateur, anyway)
password est gardé tel quel, on utilise nos validations et champs
perso pour le modifier"""
exclude = ('user', 'num', 'password')
""" Premier champ de mdp, à laisser vide si inchangé"""
pass_change1 = CharField(max_length=255,
widget=PasswordInput,
label="Mot de passe (laisser vide si inchangé)",
required=False)
""" Champ de confirmation """
pass_change2 = CharField(max_length=255,
widget=PasswordInput,
label="Mot de passe (répéter)",
required=False)
def __init__(self, *args, **kwargs):
""" Construit un formulaire. On rajoute un argument facultatif: l'user
qui édite ce formulaire (pour la création de l'objet).
On récupère aussi une instance de profil, éventuellement. Si elle
n'existe pas, c'est que l'on doit créer le profil, le mdp est donc
obligatoire (sinon non).
"""
self.user = kwargs.get('user',None)
if kwargs.has_key('user'):
del kwargs['user']
super(ProfileForm, self).__init__(*args, **kwargs)
self.need_pass = kwargs.get('instance',None) == None
def clean(self):
""" En plus des vérifications habituelles, on vérifie que les deux mdp
sont identiques, si renseignés. Et renseignés si obligatoires."""
cleaned_data = super(ProfileForm, self).clean()
p1 = cleaned_data.get('pass_change1','')
p2 = cleaned_data.get('pass_change2','')
if self.need_pass and len(p1) == 0:
raise ValidationError(u'Vous devez rentrer un mot de passe (il n\'a jamais été défini)')
if p1 != p2:
raise ValidationError(u'Les mots de passe ne correspondent pas')
# assert( p1 == p2 )
if 0 < len(p1) and len(p1) < 6:
raise ValidationError(u'Le mot de passe doit posséder au moins 6 caractères')
return cleaned_data
def save(self, commit=True):
""" On applique deux trois modifs avant de réellement sauver: on
remplace l'user et on redéfinie le mdp si changé"""
obj = super(ProfileForm, self).save(commit=False)
obj.set_user(self.user) # important: on doit calculer l'user et le num
# AVANT de définir le pass
if self.cleaned_data.get('pass_change1','') != '':
obj.set_password(self.cleaned_data['pass_change1'])
if commit:
return obj.save()
else:
return obj
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys
sys.path.append('/usr/scripts/lc_ldap/')
import lc_ldap
from django.core.management.base import BaseCommand, CommandError
from intranet.apps.voip.models import Profile
class Command(BaseCommand):
args = ''
help = 'Génère une conf pour asterisk'
def handle(self, *args, **options):
conn = lc_ldap.lc_ldap()
for profile in Profile.objects.order_by('user__username').all():
self.stdout.write(profile.asterisk_config().encode('utf-8') + '\n')
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys
sys.path.append('/usr/scripts/lc_ldap/')
import lc_ldap
from django.core.management.base import BaseCommand, CommandError
from intranet.apps.voip.models import Profile
class Command(BaseCommand):
args = ''
help = 'Génère une conf pour la boîte vocal d\'asterisk'
def handle(self, *args, **options):
conn = lc_ldap.lc_ldap()
for profile in Profile.objects.order_by('user__username').all():
self.stdout.write(profile.asterisk_voicemail_config().encode('utf-8') + '\n')
......@@ -3,6 +3,10 @@
from django.db import models
from django.contrib.auth.models import User
import hashlib
from django.utils.importlib import import_module
conn_pool = import_module('conn_pool', 'intranet')
class Profile(models.Model):
""" Profil d'utilisateur Voip """
......@@ -10,18 +14,77 @@ class Profile(models.Model):
class Meta:
verbose_name = u'Profil SIP'
verbose_name_plural = u'Profils SIP'
CALLER_IDS = [
('full_name', u'Nom complet'),
('number', u'Numéro de Téléphone'),
('both', u'Nom et numéro de téléphone'),
]
user = models.OneToOneField(User, primary_key=True)
password = models.CharField(u"Mot de passe", max_length=32, null=False, blank=False)
published = models.BooleanField(u"Publication dans l'annuaire")
caller_id = models.CharField(u"Affichage de l'appelant", max_length=9, choices=CALLER_IDS)
num = models.CharField(u"Numéro de téléphone", max_length=10, null=False, blank=False)
def set_user(self, new_user):
self.user = new_user
try:
dn = conn_pool.CONNS[new_user.username].dn.split(',')[0]
except KeyError:
raise Exception("Not allowed") # FIXME
# django.contrib.auth.logout(request.user)
# return django.shortcuts.redirect('login')
if dn.startswith('aid='):
sip_ext = '1%04d' % int(dn[4:])
else:
#return django.http.HttpResponseForbidden()
raise Exception("Not allowed") # FIXME
self.num = sip_ext
def set_password(self, new_pass):
self.password = hashlib.md5("%s:asterisk:%s" % (self.num, new_pass)).hexdigest()
def __unicode__(self):
return self.user.username
def asterisk_voicemail_config(self):
return u"%(num)s => %(mail_pass)s,%(full_name)s,%(mail)s,,attach=%(attach)s|delete=%(delete)s" % {
'num':self.num,'mail_pass':4567,'full_name':self.user.get_full_name(),
'mail':self.user.username,'attach':'yes','delete':'no'}
def asterisk_config(self):
return u""";%(uid)s
[%(num)s]
type=friend
;auth=md5
username=%(num)s
callerid="%(callerid)s"
md5secret=%(passwd)s
transport=udp,tcp,tls
host=dynamic
context=crans-sip
language=fr
insecure=port
nat=yes
canreinvite=no
dtmfmode=auto
video=no
restrictcid=no
amaflags=default
mailbox=%(num)s@666
""" % {
'callerid': self.get_caller_id(),
'num': self.num,
'passwd': self.password,
'uid': self.user.username,
}
def get_caller_id(self):
if self.caller_id == 'full_name':
return self.user.get_full_name()
elif self.caller_id == 'number':
return self.num
else: # Both
return self.user.get_full_name() + u' <' + self.num + u'>'
......@@ -5,8 +5,6 @@ from django.template import RequestContext
from models import Profile
from forms import ProfileForm
from django.utils.importlib import import_module
conn_pool = import_module('conn_pool', 'intranet')
@login_required
def index(request):
......@@ -15,19 +13,8 @@ def index(request):
except IndexError:
return django.shortcuts.render(request, "voip/noaccount.html")
try:
dn = conn_pool.CONNS[request.user.username].dn.split(',')[0]
except KeyError:
dn = ''
if dn.startswith('aid='):
sip_ext = '1%04d' % int(dn[4:])
else:
sip_ext = 'Please relogin'
return django.shortcuts.render(request, "voip/view.html",
{
'profile': profile,
'sip_ext': sip_ext,
})
{'profile': profile,})
@login_required
def edit(request):
......@@ -36,11 +23,9 @@ def edit(request):
except IndexError:
profile = None
if request.method == 'POST':
form = ProfileForm(request.POST, instance=profile)
form = ProfileForm(request.POST, instance=profile, user=request.user)
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.save()
profile = form.save()
return django.shortcuts.redirect('voip:index')
else:
form = ProfileForm(instance=profile)
......
......@@ -4,11 +4,12 @@
<p>
<dl>
<dt>Serveur</dt><dd>sip.crans.org</dd>
<dt>Nom d'utilisateur</dt><dd>{{ sip_ext }}</dd>
<dt>Mot de passe</dt><dd>{{ profile.password }}</dd>
<dt>Nom d'utilisateur</dt><dd>{{ profile.num }}</dd>
<dt>Mot de passe</dt><dd>*******</dd>
<dt>Publication dans l'annuaire</dt>
<dd>{{ profile.published|yesno:"Activée,Désactivée" }}</dd>
<dt>Présentation de l'appelant</dt><dd>{{ profile.get_caller_id_display }}</dd>
<dt>Présentation de l'appelant</dt><dd>{{ profile.get_caller_id_display }}
({{ profile.get_caller_id }})</dd>
</dl>
<a href="{% url voip:edit %}">Éditer</a>
</p>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment