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

Merge branch 'roles' into 'dev'

Ajout les Roles

See merge request federez/re2o!182
This commit is contained in:
chirac 2018-08-04 08:24:30 +02:00
commit 42f3c32cef
13 changed files with 388 additions and 45 deletions

View file

@ -120,3 +120,11 @@ Don't forget to run migrations, several settings previously in the `preferences`
in their own Payment models. in their own Payment models.
To have a closer look on how the payments works, please go to the wiki. To have a closer look on how the payments works, please go to the wiki.
## MR 182: Add role models
Adds the Role model.
You need to ensure that your database character set is utf-8.
```sql
ALTER DATABASE re2o CHARACTER SET utf8;
```

View file

@ -338,6 +338,7 @@ class OptionalMachineSerializer(NamespacedHMSerializer):
class OptionalTopologieSerializer(NamespacedHMSerializer): class OptionalTopologieSerializer(NamespacedHMSerializer):
"""Serialize `preferences.models.OptionalTopologie` objects. """Serialize `preferences.models.OptionalTopologie` objects.
""" """
class Meta: class Meta:
model = preferences.OptionalTopologie model = preferences.OptionalTopologie
fields = ('radius_general_policy', 'vlan_decision_ok', fields = ('radius_general_policy', 'vlan_decision_ok',

View file

@ -42,6 +42,7 @@ from .models import (
SshFp, SshFp,
Nas, Nas,
Service, Service,
Role,
OuverturePort, OuverturePort,
Ipv6List, Ipv6List,
OuverturePortList, OuverturePortList,
@ -146,6 +147,11 @@ class ServiceAdmin(VersionAdmin):
""" Admin view of a ServiceAdmin object """ """ Admin view of a ServiceAdmin object """
list_display = ('service_type', 'min_time_regen', 'regular_time_regen') list_display = ('service_type', 'min_time_regen', 'regular_time_regen')
class RoleAdmin(VersionAdmin):
""" Admin view of a RoleAdmin object """
pass
admin.site.register(Machine, MachineAdmin) admin.site.register(Machine, MachineAdmin)
admin.site.register(MachineType, MachineTypeAdmin) admin.site.register(MachineType, MachineTypeAdmin)
@ -162,6 +168,7 @@ admin.site.register(IpList, IpListAdmin)
admin.site.register(Interface, InterfaceAdmin) admin.site.register(Interface, InterfaceAdmin)
admin.site.register(Domain, DomainAdmin) admin.site.register(Domain, DomainAdmin)
admin.site.register(Service, ServiceAdmin) admin.site.register(Service, ServiceAdmin)
admin.site.register(Role, RoleAdmin)
admin.site.register(Vlan, VlanAdmin) admin.site.register(Vlan, VlanAdmin)
admin.site.register(Ipv6List, Ipv6ListAdmin) admin.site.register(Ipv6List, Ipv6ListAdmin)
admin.site.register(Nas, NasAdmin) admin.site.register(Nas, NasAdmin)

View file

@ -37,6 +37,7 @@ from __future__ import unicode_literals
from django.forms import ModelForm, Form from django.forms import ModelForm, Form
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _l
from re2o.field_permissions import FieldPermissionFormMixin from re2o.field_permissions import FieldPermissionFormMixin
from re2o.mixins import FormRevMixin from re2o.mixins import FormRevMixin
@ -53,6 +54,7 @@ from .models import (
Txt, Txt,
DName, DName,
Ns, Ns,
Role,
Service, Service,
Vlan, Vlan,
Srv, Srv,
@ -497,6 +499,38 @@ class DelNasForm(FormRevMixin, Form):
self.fields['nas'].queryset = Nas.objects.all() self.fields['nas'].queryset = Nas.objects.all()
class RoleForm(FormRevMixin, ModelForm):
"""Add and edit role."""
class Meta:
model = Role
fields = '__all__'
def __init__(self, *args, **kwargs):
prefix = kwargs.pop('prefix', self.Meta.model.__name__)
super(RoleForm, self).__init__(*args, prefix=prefix, **kwargs)
self.fields['servers'].queryset = (Interface.objects.all()
.select_related(
'domain__extension'
))
class DelRoleForm(FormRevMixin, Form):
"""Deletion of one or several roles."""
role = forms.ModelMultipleChoiceField(
queryset=Role.objects.none(),
label=_l("Current roles"),
widget=forms.CheckboxSelectMultiple
)
def __init__(self, *args, **kwargs):
instances = kwargs.pop('instances', None)
super(DelRoleForm, self).__init__(*args, **kwargs)
if instances:
self.fields['role'].queryset = instances
else:
self.fields['role'].queryset = Role.objects.all()
class ServiceForm(FormRevMixin, ModelForm): class ServiceForm(FormRevMixin, ModelForm):
"""Ajout et edition d'une classe de service : dns, dhcp, etc""" """Ajout et edition d'une classe de service : dns, dhcp, etc"""
class Meta: class Meta:

View file

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2018-06-23 14:07
from __future__ import unicode_literals
from django.db import migrations, models
import re2o.mixins
class Migration(migrations.Migration):
dependencies = [
('machines', '0085_sshfingerprint'),
]
operations = [
migrations.CreateModel(
name='Role',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('role_type', models.CharField(max_length=255, unique=True)),
('servers', models.ManyToManyField(to='machines.Interface')),
('specific_role', models.CharField(blank=True, choices=[('dhcp-server', 'DHCP server'), ('switch-conf-server', 'Switches configuration server'), ('dns-recursif-server', 'Recursive DNS server'), ('ntp-server', 'NTP server'), ('radius-server', 'Radius server'), ('log-server', 'Log server'), ('ldap-master-server', 'LDAP master server'), ('ldap-backup-server', 'LDAP backup server'), ('smtp-server', 'SMTP server'), ('postgresql-server', 'postgreSQL server'), ('mysql-server', 'mySQL server'), ('sql-client', 'SQL client'), ('gateway', 'Gatewaw')], max_length=32, null=True))
],
options={'permissions': (('view_role', 'Can view a role.'),), 'verbose_name': 'Server role'},
bases=(re2o.mixins.RevMixin, re2o.mixins.AclMixin, models.Model),
),
]

View file

@ -42,6 +42,7 @@ from django.forms import ValidationError
from django.utils.functional import cached_property from django.utils.functional import cached_property
from django.utils import timezone from django.utils import timezone
from django.core.validators import MaxValueValidator from django.core.validators import MaxValueValidator
from django.utils.translation import ugettext_lazy as _l
from macaddress.fields import MACAddressField from macaddress.fields import MACAddressField
@ -158,7 +159,7 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
user_request, user_request,
*args, *args,
**kwargs **kwargs
)[0]): )[0]):
return False, (u"Vous ne pouvez pas éditer une machine " return False, (u"Vous ne pouvez pas éditer une machine "
"d'un autre user que vous sans droit") "d'un autre user que vous sans droit")
return True, None return True, None
@ -176,7 +177,7 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
user_request, user_request,
*args, *args,
**kwargs **kwargs
)[0]): )[0]):
return False, (u"Vous ne pouvez pas éditer une machine " return False, (u"Vous ne pouvez pas éditer une machine "
"d'un autre user que vous sans droit") "d'un autre user que vous sans droit")
return True, None return True, None
@ -338,10 +339,10 @@ class IpType(RevMixin, AclMixin, models.Model):
return return
else: else:
for ipv6 in Ipv6List.objects.filter( for ipv6 in Ipv6List.objects.filter(
interface__in=Interface.objects.filter( interface__in=Interface.objects.filter(
type__in=MachineType.objects.filter(ip_type=self) type__in=MachineType.objects.filter(ip_type=self)
) )
): ):
ipv6.check_and_replace_prefix(prefix=self.prefix_v6) ipv6.check_and_replace_prefix(prefix=self.prefix_v6)
def clean(self): def clean(self):
@ -713,7 +714,7 @@ class Srv(RevMixin, AclMixin, models.Model):
choices=( choices=(
(TCP, 'TCP'), (TCP, 'TCP'),
(UDP, 'UDP'), (UDP, 'UDP'),
), ),
default=TCP, default=TCP,
) )
extension = models.ForeignKey('Extension', on_delete=models.PROTECT) extension = models.ForeignKey('Extension', on_delete=models.PROTECT)
@ -1047,7 +1048,7 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
user_request, user_request,
*args, *args,
**kwargs **kwargs
)[0]): )[0]):
return False, (u"Vous ne pouvez pas éditer une machine " return False, (u"Vous ne pouvez pas éditer une machine "
"d'un autre user que vous sans droit") "d'un autre user que vous sans droit")
return True, None return True, None
@ -1064,7 +1065,7 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
user_request, user_request,
*args, *args,
**kwargs **kwargs
)[0]): )[0]):
return False, (u"Vous ne pouvez pas éditer une machine " return False, (u"Vous ne pouvez pas éditer une machine "
"d'un autre user que vous sans droit") "d'un autre user que vous sans droit")
return True, None return True, None
@ -1165,7 +1166,7 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
user_request, user_request,
*args, *args,
**kwargs **kwargs
)[0]): )[0]):
return False, (u"Vous ne pouvez pas éditer une machine " return False, (u"Vous ne pouvez pas éditer une machine "
"d'un autre user que vous sans droit") "d'un autre user que vous sans droit")
return True, None return True, None
@ -1182,7 +1183,7 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
user_request, user_request,
*args, *args,
**kwargs **kwargs
)[0]): )[0]):
return False, (u"Vous ne pouvez pas éditer une machine " return False, (u"Vous ne pouvez pas éditer une machine "
"d'un autre user que vous sans droit") "d'un autre user que vous sans droit")
return True, None return True, None
@ -1358,11 +1359,11 @@ class Domain(RevMixin, AclMixin, models.Model):
return False, (u"Vous ne pouvez pas ajouter un alias à une " return False, (u"Vous ne pouvez pas ajouter un alias à une "
"machine d'un autre user que vous sans droit") "machine d'un autre user que vous sans droit")
if Domain.objects.filter( if Domain.objects.filter(
cname__in=Domain.objects.filter( cname__in=Domain.objects.filter(
interface_parent__in=(interface.machine.user interface_parent__in=(interface.machine.user
.user_interfaces()) .user_interfaces())
) )
).count() >= max_lambdauser_aliases: ).count() >= max_lambdauser_aliases:
return False, (u"Vous avez atteint le maximum d'alias " return False, (u"Vous avez atteint le maximum d'alias "
"autorisés que vous pouvez créer vous même " "autorisés que vous pouvez créer vous même "
"(%s) " % max_lambdauser_aliases) "(%s) " % max_lambdauser_aliases)
@ -1441,6 +1442,75 @@ class IpList(RevMixin, AclMixin, models.Model):
return self.ipv4 return self.ipv4
class Role(RevMixin, AclMixin, models.Model):
"""Define the role of a machine.
Allow automated generation of the server configuration.
"""
ROLE = (
('dhcp-server', _l('DHCP server')),
('switch-conf-server', _l('Switches configuration server')),
('dns-recursif-server', _l('Recursive DNS server')),
('ntp-server', _l('NTP server')),
('radius-server', _l('Radius server')),
('log-server', _l('Log server')),
('ldap-master-server', _l('LDAP master server')),
('ldap-backup-server', _l('LDAP backup server')),
('smtp-server', _l('SMTP server')),
('postgresql-server', _l('postgreSQL server')),
('mysql-server', _l('mySQL server')),
('sql-client', _l('SQL client')),
('gateway', _l('Gatewaw')),
)
role_type = models.CharField(max_length=255, unique=True)
servers = models.ManyToManyField('Interface')
specific_role = models.CharField(
choices=ROLE,
null=True,
blank=True,
max_length=32,
)
class Meta:
permissions = (
("view_role", _l("Can view a role.")),
)
verbose_name = _l("Server role")
@classmethod
def get_instance(cls, roleid, *_args, **_kwargs):
"""Get the Role instance with roleid.
Args:
roleid: The id
Returns:
The role.
"""
return cls.objects.get(pk=roleid)
@classmethod
def interface_for_roletype(cls, roletype):
"""Return interfaces for a roletype"""
return Interface.objects.filter(
role=cls.objects.filter(specific_role=roletype)
)
@classmethod
def all_interfaces_for_roletype(cls, roletype):
"""Return all interfaces for a roletype"""
return Interface.objects.filter(
machine__interface__role=cls.objects.filter(specific_role=roletype)
)
def save(self, *args, **kwargs):
super(Role, self).save(*args, **kwargs)
def __str__(self):
return str(self.role_type)
class Service(RevMixin, AclMixin, models.Model): class Service(RevMixin, AclMixin, models.Model):
""" Definition d'un service (dhcp, dns, etc)""" """ Definition d'un service (dhcp, dns, etc)"""
PRETTY_NAME = "Services à générer (dhcp, dns, etc)" PRETTY_NAME = "Services à générer (dhcp, dns, etc)"
@ -1471,8 +1541,8 @@ class Service(RevMixin, AclMixin, models.Model):
""" Django ne peut créer lui meme les relations manytomany avec table """ Django ne peut créer lui meme les relations manytomany avec table
intermediaire explicite""" intermediaire explicite"""
for serv in servers.exclude( for serv in servers.exclude(
pk__in=Interface.objects.filter(service=self) pk__in=Interface.objects.filter(service=self)
): ):
link = Service_link(service=self, server=serv) link = Service_link(service=self, server=serv)
link.save() link.save()
Service_link.objects.filter(service=self).exclude(server__in=servers)\ Service_link.objects.filter(service=self).exclude(server__in=servers)\
@ -1630,7 +1700,7 @@ class OuverturePort(RevMixin, AclMixin, models.Model):
choices=( choices=(
(TCP, 'TCP'), (TCP, 'TCP'),
(UDP, 'UDP'), (UDP, 'UDP'),
), ),
default=TCP, default=TCP,
) )
io = models.CharField( io = models.CharField(
@ -1638,7 +1708,7 @@ class OuverturePort(RevMixin, AclMixin, models.Model):
choices=( choices=(
(IN, 'IN'), (IN, 'IN'),
(OUT, 'OUT'), (OUT, 'OUT'),
), ),
default=OUT, default=OUT,
) )

View file

@ -0,0 +1,54 @@
{% 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 © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
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 acl %}
{% load i18n %}
{% load logs_extra %}
<table class="table table-striped">
<thead>
<tr>
<th>{% trans "Role name" %}</th>
<th>{% trans "Specific role" %}</th>
<th>{% trans "Servers" %}</th>
<th></th>
<th></th>
</tr>
</thead>
{% for role in role_list %}
<tr>
<td>{{ role.role_type }}</td>
<td>{{ role.specific_role }}</td>
<td>{% for serv in role.servers.all %}{{ serv }}, {% endfor %}</td>
<td class="text-right">
{% can_edit role %}
{% include 'buttons/edit.html' with href='machines:edit-role' id=role.id %}
{% acl_end %}
{% history_button role %}
</td>
</tr>
{% endfor %}
</table>

View file

@ -0,0 +1,42 @@
{% extends "machines/sidebar.html" %}
{% 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 © 2017 Gabriel Détraz
Copyright © 2017 Goulven Kermarec
Copyright © 2017 Augustin Lemesle
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 bootstrap3 %}
{% load acl %}
{% load i18n %}
{% block title %}Machines{% endblock %}
{% block content %}
<h2>{% trans "Roles list" %}</h2>
{% can_create Role %}
<a class="btn btn-primary btn-sm" role="button" href="{% url 'machines:add-role' %}"><i class="fa fa-plus"></i> {% trans "Add role"%}</a>
{% acl_end %}
<a class="btn btn-danger btn-sm" role="button" href="{% url 'machines:del-role' %}"><i class="fa fa-trash"></i> {% trans "Delete one or several roles" %}</a>
{% include "machines/aff_role.html" with role_list=role_list %}
<br />
<br />
{% endblock %}

View file

@ -72,6 +72,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% if sshfpform %} {% if sshfpform %}
{% bootstrap_form_errors sshfpform %} {% bootstrap_form_errors sshfpform %}
{% endif %} {% endif %}
{% if roleform %}
{% bootstrap_form_errors roleform %}
{% endif %}
{% if vlanform %} {% if vlanform %}
{% bootstrap_form_errors vlanform %} {% bootstrap_form_errors vlanform %}
{% endif %} {% endif %}
@ -148,6 +151,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<h3>Service</h3> <h3>Service</h3>
{% massive_bootstrap_form serviceform 'servers' %} {% massive_bootstrap_form serviceform 'servers' %}
{% endif %} {% endif %}
{% if roleform %}
<h3>Role</h3>
{% massive_bootstrap_form roleform 'servers' %}
{% endif %}
{% if vlanform %} {% if vlanform %}
<h3>Vlan</h3> <h3>Vlan</h3>
{% bootstrap_form vlanform %} {% bootstrap_form vlanform %}

View file

@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% endcomment %} {% endcomment %}
{% load acl %} {% load acl %}
{% load i18n %}
{% block sidebar %} {% block sidebar %}
{% can_view_all Machine %} {% can_view_all Machine %}
@ -68,6 +69,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Services (dhcp, dns...) Services (dhcp, dns...)
</a> </a>
{% acl_end %} {% acl_end %}
{% can_view_all Role %}
<a class="list-group-item list-group-item-info" href="{% url "machines:index-role" %}">
<i class="fa fa-list-ul"></i>
{% trans "Server roles" %}
</a>
{% acl_end %}
{% can_view_all OuverturePortList %} {% can_view_all OuverturePortList %}
<a class="list-group-item list-group-item-info" href="{% url "machines:index-portlist" %}"> <a class="list-group-item list-group-item-info" href="{% url "machines:index-portlist" %}">
<i class="fa fa-list-ul"></i> <i class="fa fa-list-ul"></i>

View file

@ -21,7 +21,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., # with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""machines.urls """machines.urls
The defined URLs for the Cotisations app The defined URLs for the Machines app
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
@ -125,6 +125,12 @@ urlpatterns = [
name='edit-service'), name='edit-service'),
url(r'^del_service/$', views.del_service, name='del-service'), url(r'^del_service/$', views.del_service, name='del-service'),
url(r'^index_service/$', views.index_service, name='index-service'), url(r'^index_service/$', views.index_service, name='index-service'),
url(r'^add_role/$', views.add_role, name='add-role'),
url(r'^edit_role/(?P<roleid>[0-9]+)$',
views.edit_role,
name='edit-role'),
url(r'^del_role/$', views.del_role, name='del-role'),
url(r'^index_role/$', views.index_role, name='index-role'),
url(r'^add_vlan/$', views.add_vlan, name='add-vlan'), url(r'^add_vlan/$', views.add_vlan, name='add-vlan'),
url(r'^edit_vlan/(?P<vlanid>[0-9]+)$', views.edit_vlan, name='edit-vlan'), url(r'^edit_vlan/(?P<vlanid>[0-9]+)$', views.edit_vlan, name='edit-vlan'),
url(r'^del_vlan/$', views.del_vlan, name='del-vlan'), url(r'^del_vlan/$', views.del_vlan, name='del-vlan'),

View file

@ -40,6 +40,7 @@ from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import ProtectedError, F from django.db.models import ProtectedError, F
from django.forms import modelformset_factory from django.forms import modelformset_factory
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from django.utils.translation import ugettext as _
from rest_framework.renderers import JSONRenderer from rest_framework.renderers import JSONRenderer
@ -101,6 +102,8 @@ from .forms import (
DelMxForm, DelMxForm,
VlanForm, VlanForm,
DelVlanForm, DelVlanForm,
RoleForm,
DelRoleForm,
ServiceForm, ServiceForm,
DelServiceForm, DelServiceForm,
SshFpForm, SshFpForm,
@ -122,6 +125,7 @@ from .models import (
Mx, Mx,
Ns, Ns,
Domain, Domain,
Role,
Service, Service,
Service_link, Service_link,
Vlan, Vlan,
@ -178,14 +182,14 @@ def generate_ipv4_engine(is_type_tt):
""" """
return ( return (
'new Bloodhound( {{' 'new Bloodhound( {{'
'datumTokenizer: Bloodhound.tokenizers.obj.whitespace( "value" ),' 'datumTokenizer: Bloodhound.tokenizers.obj.whitespace( "value" ),'
'queryTokenizer: Bloodhound.tokenizers.whitespace,' 'queryTokenizer: Bloodhound.tokenizers.whitespace,'
'local: choices_ipv4[ $( "#{type_id}" ).val() ],' 'local: choices_ipv4[ $( "#{type_id}" ).val() ],'
'identify: function( obj ) {{ return obj.key; }}' 'identify: function( obj ) {{ return obj.key; }}'
'}} )' '}} )'
).format( ).format(
type_id=f_type_id(is_type_tt) type_id=f_type_id(is_type_tt)
) )
def generate_ipv4_match_func(is_type_tt): def generate_ipv4_match_func(is_type_tt):
@ -193,17 +197,17 @@ def generate_ipv4_match_func(is_type_tt):
""" """
return ( return (
'function(q, sync) {{' 'function(q, sync) {{'
'if (q === "") {{' 'if (q === "") {{'
'var first = choices_ipv4[$("#{type_id}").val()].slice(0, 5);' 'var first = choices_ipv4[$("#{type_id}").val()].slice(0, 5);'
'first = first.map( function (obj) {{ return obj.key; }} );' 'first = first.map( function (obj) {{ return obj.key; }} );'
'sync(engine_ipv4.get(first));' 'sync(engine_ipv4.get(first));'
'}} else {{' '}} else {{'
'engine_ipv4.search(q, sync);' 'engine_ipv4.search(q, sync);'
'}}'
'}}' '}}'
).format( '}}'
type_id=f_type_id(is_type_tt) ).format(
) type_id=f_type_id(is_type_tt)
)
def generate_ipv4_mbf_param(form_obj, is_type_tt): def generate_ipv4_mbf_param(form_obj, is_type_tt):
@ -1141,6 +1145,65 @@ def del_alias(request, interface, interfaceid):
) )
@login_required
@can_create(Role)
def add_role(request):
""" View used to add a Role object """
role = RoleForm(request.POST or None)
if role.is_valid():
role.save()
messages.success(request, "Cet enregistrement role a été ajouté")
return redirect(reverse('machines:index-role'))
return form(
{'roleform': role, 'action_name': 'Créer'},
'machines/machine.html',
request
)
@login_required
@can_edit(Role)
def edit_role(request, role_instance, **_kwargs):
""" View used to edit a Role object """
role = RoleForm(request.POST or None, instance=role_instance)
if role.is_valid():
if role.changed_data:
role.save()
messages.success(request, _("Role updated"))
return redirect(reverse('machines:index-role'))
return form(
{'roleform': role, 'action_name': _('Edit')},
'machines/machine.html',
request
)
@login_required
@can_delete_set(Role)
def del_role(request, instances):
""" View used to delete a Service object """
role = DelRoleForm(request.POST or None, instances=instances)
if role.is_valid():
role_dels = role.cleaned_data['role']
for role_del in role_dels:
try:
role_del.delete()
messages.success(request, _("The role has been deleted."))
except ProtectedError:
messages.error(
request,
(_("Error: The following role cannot be deleted: %(role)")
% {'role': role_del}
)
)
return redirect(reverse('machines:index-role'))
return form(
{'roleform': role, 'action_name': _('Delete')},
'machines/machine.html',
request
)
@login_required @login_required
@can_create(Service) @can_create(Service)
def add_service(request): def add_service(request):
@ -1481,6 +1544,21 @@ def index_ipv6(request, interface, interfaceid):
) )
@login_required
@can_view_all(Role)
def index_role(request):
""" View used to display the list of existing roles """
role_list = (Role.objects
.prefetch_related(
'servers__domain__extension'
).all())
return render(
request,
'machines/index_role.html',
{'role_list': role_list}
)
@login_required @login_required
@can_view_all(Service) @can_view_all(Service)
def index_service(request): def index_service(request):
@ -1570,12 +1648,12 @@ def add_portlist(request):
""" View used to add a port policy """ """ View used to add a port policy """
port_list = EditOuverturePortListForm(request.POST or None) port_list = EditOuverturePortListForm(request.POST or None)
port_formset = modelformset_factory( port_formset = modelformset_factory(
OuverturePort, OuverturePort,
fields=('begin', 'end', 'protocole', 'io'), fields=('begin', 'end', 'protocole', 'io'),
extra=0, extra=0,
can_delete=True, can_delete=True,
min_num=1, min_num=1,
validate_min=True, validate_min=True,
)(request.POST or None, queryset=OuverturePort.objects.none()) )(request.POST or None, queryset=OuverturePort.objects.none())
if port_list.is_valid() and port_formset.is_valid(): if port_list.is_valid() and port_formset.is_valid():
pl = port_list.save() pl = port_list.save()
@ -1622,11 +1700,12 @@ def configure_ports(request, interface_instance, **_kwargs):
) )
## Framework Rest # Framework Rest
class JSONResponse(HttpResponse): class JSONResponse(HttpResponse):
""" Class to build a JSON response. Used for API """ """ Class to build a JSON response. Used for API """
def __init__(self, data, **kwargs): def __init__(self, data, **kwargs):
content = JSONRenderer().render(data) content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json' kwargs['content_type'] = 'application/json'

View file

@ -79,6 +79,7 @@ from django.contrib.contenttypes.models import ContentType
register = template.Library() register = template.Library()
def get_model(model_name): def get_model(model_name):
"""Retrieve the model object from its name""" """Retrieve the model object from its name"""
splitted = model_name.split('.') splitted = model_name.split('.')