8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-26 06:32:26 +00:00

Merge branch 'feature_pre_subscribtion_vlan' into 'dev'

VLAN de pré-rézotage.

See merge request federez/re2o!288
This commit is contained in:
chirac 2018-12-09 00:11:23 +01:00
commit d9dc5fc7ce
12 changed files with 851 additions and 406 deletions

View file

@ -57,14 +57,9 @@ application = get_wsgi_application()
from machines.models import Interface, IpList, Nas, Domain from machines.models import Interface, IpList, Nas, Domain
from topologie.models import Port, Switch from topologie.models import Port, Switch
from users.models import User from users.models import User
from preferences.models import OptionalTopologie from preferences.models import RadiusOption
options, created = OptionalTopologie.objects.get_or_create()
VLAN_NOK = options.vlan_decision_nok.vlan_id
VLAN_OK = options.vlan_decision_ok.vlan_id
RADIUS_POLICY = options.radius_general_policy
#: Serveur radius de test (pas la prod) #: Serveur radius de test (pas la prod)
TEST_SERVER = bool(os.getenv('DBG_FREERADIUS', False)) TEST_SERVER = bool(os.getenv('DBG_FREERADIUS', False))
@ -287,6 +282,7 @@ def find_nas_from_request(nas_id):
.select_related('machine__switch__stack')) .select_related('machine__switch__stack'))
return nas.first() return nas.first()
def check_user_machine_and_register(nas_type, username, mac_address): def check_user_machine_and_register(nas_type, username, mac_address):
"""Verifie le username et la mac renseignee. L'enregistre si elle est """Verifie le username et la mac renseignee. L'enregistre si elle est
inconnue. inconnue.
@ -327,32 +323,50 @@ def check_user_machine_and_register(nas_type, username, mac_address):
def decide_vlan_switch(nas_machine, nas_type, port_number, def decide_vlan_switch(nas_machine, nas_type, port_number,
mac_address): mac_address):
"""Fonction de placement vlan pour un switch en radius filaire auth par """Fonction de placement vlan pour un switch en radius filaire auth par
mac. mac.
Plusieurs modes : Plusieurs modes :
- nas inconnu, port inconnu : on place sur le vlan par defaut VLAN_OK - tous les modes:
- pas de radius sur le port : VLAN_OK - nas inconnu: VLAN_OK
- bloq : VLAN_NOK - port inconnu: Politique définie dans RadiusOption
- force : placement sur le vlan indiqué dans la bdd - pas de radius sur le port: VLAN_OK
- mode strict : - force: placement sur le vlan indiqué dans la bdd
- pas de chambre associée : VLAN_NOK - mode strict:
- pas d'utilisateur dans la chambre : VLAN_NOK - pas de chambre associée: Politique définie
- cotisation non à jour : VLAN_NOK dans RadiusOption
- sinon passe à common (ci-dessous) - pas d'utilisateur dans la chambre : Rejet
- mode common : (redirection web si disponible)
- interface connue (macaddress): - utilisateur de la chambre banni ou désactivé : Rejet
- utilisateur proprio non cotisant ou banni : VLAN_NOK (redirection web si disponible)
- user à jour : VLAN_OK - utilisateur de la chambre non cotisant et non whiteslist:
- interface inconnue : Politique définie dans RadiusOption
- register mac désactivé : VLAN_NOK
- register mac activé -> redirection vers webauth - sinon passe à common (ci-dessous)
- mode common :
- interface connue (macaddress):
- utilisateur proprio non cotisant / machine désactivée:
Politique définie dans RadiusOption
- utilisateur proprio banni :
Politique définie dans RadiusOption
- user à jour : VLAN_OK (réassignation de l'ipv4 au besoin)
- interface inconnue :
- register mac désactivé : Politique définie
dans RadiusOption
- register mac activé: redirection vers webauth
Returns:
tuple avec :
- Nom du switch (str)
- chambre (str)
- raison de la décision (str)
- vlan_id (int)
- decision (bool)
""" """
# Get port from switch and port number # Get port from switch and port number
extra_log = "" extra_log = ""
# Si le NAS est inconnu, on place sur le vlan defaut # Si le NAS est inconnu, on place sur le vlan defaut
if not nas_machine: if not nas_machine:
return ('?', u'Chambre inconnue', u'Nas inconnu', VLAN_OK, True) return ('?', u'Chambre inconnue', u'Nas inconnu', RadiusOption.get_cached_value('vlan_decision_ok').vlan_id, True)
sw_name = str(getattr(nas_machine, 'short_name', str(nas_machine))) sw_name = str(getattr(nas_machine, 'short_name', str(nas_machine)))
@ -367,7 +381,13 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
# Aucune information particulière ne permet de déterminer quelle # Aucune information particulière ne permet de déterminer quelle
# politique à appliquer sur ce port # politique à appliquer sur ce port
if not port: if not port:
return (sw_name, "Chambre inconnue", u'Port inconnu', VLAN_OK, True) return (
sw_name,
"Chambre inconnue",
u'Port inconnu',
RadiusOption('unknown_port_vlan').vlan_id,
RadiusOption('unknown_port')!= RadiusOption.REJECT
)
# On récupère le profil du port # On récupère le profil du port
port_profile = port.get_port_profile port_profile = port.get_port_profile
@ -378,11 +398,11 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
DECISION_VLAN = int(port_profile.vlan_untagged.vlan_id) DECISION_VLAN = int(port_profile.vlan_untagged.vlan_id)
extra_log = u"Force sur vlan " + str(DECISION_VLAN) extra_log = u"Force sur vlan " + str(DECISION_VLAN)
else: else:
DECISION_VLAN = VLAN_OK DECISION_VLAN = RadiusOption.get_cached_value('vlan_decision_ok')
# Si le port est désactivé, on rejette sur le vlan de déconnexion # Si le port est désactivé, on rejette la connexion
if not port.state: if not port.state:
return (sw_name, port.room, u'Port desactivé', VLAN_NOK, True) return (sw_name, port.room, u'Port desactivé', None, False)
# Si radius est désactivé, on laisse passer # Si radius est désactivé, on laisse passer
if port_profile.radius_type == 'NO': if port_profile.radius_type == 'NO':
@ -392,33 +412,68 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
DECISION_VLAN, DECISION_VLAN,
True) True)
# Si le 802.1X est activé sur ce port, cela veut dire que la personne a été accept précédemment # Si le 802.1X est activé sur ce port, cela veut dire que la personne a
# été accept précédemment
# Par conséquent, on laisse passer sur le bon vlan # Par conséquent, on laisse passer sur le bon vlan
if nas_type.port_access_mode == '802.1X' and port_profile.radius_type == '802.1X': if (nas_type.port_access_mode, port_profile.radius_type) == ('802.1X', '802.1X'):
room = port.room or "Chambre/local inconnu" room = port.room or "Chambre/local inconnu"
return (sw_name, room, u'Acceptation authentification 802.1X', DECISION_VLAN, True) return (
sw_name,
room,
u'Acceptation authentification 802.1X',
DECISION_VLAN,
True
)
# Sinon, cela veut dire qu'on fait de l'auth radius par mac # Sinon, cela veut dire qu'on fait de l'auth radius par mac
# Si le port est en mode strict, on vérifie que tous les users # Si le port est en mode strict, on vérifie que tous les users
# rattachés à ce port sont bien à jour de cotisation. Sinon on rejette (anti squattage) # rattachés à ce port sont bien à jour de cotisation. Sinon on rejette
# Il n'est pas possible de se connecter sur une prise strict sans adhérent à jour de cotis # (anti squattage)
# dedans # Il n'est pas possible de se connecter sur une prise strict sans adhérent
# à jour de cotis dedans
if port_profile.radius_mode == 'STRICT': if port_profile.radius_mode == 'STRICT':
room = port.room room = port.room
if not room: if not room:
return (sw_name, "Inconnue", u'Chambre inconnue', VLAN_NOK, True) return (
sw_name,
"Inconnue",
u'Chambre inconnue',
RadiusOption('unknown_room_vlan').vlan_id,
RadiusOption('unknown_room')!= RadiusOption.REJECT
)
room_user = User.objects.filter( room_user = User.objects.filter(
Q(club__room=port.room) | Q(adherent__room=port.room) Q(club__room=port.room) | Q(adherent__room=port.room)
) )
if not room_user: if not room_user:
return (sw_name, room, u'Chambre non cotisante -> Web redirect', None, False) return (
sw_name,
room,
u'Chambre non cotisante -> Web redirect',
None,
False
)
for user in room_user: for user in room_user:
if not user.has_access(): if user.is_ban() or user.state != User.STATE_ACTIVE:
return (sw_name, room, u'Chambre resident desactive -> Web redirect', None, False) return (
sw_name,
room,
u'Utilisateur banni ou désactivé -> Web redirect',
None,
False
)
elif not (user.is_connected() or user.is_whitelisted()):
return (
sw_name,
room,
u'Utilisateur non cotisant',
RadiusOption('non_member_vlan').vlan_id,
RadiusOption('non_member')!= RadiusOption.REJECT
)
# else: user OK, on passe à la verif MAC # else: user OK, on passe à la verif MAC
# Si on fait de l'auth par mac, on cherche l'interface via sa mac dans la bdd # Si on fait de l'auth par mac, on cherche l'interface
# via sa mac dans la bdd
if port_profile.radius_mode == 'COMMON' or port_profile.radius_mode == 'STRICT': if port_profile.radius_mode == 'COMMON' or port_profile.radius_mode == 'STRICT':
# Authentification par mac # Authentification par mac
interface = (Interface.objects interface = (Interface.objects
@ -428,38 +483,67 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
.first()) .first())
if not interface: if not interface:
room = port.room room = port.room
# On essaye de register la mac, si l'autocapture a été activée # On essaye de register la mac, si l'autocapture a été activée,
# Sinon on rejette sur vlan_nok # on rejette pour faire une redirection web si possible.
if not nas_type.autocapture_mac: if nas_type.autocapture_mac:
return (sw_name, "", u'Machine inconnue', VLAN_NOK, True) return (
# On rejette pour basculer sur du webauth sw_name,
room,
u'Machine Inconnue -> Web redirect',
None,
False
)
# Sinon on bascule sur la politique définie dans les options
# radius.
else: else:
return (sw_name, room, u'Machine Inconnue -> Web redirect', None, False) return (
sw_name,
"",
u'Machine inconnue',
RadiusOption('unknown_machine_vlan').vlan_id,
RadiusOption('unknown_machine')!= RadiusOption.REJECT
)
# L'interface a été trouvée, on vérifie qu'elle est active, sinon on reject # L'interface a été trouvée, on vérifie qu'elle est active,
# sinon on reject
# Si elle n'a pas d'ipv4, on lui en met une # Si elle n'a pas d'ipv4, on lui en met une
# Enfin on laisse passer sur le vlan pertinent # Enfin on laisse passer sur le vlan pertinent
else: else:
room = port.room room = port.room
if interface.machine.user.is_ban():
return (
sw_name,
room,
u'Adherent banni',
RadiusOption('banned_vlan').vlan_id,
RadiusOption('banned')!= RadiusOption.REJECT
)
if not interface.is_active: if not interface.is_active:
return (sw_name, return (
room, sw_name,
u'Machine non active / adherent non cotisant', room,
VLAN_NOK, u'Machine non active / adherent non cotisant',
True) RadiusOption('non_member_vlan').vlan_id,
## Si on choisi de placer les machines sur le vlan correspondant à leur type : RadiusOption('non_member')!= RadiusOption.REJECT
if RADIUS_POLICY == 'MACHINE': )
# Si on choisi de placer les machines sur le vlan
# correspondant à leur type :
if RadiusOption.get_cached_value('radius_general_policy') == 'MACHINE':
DECISION_VLAN = interface.type.ip_type.vlan.vlan_id DECISION_VLAN = interface.type.ip_type.vlan.vlan_id
if not interface.ipv4: if not interface.ipv4:
interface.assign_ipv4() interface.assign_ipv4()
return (sw_name, return (
room, sw_name,
u"Ok, Reassignation de l'ipv4" + extra_log, room,
DECISION_VLAN, u"Ok, Reassignation de l'ipv4" + extra_log,
True) DECISION_VLAN,
True
)
else: else:
return (sw_name, return (
room, sw_name,
u'Machine OK' + extra_log, room,
DECISION_VLAN, u'Machine OK' + extra_log,
True) DECISION_VLAN,
True
)

View file

@ -42,6 +42,7 @@ from .models import (
Reminder, Reminder,
RadiusKey, RadiusKey,
SwitchManagementCred, SwitchManagementCred,
RadiusOption,
) )
from topologie.models import Switch from topologie.models import Switch
@ -229,6 +230,13 @@ class EditHomeOptionForm(ModelForm):
self.fields['twitter_account_name'].label = _("Twitter account name") self.fields['twitter_account_name'].label = _("Twitter account name")
class EditRadiusOptionForm(ModelForm):
"""Edition forms for Radius options"""
class Meta:
model = RadiusOption
fields = '__all__'
class ServiceForm(ModelForm): class ServiceForm(ModelForm):
"""Edition, ajout de services sur la page d'accueil""" """Edition, ajout de services sur la page d'accueil"""
class Meta: class Meta:

View file

@ -8,7 +8,7 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('preferences', '0054_merge_20181025_1258'), ('preferences', '0053_optionaluser_self_change_room'),
] ]
operations = [ operations = [

View file

@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-10-13 14:29
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import re2o.mixins
def create_radius_policy(apps, schema_editor):
OptionalTopologie = apps.get_model('preferences', 'OptionalTopologie')
RadiusOption = apps.get_model('preferences', 'RadiusOption')
option,_ = OptionalTopologie.objects.get_or_create()
radius_option = RadiusOption()
radius_option.radius_general_policy = option.radius_general_policy
radius_option.vlan_decision_ok = option.vlan_decision_ok
radius_option.save()
class Migration(migrations.Migration):
dependencies = [
('machines', '0095_auto_20180919_2225'),
('preferences', '0055_generaloption_main_site_url'),
]
operations = [
migrations.CreateModel(
name='RadiusOption',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('radius_general_policy', models.CharField(choices=[('MACHINE', "On the IP range's VLAN of the machine"), ('DEFINED', "Preset in 'VLAN for machines accepted by RADIUS'")], default='DEFINED', max_length=32)),
],
options={
'verbose_name': 'radius policies',
},
bases=(re2o.mixins.AclMixin, models.Model),
),
migrations.AddField(
model_name='radiusoption',
name='banned_vlan',
field=models.ForeignKey(blank=True, help_text='Vlan for banned if not rejected.', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='banned_vlan', to='machines.Vlan', verbose_name='Banned Vlan'),
),
migrations.AddField(
model_name='radiusoption',
name='non_member_vlan',
field=models.ForeignKey(blank=True, help_text='Vlan for non members if not rejected.', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='non_member_vlan', to='machines.Vlan', verbose_name='Non member Vlan'),
),
migrations.AddField(
model_name='radiusoption',
name='unknown_machine_vlan',
field=models.ForeignKey(blank=True, help_text='Vlan for unknown machines if not rejected.', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='unknown_machine_vlan', to='machines.Vlan', verbose_name='Unknown machine Vlan'),
),
migrations.AddField(
model_name='radiusoption',
name='unknown_port_vlan',
field=models.ForeignKey(blank=True, help_text='Vlan for unknown ports if not rejected.', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='unknown_port_vlan', to='machines.Vlan', verbose_name='Unknown port Vlan'),
),
migrations.AddField(
model_name='radiusoption',
name='unknown_room_vlan',
field=models.ForeignKey(blank=True, help_text='Vlan for unknown room if not rejected.', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='unknown_room_vlan', to='machines.Vlan', verbose_name='Unknown room Vlan'),
),
migrations.AddField(
model_name='radiusoption',
name='banned',
field=models.CharField(choices=[('REJECT', 'Reject the machine'), ('SET_VLAN', 'Place the machine on the VLAN')], default='REJECT', max_length=32, verbose_name='Policy for banned users.'),
),
migrations.AddField(
model_name='radiusoption',
name='non_member',
field=models.CharField(choices=[('REJECT', 'Reject the machine'), ('SET_VLAN', 'Place the machine on the VLAN')], default='REJECT', max_length=32, verbose_name='Policy non member users.'),
),
migrations.AddField(
model_name='radiusoption',
name='unknown_machine',
field=models.CharField(choices=[('REJECT', 'Reject the machine'), ('SET_VLAN', 'Place the machine on the VLAN')], default='REJECT', max_length=32, verbose_name='Policy for unknown machines'),
),
migrations.AddField(
model_name='radiusoption',
name='unknown_port',
field=models.CharField(choices=[('REJECT', 'Reject the machine'), ('SET_VLAN', 'Place the machine on the VLAN')], default='REJECT', max_length=32, verbose_name='Policy for unknown machines'),
),
migrations.AddField(
model_name='radiusoption',
name='unknown_room',
field=models.CharField(choices=[('REJECT', 'Reject the machine'), ('SET_VLAN', 'Place the machine on the VLAN')], default='REJECT', max_length=32, verbose_name='Policy for machine connecting from unregistered room (relevant on ports with STRICT radius mode)'),
),
migrations.AddField(
model_name='radiusoption',
name='vlan_decision_ok',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vlan_ok_option', to='machines.Vlan'),
),
migrations.RunPython(create_radius_policy),
migrations.RemoveField(
model_name='optionaltopologie',
name='radius_general_policy',
),
migrations.RemoveField(
model_name='optionaltopologie',
name='vlan_decision_nok',
),
migrations.RemoveField(
model_name='optionaltopologie',
name='vlan_decision_ok',
),
]

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-12-04 13:57
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('preferences', '0056_radiusoption'),
]
operations = [
migrations.AlterField(
model_name='radiusoption',
name='unknown_port',
field=models.CharField(choices=[('REJECT', 'Reject the machine'), ('SET_VLAN', 'Place the machine on the VLAN')], default='REJECT', max_length=32, verbose_name='Policy for unknown port'),
),
]

View file

@ -199,25 +199,6 @@ class OptionalTopologie(AclMixin, PreferencesModel):
('tftp', 'tftp'), ('tftp', 'tftp'),
) )
radius_general_policy = models.CharField(
max_length=32,
choices=CHOICE_RADIUS,
default='DEFINED'
)
vlan_decision_ok = models.OneToOneField(
'machines.Vlan',
on_delete=models.PROTECT,
related_name='decision_ok',
blank=True,
null=True
)
vlan_decision_nok = models.OneToOneField(
'machines.Vlan',
on_delete=models.PROTECT,
related_name='decision_nok',
blank=True,
null=True
)
switchs_web_management = models.BooleanField( switchs_web_management = models.BooleanField(
default=False, default=False,
help_text="Web management, activé si provision automatique" help_text="Web management, activé si provision automatique"
@ -309,7 +290,6 @@ class OptionalTopologie(AclMixin, PreferencesModel):
"""Return true if all settings are ok : switchs on automatic provision, """Return true if all settings are ok : switchs on automatic provision,
ip_type""" ip_type"""
return bool(self.provisioned_switchs and self.switchs_ip_type and SwitchManagementCred.objects.filter(default_switch=True).exists() and self.switchs_management_interface_ip and bool(self.switchs_provision != 'sftp' or self.switchs_management_sftp_creds)) return bool(self.provisioned_switchs and self.switchs_ip_type and SwitchManagementCred.objects.filter(default_switch=True).exists() and self.switchs_management_interface_ip and bool(self.switchs_provision != 'sftp' or self.switchs_management_sftp_creds))
class Meta: class Meta:
permissions = ( permissions = (
("view_optionaltopologie", _("Can view the topology options")), ("view_optionaltopologie", _("Can view the topology options")),
@ -588,3 +568,122 @@ class MailMessageOption(AclMixin, models.Model):
) )
verbose_name = _("email message options") verbose_name = _("email message options")
class RadiusOption(AclMixin, PreferencesModel):
class Meta:
verbose_name = _("radius policies")
MACHINE = 'MACHINE'
DEFINED = 'DEFINED'
CHOICE_RADIUS = (
(MACHINE, _("On the IP range's VLAN of the machine")),
(DEFINED, _("Preset in 'VLAN for machines accepted by RADIUS'")),
)
REJECT = 'REJECT'
SET_VLAN = 'SET_VLAN'
CHOICE_POLICY = (
(REJECT, _('Reject the machine')),
(SET_VLAN, _('Place the machine on the VLAN'))
)
radius_general_policy = models.CharField(
max_length=32,
choices=CHOICE_RADIUS,
default='DEFINED'
)
unknown_machine = models.CharField(
max_length=32,
choices=CHOICE_POLICY,
default=REJECT,
verbose_name=_("Policy for unknown machines"),
)
unknown_machine_vlan = models.ForeignKey(
'machines.Vlan',
on_delete=models.PROTECT,
related_name='unknown_machine_vlan',
blank=True,
null=True,
verbose_name=_('Unknown machine Vlan'),
help_text=_(
'Vlan for unknown machines if not rejected.'
)
)
unknown_port = models.CharField(
max_length=32,
choices=CHOICE_POLICY,
default=REJECT,
verbose_name=_("Policy for unknown port"),
)
unknown_port_vlan = models.ForeignKey(
'machines.Vlan',
on_delete=models.PROTECT,
related_name='unknown_port_vlan',
blank=True,
null=True,
verbose_name=_('Unknown port Vlan'),
help_text=_(
'Vlan for unknown ports if not rejected.'
)
)
unknown_room = models.CharField(
max_length=32,
choices=CHOICE_POLICY,
default=REJECT,
verbose_name=_(
"Policy for machine connecting from "
"unregistered room (relevant on ports with STRICT "
"radius mode)"
),
)
unknown_room_vlan = models.ForeignKey(
'machines.Vlan',
related_name='unknown_room_vlan',
on_delete=models.PROTECT,
blank=True,
null=True,
verbose_name=_('Unknown room Vlan'),
help_text=_(
'Vlan for unknown room if not rejected.'
)
)
non_member = models.CharField(
max_length=32,
choices=CHOICE_POLICY,
default=REJECT,
verbose_name=_("Policy non member users."),
)
non_member_vlan = models.ForeignKey(
'machines.Vlan',
related_name='non_member_vlan',
on_delete=models.PROTECT,
blank=True,
null=True,
verbose_name=_('Non member Vlan'),
help_text=_(
'Vlan for non members if not rejected.'
)
)
banned = models.CharField(
max_length=32,
choices=CHOICE_POLICY,
default=REJECT,
verbose_name=_("Policy for banned users."),
)
banned_vlan = models.ForeignKey(
'machines.Vlan',
related_name='banned_vlan',
on_delete=models.PROTECT,
blank=True,
null=True,
verbose_name=_('Banned Vlan'),
help_text=_(
'Vlan for banned if not rejected.'
)
)
vlan_decision_ok = models.OneToOneField(
'machines.Vlan',
on_delete=models.PROTECT,
related_name='vlan_ok_option',
blank=True,
null=True
)

View file

@ -0,0 +1,96 @@
{% comment %}
Re2o est un logiciel d'administration développé initiallement au rezometz. Il
se veut agnostique au réseau considéré, de manière à être installable en
quelques clics.
Copyright © 2018 Hugo Levy-Falk
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
{% endcomment %}
{% load i18n %}
{% load acl %}
{% load logs_extra %}
<table>
<tr>
<th>{% trans "General policy for VLAN setting" %}</th>
<td>{{ radiusoptions.radius_general_policy }}</td>
<td>{% trans "This setting defines the VLAN policy after acceptance by RADIUS: either on the IP range's VLAN of the machine, or a VLAN preset in 'VLAN for machines accepted by RADIUS'" %}</td>
</tr>
<tr>
<th>{% trans "VLAN for machines accepted by RADIUS" %}</th>
<td><span class="label label-success">Vlan {{ radiusoptions.vlan_decision_ok }}</span></td>
</tr>
</table>
<hr/>
<table class="table table-striped">
<thead>
<tr>
<th>{% trans "Situation" %}</th>
<th>{% trans "Behavior" %}</th>
</tr>
</thead>
<tr>
<th>{% trans "Unknown machine" %}</th>
<td>
{% if radiusoptions.unknown_machine == 'REJECT' %}
<span class="label label-danger">{% trans "Reject" %}</span>
{% else %}
<span class="label label-success">Vlan {{ radiusoptions.unknown_machine_vlan }}</span>
{% endif %}
</td>
</tr>
<tr>
<th>{% trans "Unknown port" %}</th>
<td>
{% if radiusoptions.unknown_port == 'REJECT' %}
<span class="label label-danger">{% trans "Reject" %}</span>
{% else %}
<span class="label label-success">Vlan {{ radiusoptions.unknown_port_vlan }}</span>
{% endif %}
</td>
</tr>
<tr>
<th>{% trans "Unknown room" %}</th>
<td>
{% if radiusoptions.unknown_room == 'REJECT' %}
<span class="label label-danger">{% trans "Reject" %}</span>
{% else %}
<span class="label label-success">Vlan {{ radiusoptions.unknown_room_vlan }}</span>
{% endif %}
</td>
</tr>
<tr>
<th>{% trans "Non member" %}</th>
<td>
{% if radiusoptions.non_member == 'REJECT' %}
<span class="label label-danger">{% trans "Reject" %}</span>
{% else %}
<span class="label label-success">Vlan {{ radiusoptions.non_member_vlan }}</span>
{% endif %}
</td>
</tr>
<tr>
<th>{% trans "Banned user" %}</th>
<td>
{% if radiusoptions.unknown_port == 'REJECT' %}
<span class="label label-danger">{% trans "Reject" %}</span>
{% else %}
<span class="label label-success">Vlan {{ radiusoptions.banned_vlan }}</span>
{% endif %}
</td>
</tr>
</table>

View file

@ -33,203 +33,203 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% block content %} {% block content %}
<div id="accordion"> <div id="accordion">
<div class="panel panel-default" id="general"> <div class="panel panel-default" id="general">
<div class="panel-heading" data-toggle="collapse" href="#collapse_general"> <div class="panel-heading" data-toggle="collapse" href="#collapse_general">
<h4 class="panel-title" id="general"> <h4 class="panel-title" id="general">
<a><i class="fa fa-cog"></i> {% trans "General preferences" %}</a> <a><i class="fa fa-cog"></i> {% trans "General preferences" %}</a>
</h4> </h4>
</div> </div>
<div id="collapse_general" class="panel-collapse panel-body collapse"> <div id="collapse_general" class="panel-collapse panel-body collapse">
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'GeneralOption' %}"> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'GeneralOption' %}">
<i class="fa fa-edit"></i>{% trans "Edit" %} <i class="fa fa-edit"></i>{% trans "Edit" %}
</a> </a>
<p></p> <p></p>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>{% trans "Website name" %}</th> <th>{% trans "Website name" %}</th>
<td>{{ generaloptions.site_name }}</td> <td>{{ generaloptions.site_name }}</td>
<th>{% trans "Email address for automatic emailing" %}</th> <th>{% trans "Email address for automatic emailing" %}</th>
<td>{{ generaloptions.email_from }}</td> <td>{{ generaloptions.email_from }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Number of results displayed when searching" %}</th> <th>{% trans "Number of results displayed when searching" %}</th>
<td>{{ generaloptions.search_display_page }}</td> <td>{{ generaloptions.search_display_page }}</td>
<th>{% trans "Number of items per page (standard size)" %}</th> <th>{% trans "Number of items per page (standard size)" %}</th>
<td>{{ generaloptions.pagination_number }}</td> <td>{{ generaloptions.pagination_number }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Number of items per page (large size)" %}</th> <th>{% trans "Number of items per page (large size)" %}</th>
<td>{{ generaloptions.pagination_large_number }}</td> <td>{{ generaloptions.pagination_large_number }}</td>
<th>{% trans "Time before expiration of the reset password link (in hours)" %}</th> <th>{% trans "Time before expiration of the reset password link (in hours)" %}</th>
<td>{{ generaloptions.req_expire_hrs }}</td> <td>{{ generaloptions.req_expire_hrs }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "General message displayed on the website" %}</th> <th>{% trans "General message displayed on the website" %}</th>
<td>{{ generaloptions.general_message }}</td> <td>{{ generaloptions.general_message }}</td>
<th>{% trans "Main site url" %}</th> <th>{% trans "Main site url" %}</th>
<td>{{ generaloptions.main_site_url }}</td> <td>{{ generaloptions.main_site_url }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Summary of the General Terms of Use" %}</th> <th>{% trans "Summary of the General Terms of Use" %}</th>
<td>{{ generaloptions.GTU_sum_up }}</td> <td>{{ generaloptions.GTU_sum_up }}</td>
<th>{% trans "General Terms of Use" %}</th> <th>{% trans "General Terms of Use" %}</th>
<td>{{ generaloptions.GTU }}</th> <td>{{ generaloptions.GTU }}</th>
</tr> </tr>
</table> </table>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>{% trans "Local email accounts enabled" %}</th> <th>{% trans "Local email accounts enabled" %}</th>
<td>{{ useroptions.local_email_accounts_enabled|tick }}</td> <td>{{ useroptions.local_email_accounts_enabled|tick }}</td>
<th>{% trans "Local email domain" %}</th> <th>{% trans "Local email domain" %}</th>
<td>{{ useroptions.local_email_domain }}</td> <td>{{ useroptions.local_email_domain }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Maximum number of email aliases allowed" %}</th> <th>{% trans "Maximum number of email aliases allowed" %}</th>
<td>{{ useroptions.max_email_address }}</td> <td>{{ useroptions.max_email_address }}</td>
</tr> </tr>
</table> </table>
</div> </div>
</div>
<div class="panel panel-default" id="users">
<div class="panel-heading" data-toggle="collapse" href="#collapse_users">
<h4 class="panel-title">
<a><i class="fa fa-users fa-fw"></i> {% trans "User preferences" %}</a>
</h4>
</div> </div>
<div id="collapse_users" class="panel-collapse panel-body collapse">
<p></p> <div class="panel panel-default" id="users">
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalUser' %}"> <div class="panel-heading" data-toggle="collapse" href="#collapse_users">
<i class="fa fa-edit"></i> <h4 class="panel-title">
{% trans "Edit" %} <a><i class="fa fa-users fa-fw"></i> {% trans "User preferences" %}</a>
</a> </h4>
<p></p> </div>
<div id="collapse_users" class="panel-collapse panel-body collapse">
<table class="table table-striped"> <p></p>
<tr> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalUser' %}">
<th>{% trans "Creation of members by everyone" %}</th> <i class="fa fa-edit"></i>
<td>{{ useroptions.all_can_create_adherent|tick }}</td> {% trans "Edit" %}
<th>{% trans "Creation of clubs by everyone" %}</th> </a>
<td>{{ useroptions.all_can_create_club|tick }}</td> <p></p>
</tr>
<tr> <table class="table table-striped">
<th>{% trans "Self registration" %}</th> <tr>
<td>{{ useroptions.self_adhesion|tick }}</td> <th>{% trans "Creation of members by everyone" %}</th>
<th>{% trans "Delete not yet active users after" %}</th> <td>{{ useroptions.all_can_create_adherent|tick }}</td>
<td>{{ useroptions.delete_notyetactive }} days</td> <th>{% trans "Creation of clubs by everyone" %}</th>
</tr> <td>{{ useroptions.all_can_create_club|tick }}</td>
</tr>
<tr>
<th>{% trans "Self registration" %}</th>
<td>{{ useroptions.self_adhesion|tick }}</td>
<th>{% trans "Delete not yet active users after" %}</th>
<td>{{ useroptions.delete_notyetactive }} days</td>
</tr>
</table> </table>
<h4 id="users">{% trans "Users general permissions" %}</h4> <h4 id="users">{% trans "Users general permissions" %}</h4>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>{% trans "Default shell for users" %}</th> <th>{% trans "Default shell for users" %}</th>
<td>{{ useroptions.shell_default }}</td> <td>{{ useroptions.shell_default }}</td>
<th>{% trans "Users can edit their shell" %}</th> <th>{% trans "Users can edit their shell" %}</th>
<td>{{ useroptions.self_change_shell|tick }}</td> <td>{{ useroptions.self_change_shell|tick }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Users can edit their room" %}</th> <th>{% trans "Users can edit their room" %}</th>
<td>{{ useroptions.self_change_room|tick }}</td> <td>{{ useroptions.self_change_room|tick }}</td>
<th>{% trans "Telephone number required" %}</th> <th>{% trans "Telephone number required" %}</th>
<td>{{ useroptions.is_tel_mandatory|tick }}</td> <td>{{ useroptions.is_tel_mandatory|tick }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "GPG fingerprint field" %}</th> <th>{% trans "GPG fingerprint field" %}</th>
<td>{{ useroptions.gpg_fingerprint|tick }}</td> <td>{{ useroptions.gpg_fingerprint|tick }}</td>
</tr> </tr>
</table> </table>
</div>
</div> </div>
</div> </div>
</div>
<div class="panel panel-default" id="machines"> <div class="panel panel-default" id="machines">
<div class="panel-heading" data-toggle="collapse" href="#collapse_machines"> <div class="panel-heading" data-toggle="collapse" href="#collapse_machines">
<h4 class ="panel-title"> <h4 class ="panel-title">
<a><i class="fa fa-desktop"></i> {% trans "Machines preferences" %}</a> <a><i class="fa fa-desktop"></i> {% trans "Machines preferences" %}</a>
</h4> </h4>
</div> </div>
<div id="collapse_machines" class="panel-collapse panel-body collapse"> <div id="collapse_machines" class="panel-collapse panel-body collapse">
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalMachine' %}"> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalMachine' %}">
<i class="fa fa-edit"></i> <i class="fa fa-edit"></i>
{% trans "Edit" %} {% trans "Edit" %}
</a> </a>
<p></p> <p></p>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>{% trans "Password per machine" %}</th> <th>{% trans "Password per machine" %}</th>
<td>{{ machineoptions.password_machine|tick }}</td> <td>{{ machineoptions.password_machine|tick }}</td>
<th>{% trans "Maximum number of interfaces allowed for a standard user" %}</th> <th>{% trans "Maximum number of interfaces allowed for a standard user" %}</th>
<td>{{ machineoptions.max_lambdauser_interfaces }}</td> <td>{{ machineoptions.max_lambdauser_interfaces }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Maximum number of DNS aliases allowed for a standard user" %}</th> <th>{% trans "Maximum number of DNS aliases allowed for a standard user" %}</th>
<td>{{ machineoptions.max_lambdauser_aliases }}</td> <td>{{ machineoptions.max_lambdauser_aliases }}</td>
<th>{% trans "IPv6 support" %}</th> <th>{% trans "IPv6 support" %}</th>
<td>{{ machineoptions.ipv6_mode }}</td> <td>{{ machineoptions.ipv6_mode }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Creation of machines" %}</th> <th>{% trans "Creation of machines" %}</th>
<td>{{ machineoptions.create_machine|tick }}</td> <td>{{ machineoptions.create_machine|tick }}</td>
</tr> </tr>
</table> </table>
</div> </div>
</div> </div>
<div class="panel panel-default" id="topo"> <div class="panel panel-default" id="topo">
<div class="panel-heading" data-toggle="collapse" href="#collapse_topo"> <div class="panel-heading" data-toggle="collapse" href="#collapse_topo">
<h4 class="panel-title"> <h4 class="panel-title">
<a><i class="fa fa-sitemap"></i> {% trans "Topology preferences" %}</a> <a><i class="fa fa-sitemap"></i> {% trans "Topology preferences" %}</a>
</h4> </h4>
</div> </div>
<div id="collapse_topo" class="panel-collapse panel-body collapse"> <div id="collapse_topo" class="panel-collapse panel-body collapse">
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalTopologie' %}"> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalTopologie' %}">
<i class="fa fa-edit"></i> <i class="fa fa-edit"></i>
{% trans "Edit" %} {% trans "Edit" %}
</a> </a>
<p></p> <p></p>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>{% trans "General policy for VLAN setting" %}</th> <th>{% trans "General policy for VLAN setting" %}</th>
<td>{{ topologieoptions.radius_general_policy }}</td> <td>{{ topologieoptions.radius_general_policy }}</td>
<th>{% trans "This setting defines the VLAN policy after acceptance by RADIUS: either on the IP range's VLAN of the machine, or a VLAN preset in 'VLAN for machines accepted by RADIUS'" %}</th> <th>{% trans "This setting defines the VLAN policy after acceptance by RADIUS: either on the IP range's VLAN of the machine, or a VLAN preset in 'VLAN for machines accepted by RADIUS'" %}</th>
<td></td> <td></td>
</tr> </tr>
<tr> <tr>
<th>{% trans "VLAN for machines accepted by RADIUS" %}</th> <th>{% trans "VLAN for machines accepted by RADIUS" %}</th>
<td>{{ topologieoptions.vlan_decision_ok }}</td> <td>{{ topologieoptions.vlan_decision_ok }}</td>
<th>{% trans "VLAN for machines rejected by RADIUS" %}</th> <th>{% trans "VLAN for machines rejected by RADIUS" %}</th>
<td>{{ topologieoptions.vlan_decision_nok }}</td> <td>{{ topologieoptions.vlan_decision_nok }}</td>
</tr> </tr>
<tr> <tr>
<th>Placement sur ce vlan par default en cas de rejet</th> <th>{% trans "VLAN for non members machines" %}</th>
<td>{{ topologieoptions.vlan_decision_nok }}</td> <td>{{ topologieoptions.vlan_non_member }}</td>
</tr> </tr>
</table> </table>
<h4>Clef radius</h4> <h4>Clef radius</h4>
{% can_create RadiusKey%} {% can_create RadiusKey%}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:add-radiuskey' %}"><i class="fa fa-plus"></i> Ajouter une clef radius</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:add-radiuskey' %}"><i class="fa fa-plus"></i> Ajouter une clef radius</a>
{% acl_end %} {% acl_end %}
{% include "preferences/aff_radiuskey.html" with radiuskey_list=radiuskey_list %} {% include "preferences/aff_radiuskey.html" with radiuskey_list=radiuskey_list %}
</div> </div>
</div> </div>
<div class="panel panel-default" id="switches"> <div class="panel panel-default" id="switches">
<div class="panel-heading" data-toggle="collapse" href="#collapse_switches"> <div class="panel-heading" data-toggle="collapse" href="#collapse_switches">
<h4 class="panel-title"> <h4 class="panel-title">
<a><i class="fa fa-server"></i> Configuration des Switches</a> <a><i class="fa fa-server"></i> Configuration des Switches</a>
</h4> </h4>
</div> </div>
<div id="collapse_switches" class="panel-collapse panel-body collapse"> <div id="collapse_switches" class="panel-collapse panel-body collapse">
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalTopologie' %}"> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'OptionalTopologie' %}">
<i class="fa fa-edit"></i> <i class="fa fa-edit"></i>
@ -238,106 +238,117 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<p></p> <p></p>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>Web management, activé si provision automatique</th> <th>Web management, activé si provision automatique</th>
<td>{{ topologieoptions.switchs_web_management }}</td> <td>{{ topologieoptions.switchs_web_management }}</td>
<th>Rest management, activé si provision auto</th> <th>Rest management, activé si provision auto</th>
<td>{{ topologieoptions.switchs_rest_management }}</td> <td>{{ topologieoptions.switchs_rest_management }}</td>
</tr> </tr>
</table> </table>
<h5>{% if topologieoptions.provision_switchs_enabled %}<span class="label label-success">Provision de la config des switchs{% else %}<span class="label label-danger">Provision de la config des switchs{% endif%}</span></h5> <h5>{% if topologieoptions.provision_switchs_enabled %}<span class="label label-success">Provision de la config des switchs{% else %}<span class="label label-danger">Provision de la config des switchs{% endif%}</span></h5>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>Switchs configurés automatiquement</th> <th>Switchs configurés automatiquement</th>
<td>{{ topologieoptions.provisioned_switchs|join:", " }} {% if topologieoptions.provisioned_switchs %}<span class="label label-success"> OK{% else %}<span class="label label-danger">Manquant{% endif %}</span></td> <td>{{ topologieoptions.provisioned_switchs|join:", " }} {% if topologieoptions.provisioned_switchs %}<span class="label label-success"> OK{% else %}<span class="label label-danger">Manquant{% endif %}</span></td>
</tr> </tr>
<tr> <tr>
<th>Plage d'ip de management des switchs</th> <th>Plage d'ip de management des switchs</th>
<td>{{ topologieoptions.switchs_ip_type }} {% if topologieoptions.switchs_ip_type %}<span class="label label-success"> OK{% else %}<span class="label label-danger">Manquant{% endif %}</span></td> <td>{{ topologieoptions.switchs_ip_type }} {% if topologieoptions.switchs_ip_type %}<span class="label label-success"> OK{% else %}<span class="label label-danger">Manquant{% endif %}</span></td>
</tr> </tr>
<tr> <tr>
<th>Serveur des config des switchs</th> <th>Serveur des config des switchs</th>
<td>{{ topologieoptions.switchs_management_interface }} {% if topologieoptions.switchs_management_interface %} - {{ topologieoptions.switchs_management_interface_ip }} <span class="label label-success"> OK{% else %}<span class="label label-danger">Manquant{% endif %}</span></td> <td>{{ topologieoptions.switchs_management_interface }} {% if topologieoptions.switchs_management_interface %} - {{ topologieoptions.switchs_management_interface_ip }} <span class="label label-success"> OK{% else %}<span class="label label-danger">Manquant{% endif %}</span></td>
</tr> </tr>
<tr> <tr>
<th>Mode de provision des switchs</th> <th>Mode de provision des switchs</th>
<td>{{ topologieoptions.switchs_provision }}</td> <td>{{ topologieoptions.switchs_provision }}</td>
</tr> </tr>
<tr> <tr>
<th>Mode TFTP</th> <th>Mode TFTP</th>
<td><span class="label label-success"> OK</span></td> <td><span class="label label-success"> OK</span></td>
</tr> </tr>
<tr> <tr>
<th>Mode SFTP</th> <th>Mode SFTP</th>
<td>{% if topologieoptions.switchs_management_sftp_creds %}<span class="label label-success"> OK{% else %}<span class="label label-danger">Creds manquants{% endif %}</span></td> <td>{% if topologieoptions.switchs_management_sftp_creds %}<span class="label label-success"> OK{% else %}<span class="label label-danger">Creds manquants{% endif %}</span></td>
</tr> </tr>
</table> </table>
<h6>Creds de management des switchs</h6> <h6>Creds de management des switchs</h6>
{% can_create SwitchManagementCred%} {% can_create SwitchManagementCred%}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:add-switchmanagementcred' %}"><i class="fa fa-plus"></i> Ajouter un id/mdp de management switch</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:add-switchmanagementcred' %}"><i class="fa fa-plus"></i> Ajouter un id/mdp de management switch</a>
{% acl_end %} {% acl_end %}
<p> <p>
</p> </p>
{% if switchmanagementcred_list %}<span class="label label-success"> OK{% else %}<span class="label label-danger">Manquant{% endif %}</span> {% if switchmanagementcred_list %}<span class="label label-success"> OK{% else %}<span class="label label-danger">Manquant{% endif %}</span>
{% include "preferences/aff_switchmanagementcred.html" with switchmanagementcred_list=switchmanagementcred_list %} {% include "preferences/aff_switchmanagementcred.html" with switchmanagementcred_list=switchmanagementcred_list %}
</div> </div>
</div> </div>
<div class="panel panel-default" id="radius">
<div class="panel-heading" data-toggle="collapse" href="#collapse_radius">
<h4 class="panel-title"><a><i class="fa fa-circle"></i> {% trans "Radius preferences" %}</h4></a>
</div>
<div id="collapse_radius" class="panel-collapse panel-body collapse">
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'RadiusOption' %}">
<i class="fa fa-edit"></i>
{% trans "Edit" %}
</a>
{% include "preferences/aff_radiusoptions.html" %}
</div>
</div>
<div class="panel panel-default" id="asso"> <div class="panel panel-default" id="asso">
<div class="panel-heading" data-toggle="collapse" href="#collapse_asso"> <div class="panel-heading" data-toggle="collapse" href="#collapse_asso">
<h4 class="panel-title"> <h4 class="panel-title">
<a><i class="fa fa-at"></i> {% trans "Information about the organisation" %}</a> <a><i class="fa fa-at"></i> {% trans "Information about the organisation" %}</a>
</h4> </h4>
</div> </div>
<div id="collapse_asso" class="panel-collapse panel-body collapse"> <div id="collapse_asso" class="panel-collapse panel-body collapse">
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'AssoOption' %}"> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'AssoOption' %}">
<i class="fa fa-edit"></i> <i class="fa fa-edit"></i>
{% trans "Edit" %} {% trans "Edit" %}
</a> </a>
<p></p> <p></p>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>{% trans "Name" %}</th> <th>{% trans "Name" %}</th>
<td>{{ assooptions.name }}</td> <td>{{ assooptions.name }}</td>
<th>{% trans "SIRET number" %}</th> <th>{% trans "SIRET number" %}</th>
<td>{{ assooptions.siret }}</td> <td>{{ assooptions.siret }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Address" %}</th> <th>{% trans "Address" %}</th>
<td>{{ assooptions.adresse1 }}<br> <td>{{ assooptions.adresse1 }}<br>
{{ assooptions.adresse2 }} {{ assooptions.adresse2 }}
</td> </td>
<th>{% trans "Contact email address" %}</th> <th>{% trans "Contact email address" %}</th>
<td>{{ assooptions.contact }}</td> <td>{{ assooptions.contact }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Telephone number" %}</th> <th>{% trans "Telephone number" %}</th>
<td>{{ assooptions.telephone }}</td> <td>{{ assooptions.telephone }}</td>
<th>{% trans "Usual name" %}</th> <th>{% trans "Usual name" %}</th>
<td>{{ assooptions.pseudo }}</td> <td>{{ assooptions.pseudo }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "User object of the organisation" %}</th> <th>{% trans "User object of the organisation" %}</th>
<td>{{ assooptions.utilisateur_asso }}</td> <td>{{ assooptions.utilisateur_asso }}</td>
<th>{% trans "Description of the organisation" %}</th> <th>{% trans "Description of the organisation" %}</th>
<td>{{ assooptions.description|safe }}</td> <td>{{ assooptions.description|safe }}</td>
</tr> </tr>
</table> </table>
</div>
</div> </div>
</div>
<div class="panel panel-default" id="mail"> <div class="panel panel-default" id="mail">
<div class="panel-heading" data-toggle="collapse" href="#collapse_mail"> <div class="panel-heading" data-toggle="collapse" href="#collapse_mail">
<h4 class="panel-title"> <h4 class="panel-title">
<a><i class="fa fa-comment"></i> Message pour les mails</a> <a><i class="fa fa-comment"></i> Message pour les mails</a>
</h4> </h4>
</div> </div>
<div id="collapse_mail" class="panel-collapse panel-body collapse"> <div id="collapse_mail" class="panel-collapse panel-body collapse">
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'MailMessageOption' %}"> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:edit-options' 'MailMessageOption' %}">
@ -346,26 +357,26 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</a> </a>
<p></p> <p></p>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>{% trans "Welcome email (in French)" %}</th> <th>{% trans "Welcome email (in French)" %}</th>
<td>{{ mailmessageoptions.welcome_mail_fr|safe }}</td> <td>{{ mailmessageoptions.welcome_mail_fr|safe }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Welcome email (in English)" %}</th> <th>{% trans "Welcome email (in English)" %}</th>
<td>{{ mailmessageoptions.welcome_mail_en|safe }}</td> <td>{{ mailmessageoptions.welcome_mail_en|safe }}</td>
</tr> </tr>
</table> </table>
</div> </div>
</div> </div>
<div class="panel panel-default" id="rappels"> <div class="panel panel-default" id="rappels">
<div class="panel-heading" data-toggle="collapse" href="#collapse_rappels"> <div class="panel-heading" data-toggle="collapse" href="#collapse_rappels">
<h4 class="panel-title"> <h4 class="panel-title">
<a><i class="fa fa-bell"></i> Options pour le mail de fin d'adhésion</a> <a><i class="fa fa-bell"></i> Options pour le mail de fin d'adhésion</a>
</h4> </h4>
</div> </div>
<div id="collapse_rappels" class="panel-collapse panel-body collapse"> <div id="collapse_rappels" class="panel-collapse panel-body collapse">
{% can_create preferences.Reminder%} {% can_create preferences.Reminder%}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:add-reminder' %}"><i class="fa fa-plus"></i> Ajouter un rappel</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:add-reminder' %}"><i class="fa fa-plus"></i> Ajouter un rappel</a>
@ -373,13 +384,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% acl_end %} {% acl_end %}
{% include "preferences/aff_reminder.html" with reminder_list=reminder_list %} {% include "preferences/aff_reminder.html" with reminder_list=reminder_list %}
</div> </div>
</div> </div>
<div class="panel panel-default" id="services"> <div class="panel panel-default" id="services">
<div class="panel-heading" data-toggle="collapse" href="#collapse_services"> <div class="panel-heading" data-toggle="collapse" href="#collapse_services">
<h4 class="panel-title"> <h4 class="panel-title">
<a><i class="fa fa-home"></i> {% trans "List of services and homepage preferences" %}</a> <a><i class="fa fa-home"></i> {% trans "List of services and homepage preferences" %}</a>
</h4> </h4>
</div> </div>
<div id="collapse_services" class="panel-collapse panel-body collapse"> <div id="collapse_services" class="panel-collapse panel-body collapse">
@ -390,16 +401,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% acl_end %} {% acl_end %}
{% include "preferences/aff_service.html" with service_list=service_list %} {% include "preferences/aff_service.html" with service_list=service_list %}
</div> </div>
</div> </div>
<div class="panel panel-default" id="contact"> <div class="panel panel-default" id="contact">
<div class="panel-heading" data-toggle="collapse" href="#collapse_contact"> <div class="panel-heading" data-toggle="collapse" href="#collapse_contact">
<h4 class="panel-title"> <h4 class="panel-title">
<a><i class="fa fa-list-ul"></i> {% trans "List of contact email addresses" %}</a> <a><i class="fa fa-list-ul"></i> {% trans "List of contact email addresses" %}</a>
</h4> </h4>
</div> </div>
<div id="collapse_contact" class="panel-collapse panel-body collapse"> <div id="collapse_contact" class="panel-collapse panel-body collapse">
{% can_create preferences.MailContact %} {% can_create preferences.MailContact %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:add-mailcontact' %}"><i class="fa fa-plus"></i>{% trans "Add an address" %}</a> <a class="btn btn-primary btn-sm" role="button" href="{% url 'preferences:add-mailcontact' %}"><i class="fa fa-plus"></i>{% trans "Add an address" %}</a>
@ -408,12 +419,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<p></p> <p></p>
{% include "preferences/aff_mailcontact.html" with mailcontact_list=mailcontact_list %} {% include "preferences/aff_mailcontact.html" with mailcontact_list=mailcontact_list %}
</div> </div>
</div> </div>
<div class="panel panel-default" id="social"> <div class="panel panel-default" id="social">
<div class="panel-heading" data-toggle="collapse" href="#collapse_social"> <div class="panel-heading" data-toggle="collapse" href="#collapse_social">
<h4 class="panel-title"> <h4 class="panel-title">
<a><i class="fa fa-facebook"></i><i class="fa fa-twitter"></i> Réseaux sociaux</a> <a><i class="fa fa-facebook"></i><i class="fa fa-twitter"></i> Réseaux sociaux</a>
</h4> </h4>
</div> </div>
<div id="collapse_social" class="panel-collapse panel-body collapse"> <div id="collapse_social" class="panel-collapse panel-body collapse">
@ -423,20 +434,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% trans "Edit" %} {% trans "Edit" %}
</a> </a>
<p></p> <p></p>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>{% trans "Twitter account URL" %}</th> <th>{% trans "Twitter account URL" %}</th>
<td>{{ homeoptions.twitter_url }}</td> <td>{{ homeoptions.twitter_url }}</td>
<th>{% trans "Twitter account name" %}</th> <th>{% trans "Twitter account name" %}</th>
<td>{{ homeoptions.twitter_account_name }}</td> <td>{{ homeoptions.twitter_account_name }}</td>
</tr> </tr>
<tr> <tr>
<th>{% trans "Facebook account URL" %}</th> <th>{% trans "Facebook account URL" %}</th>
<td>{{ homeoptions.facebook_url }}</td> <td>{{ homeoptions.facebook_url }}</td>
</tr> </tr>
</table> </table>
</div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View file

@ -37,6 +37,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<form class="form" method="post" enctype="multipart/form-data"> <form class="form" method="post" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{% massive_bootstrap_form options 'utilisateur_asso,automatic_provision_switchs' %} {% massive_bootstrap_form options 'utilisateur_asso,automatic_provision_switchs' %}
{% if formset %}
{{ formset.management_form }}
{% for f in formset %}
{% bootstrap_form f %}
{% endfor %}
{% endif %}
{% trans "Edit" as tr_edit %} {% trans "Edit" as tr_edit %}
{% bootstrap_button tr_edit button_type="submit" icon='ok' button_class='btn-success' %} {% bootstrap_button tr_edit button_type="submit" icon='ok' button_class='btn-success' %}
</form> </form>

View file

@ -66,6 +66,11 @@ urlpatterns = [
views.edit_options, views.edit_options,
name='edit-options' name='edit-options'
), ),
url(
r'^edit_options/(?P<section>RadiusOption)$',
views.edit_options,
name='edit-options'
),
url(r'^add_service/$', views.add_service, name='add-service'), url(r'^add_service/$', views.add_service, name='add-service'),
url( url(
r'^edit_service/(?P<serviceid>[0-9]+)$', r'^edit_service/(?P<serviceid>[0-9]+)$',

View file

@ -62,7 +62,8 @@ from .models import (
HomeOption, HomeOption,
Reminder, Reminder,
RadiusKey, RadiusKey,
SwitchManagementCred SwitchManagementCred,
RadiusOption,
) )
from . import models from . import models
from . import forms from . import forms
@ -86,6 +87,7 @@ def display_options(request):
reminder_list = Reminder.objects.all() reminder_list = Reminder.objects.all()
radiuskey_list = RadiusKey.objects.all() radiuskey_list = RadiusKey.objects.all()
switchmanagementcred_list = SwitchManagementCred.objects.all() switchmanagementcred_list = SwitchManagementCred.objects.all()
radiusoptions, _ = RadiusOption.objects.get_or_create()
return form({ return form({
'useroptions': useroptions, 'useroptions': useroptions,
'machineoptions': machineoptions, 'machineoptions': machineoptions,
@ -99,6 +101,7 @@ def display_options(request):
'reminder_list': reminder_list, 'reminder_list': reminder_list,
'radiuskey_list' : radiuskey_list, 'radiuskey_list' : radiuskey_list,
'switchmanagementcred_list': switchmanagementcred_list, 'switchmanagementcred_list': switchmanagementcred_list,
'radiusoptions' : radiusoptions,
}, 'preferences/display_preferences.html', request) }, 'preferences/display_preferences.html', request)
@ -134,7 +137,9 @@ def edit_options(request, section):
messages.success(request, _("The preferences were edited.")) messages.success(request, _("The preferences were edited."))
return redirect(reverse('preferences:display-options')) return redirect(reverse('preferences:display-options'))
return form( return form(
{'options': options}, {
'options': options,
},
'preferences/edit_preferences.html', 'preferences/edit_preferences.html',
request request
) )

View file

@ -384,8 +384,8 @@ class AdherentCreationForm(AdherentForm):
# Checkbox for GTU # Checkbox for GTU
gtu_check = forms.BooleanField(required=True) gtu_check = forms.BooleanField(required=True)
gtu_check.label = mark_safe("{} <a href='/media/{}' download='CGU'>{}</a>{}".format( #gtu_check.label = mark_safe("{} <a href='/media/{}' download='CGU'>{}</a>{}".format(
_("I commit to accept the"), GeneralOption.get_cached_value('GTU'), _("General Terms of Use"), _("."))) # _("I commit to accept the"), GeneralOption.get_cached_value('GTU'), _("General Terms of Use"), _(".")))
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(AdherentCreationForm, self).__init__(*args, **kwargs) super(AdherentCreationForm, self).__init__(*args, **kwargs)