8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-22 19:33:11 +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.
@ -331,28 +327,46 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
"""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
- pas d'utilisateur dans la chambre : Rejet
(redirection web si disponible)
- utilisateur de la chambre banni ou désactivé : Rejet
(redirection web si disponible)
- utilisateur de la chambre non cotisant et non whiteslist:
Politique définie dans RadiusOption
- sinon passe à common (ci-dessous) - sinon passe à common (ci-dessous)
- mode common : - mode common :
- interface connue (macaddress): - interface connue (macaddress):
- utilisateur proprio non cotisant ou banni : VLAN_NOK - utilisateur proprio non cotisant / machine désactivée:
- user à jour : VLAN_OK 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 : - interface inconnue :
- register mac désactivé : VLAN_NOK - register mac désactivé : Politique définie
- register mac activé -> redirection vers webauth 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 (
sw_name,
room, room,
u'Machine non active / adherent non cotisant', u'Machine non active / adherent non cotisant',
VLAN_NOK, RadiusOption('non_member_vlan').vlan_id,
True) RadiusOption('non_member')!= RadiusOption.REJECT
## Si on choisi de placer les machines sur le vlan correspondant à leur type : )
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 (
sw_name,
room, room,
u"Ok, Reassignation de l'ipv4" + extra_log, u"Ok, Reassignation de l'ipv4" + extra_log,
DECISION_VLAN, DECISION_VLAN,
True) True
)
else: else:
return (sw_name, return (
sw_name,
room, room,
u'Machine OK' + extra_log, u'Machine OK' + extra_log,
DECISION_VLAN, DECISION_VLAN,
True) 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

@ -145,9 +145,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</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>
@ -180,9 +180,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</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>
@ -209,8 +209,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<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>
@ -221,9 +221,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% 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>
@ -285,17 +285,28 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% 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 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>
<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" %}
@ -330,9 +341,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</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>
@ -357,9 +368,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</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>
@ -373,10 +384,10 @@ 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>
@ -391,9 +402,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% 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>
@ -408,9 +419,9 @@ 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>
@ -436,7 +447,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</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)