diff --git a/preferences/forms.py b/preferences/forms.py index d2bede7c..e216ea1f 100644 --- a/preferences/forms.py +++ b/preferences/forms.py @@ -44,7 +44,8 @@ from .models import ( SwitchManagementCred, RadiusOption, CotisationsOption, - DocumentTemplate + DocumentTemplate, + RadiusAttribute ) from topologie.models import Switch @@ -411,3 +412,33 @@ class DelDocumentTemplateForm(FormRevMixin, Form): self.fields['document_templates'].queryset = instances else: self.fields['document_templates'].queryset = Banque.objects.all() + + +class RadiusAttributeForm(ModelForm): + """Edit and add RADIUS attributes.""" + class Meta: + model = RadiusAttribute + fields = '__all__' + + def __init__(self, *args, **kwargs): + prefix = kwargs.pop('prefix', self.Meta.model.__name__) + super(RadiusAttributeForm, self).__init__(*args, prefix=prefix, **kwargs) + + +class DelRadiusAttributeForm(Form): + """Delete RADIUS attributes""" + attributes = forms.ModelMultipleChoiceField( + queryset=RadiusAttribute.objects.none(), + label=_("Current attributes"), + widget=forms.CheckboxSelectMultiple + ) + + def __init__(self, *args, **kwargs): + instances = kwargs.pop('instances', None) + super(DelServiceForm, self).__init__(*args, **kwargs) + if instances: + self.fields['attributes'].queryset = instances + else: + self.fields['attributes'].queryset = Attributes.objects.all() + + diff --git a/preferences/migrations/0062_radius_attributes.py b/preferences/migrations/0062_radius_attributes.py new file mode 100644 index 00000000..05a34493 --- /dev/null +++ b/preferences/migrations/0062_radius_attributes.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.23 on 2019-09-09 14:13 +from __future__ import unicode_literals + +from django.db import migrations, models +import re2o.mixins + + +class Migration(migrations.Migration): + + dependencies = [ + ('preferences', '0061_optionaluser_allow_archived_connexion'), + ] + + operations = [ + migrations.CreateModel( + name='RadiusAttribute', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('attribute', models.CharField(help_text='See http://freeradius.org/rfc/attributes.html', max_length=255, verbose_name='Attribute')), + ('operator', models.CharField(choices=[('=', '='), (':=', ':='), ('==', '=='), ('+=', '+='), ('!=', '!='), ('>', '>'), ('>=', '>='), ('<', '<'), ('<=', '<='), ('=~', '=~'), ('!~', '!~'), ('=*', '=*'), ('!*', '!*')], default=':=', help_text='See https://wiki.freeradius.org/config/Operators', max_length=2, verbose_name='Operator')), + ('value', models.CharField(max_length=255, verbose_name='Value')), + ('comment', models.TextField(blank=True, default='', help_text='Use this field to document this attribute.', verbose_name='Comment')), + ], + options={ + 'verbose_name': 'RADIUS attribute', + 'verbose_name_plural': 'RADIUS attributes', + }, + bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model), + ), + migrations.AddField( + model_name='radiusoption', + name='banned_attributes', + field=models.ManyToManyField(blank=True, help_text='Answer attributes for banned users.', related_name='banned_attribute', to='preferences.RadiusAttribute', verbose_name='Banned attributes.'), + ), + migrations.AddField( + model_name='radiusoption', + name='non_member_attributes', + field=models.ManyToManyField(blank=True, help_text='Answer attributes for non members.', related_name='non_member_attribute', to='preferences.RadiusAttribute', verbose_name='Non member attributes.'), + ), + migrations.AddField( + model_name='radiusoption', + name='ok_attributes', + field=models.ManyToManyField(blank=True, help_text='Answer attributes for accepted users.', related_name='ok_attribute', to='preferences.RadiusAttribute', verbose_name='Accepted users attributes.'), + ), + migrations.AddField( + model_name='radiusoption', + name='unknown_machine_attributes', + field=models.ManyToManyField(blank=True, help_text='Answer attributes for unknown machines.', related_name='unknown_machine_attribute', to='preferences.RadiusAttribute', verbose_name='Unknown machines attributes.'), + ), + migrations.AddField( + model_name='radiusoption', + name='unknown_port_attributes', + field=models.ManyToManyField(blank=True, help_text='Answer attributes for unknown ports.', related_name='unknown_port_attribute', to='preferences.RadiusAttribute', verbose_name='Unknown ports attributes.'), + ), + migrations.AddField( + model_name='radiusoption', + name='unknown_room_attributes', + field=models.ManyToManyField(blank=True, help_text='Answer attributes for unknown rooms.', related_name='unknown_room_attribute', to='preferences.RadiusAttribute', verbose_name='Unknown rooms attributes.'), + ), + ] diff --git a/preferences/models.py b/preferences/models.py index 98374e77..ea7e9dd5 100644 --- a/preferences/models.py +++ b/preferences/models.py @@ -591,6 +591,53 @@ class MailMessageOption(AclMixin, models.Model): verbose_name = _("email message options") +class RadiusAttribute(RevMixin, AclMixin, models.Model): + class Meta: + verbose_name = _("RADIUS attribute") + verbose_name_plural = _("RADIUS attributes") + + CHOICE_OPERATOR = ( + ('=' , '=' ), + (':=', ':='), + ('==', '=='), + ('+=', '+='), + ('!=', '!='), + ('>' , '>' ), + ('>=', '>='), + ('<' , '<' ), + ('<=', '<='), + ('=~', '=~'), + ('!~', '!~'), + ('=*', '=*'), + ('!*', '!*') + ) + attribute = models.CharField( + max_length=255, + verbose_name=_("Attribute"), + help_text=_("See http://freeradius.org/rfc/attributes.html"), + ) + operator = models.CharField( + max_length=2, + verbose_name=_("Operator"), + help_text=_("See https://wiki.freeradius.org/config/Operators"), + choices=CHOICE_OPERATOR, + default=':=' + ) + value = models.CharField( + max_length=255, + verbose_name=_("Value") + ) + comment = models.TextField( + verbose_name=_("Comment"), + help_text=_("Use this field to document this attribute."), + blank=True, + default="" + ) + + def __str__(self): + return ' '.join([self.attribute, self.operator, self.value]) + + class RadiusOption(AclMixin, PreferencesModel): class Meta: verbose_name = _("RADIUS policy") @@ -628,6 +675,13 @@ class RadiusOption(AclMixin, PreferencesModel): verbose_name=_("Unknown machines VLAN"), help_text=_("VLAN for unknown machines if not rejected") ) + unknown_machine_attributes = models.ManyToManyField( + RadiusAttribute, + related_name='unknown_machine_attribute', + blank=True, + verbose_name=_("Unknown machines attributes."), + help_text=_("Answer attributes for unknown machines."), + ) unknown_port = models.CharField( max_length=32, choices=CHOICE_POLICY, @@ -643,6 +697,13 @@ class RadiusOption(AclMixin, PreferencesModel): verbose_name=_("Unknown ports VLAN"), help_text=_("VLAN for unknown ports if not rejected") ) + unknown_port_attributes = models.ManyToManyField( + RadiusAttribute, + related_name='unknown_port_attribute', + blank=True, + verbose_name=_("Unknown ports attributes."), + help_text=_("Answer attributes for unknown ports."), + ) unknown_room = models.CharField( max_length=32, choices=CHOICE_POLICY, @@ -659,6 +720,13 @@ class RadiusOption(AclMixin, PreferencesModel): verbose_name=_("Unknown rooms VLAN"), help_text=_("VLAN for unknown rooms if not rejected") ) + unknown_room_attributes = models.ManyToManyField( + RadiusAttribute, + related_name='unknown_room_attribute', + blank=True, + verbose_name=_("Unknown rooms attributes."), + help_text=_("Answer attributes for unknown rooms."), + ) non_member = models.CharField( max_length=32, choices=CHOICE_POLICY, @@ -674,6 +742,13 @@ class RadiusOption(AclMixin, PreferencesModel): verbose_name=_("Non members VLAN"), help_text=_("VLAN for non members if not rejected") ) + non_member_attributes = models.ManyToManyField( + RadiusAttribute, + related_name='non_member_attribute', + blank=True, + verbose_name=_("Non member attributes."), + help_text=_("Answer attributes for non members."), + ) banned = models.CharField( max_length=32, choices=CHOICE_POLICY, @@ -689,6 +764,13 @@ class RadiusOption(AclMixin, PreferencesModel): verbose_name=_("Banned users VLAN"), help_text=_("VLAN for banned users if not rejected") ) + banned_attributes = models.ManyToManyField( + RadiusAttribute, + related_name='banned_attribute', + blank=True, + verbose_name=_("Banned attributes."), + help_text=_("Answer attributes for banned users."), + ) vlan_decision_ok = models.OneToOneField( 'machines.Vlan', on_delete=models.PROTECT, @@ -696,6 +778,13 @@ class RadiusOption(AclMixin, PreferencesModel): blank=True, null=True ) + ok_attributes = models.ManyToManyField( + RadiusAttribute, + related_name='ok_attribute', + blank=True, + verbose_name=_("Accepted users attributes."), + help_text=_("Answer attributes for accepted users."), + ) def default_invoice(): diff --git a/preferences/templates/preferences/aff_radiusattributes.html b/preferences/templates/preferences/aff_radiusattributes.html new file mode 100644 index 00000000..8edd8b93 --- /dev/null +++ b/preferences/templates/preferences/aff_radiusattributes.html @@ -0,0 +1,50 @@ +{% 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 %} + +
{% trans "Attribute" %} | +{% trans "Comment" %} | ++ |
---|---|---|
{{ attribute }} | +{{ attribute.comment }} | ++ {% can_edit attribute%} + {% include 'buttons/edit.html' with href='preferences:edit-radiusattribute' id=attribute.id %} + {% acl_end %} + {% can_delete attribute %} + {% include 'buttons/suppr.html' with href='preferences:del-radiusattribute' id=attribute.id %} + {% acl_end %} + {% history_button attribute %} + | +