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:
commit
42f3c32cef
13 changed files with 388 additions and 45 deletions
|
@ -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;
|
||||||
|
```
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
27
machines/migrations/0086_role.py
Normal file
27
machines/migrations/0086_role.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
54
machines/templates/machines/aff_role.html
Normal file
54
machines/templates/machines/aff_role.html
Normal 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>
|
||||||
|
|
42
machines/templates/machines/index_role.html
Normal file
42
machines/templates/machines/index_role.html
Normal 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 %}
|
||||||
|
|
|
@ -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 %}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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'),
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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('.')
|
||||||
|
|
Loading…
Reference in a new issue