mirror of https://gitlab.federez.net/re2o/re2o
81 changed files with 3107 additions and 1023 deletions
Binary file not shown.
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2018-12-29 14:22 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('cotisations', '0035_notepayment'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='custominvoice', |
|||
name='remark', |
|||
field=models.TextField(blank=True, null=True, verbose_name='Remark'), |
|||
), |
|||
] |
|||
@ -0,0 +1,28 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2018-12-29 21:03 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('cotisations', '0036_custominvoice_remark'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.CreateModel( |
|||
name='CostEstimate', |
|||
fields=[ |
|||
('custominvoice_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='cotisations.CustomInvoice')), |
|||
('validity', models.DurationField(verbose_name='Period of validity')), |
|||
('final_invoice', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='origin_cost_estimate', to='cotisations.CustomInvoice')), |
|||
], |
|||
options={ |
|||
'permissions': (('view_costestimate', 'Can view a cost estimate object'),), |
|||
}, |
|||
bases=('cotisations.custominvoice',), |
|||
), |
|||
] |
|||
@ -0,0 +1,31 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2018-12-31 22:57 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('cotisations', '0037_costestimate'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='costestimate', |
|||
name='final_invoice', |
|||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='origin_cost_estimate', to='cotisations.CustomInvoice'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='costestimate', |
|||
name='validity', |
|||
field=models.DurationField(help_text='DD HH:MM:SS', verbose_name='Period of validity'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='custominvoice', |
|||
name='paid', |
|||
field=models.BooleanField(default=False, verbose_name='Paid'), |
|||
), |
|||
] |
|||
@ -0,0 +1,101 @@ |
|||
{% 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 %} |
|||
{% load design %} |
|||
|
|||
<div class="table-responsive"> |
|||
{% if cost_estimate_list.paginator %} |
|||
{% include 'pagination.html' with list=cost_estimate_list%} |
|||
{% endif %} |
|||
|
|||
<table class="table table-striped"> |
|||
<thead> |
|||
<tr> |
|||
<th> |
|||
{% trans "Recipient" as tr_recip %} |
|||
{% include 'buttons/sort.html' with prefix='invoice' col='user' text=tr_user %} |
|||
</th> |
|||
<th>{% trans "Designation" %}</th> |
|||
<th>{% trans "Total price" %}</th> |
|||
<th> |
|||
{% trans "Payment method" as tr_payment_method %} |
|||
{% include 'buttons/sort.html' with prefix='invoice' col='payement' text=tr_payment_method %} |
|||
</th> |
|||
<th> |
|||
{% trans "Date" as tr_date %} |
|||
{% include 'buttons/sort.html' with prefix='invoice' col='date' text=tr_date %} |
|||
</th> |
|||
<th> |
|||
{% trans "Validity" as tr_validity %} |
|||
{% include 'buttons/sort.html' with prefix='invoice' col='validity' text=tr_validity %} |
|||
</th> |
|||
<th> |
|||
{% trans "Cost estimate ID" as tr_estimate_id %} |
|||
{% include 'buttons/sort.html' with prefix='invoice' col='id' text=tr_estimate_id %} |
|||
</th> |
|||
<th> |
|||
{% trans "Invoice created" as tr_invoice_created%} |
|||
{% include 'buttons/sort.html' with prefix='invoice' col='paid' text=tr_invoice_created %} |
|||
</th> |
|||
<th></th> |
|||
<th></th> |
|||
</tr> |
|||
</thead> |
|||
{% for estimate in cost_estimate_list %} |
|||
<tr> |
|||
<td>{{ estimate.recipient }}</td> |
|||
<td>{{ estimate.name }}</td> |
|||
<td>{{ estimate.prix_total }}</td> |
|||
<td>{{ estimate.payment }}</td> |
|||
<td>{{ estimate.date }}</td> |
|||
<td>{{ estimate.validity }}</td> |
|||
<td>{{ estimate.id }}</td> |
|||
<td> |
|||
{% if estimate.final_invoice %} |
|||
<a href="{% url 'cotisations:edit-custom-invoice' estimate.final_invoice.pk %}"><i style="color: #1ECA18;" class="fa fa-check"></i></a> |
|||
{% else %} |
|||
<i style="color: #D10115;" class="fa fa-times"></i>' |
|||
{% endif %} |
|||
</td> |
|||
<td> |
|||
{% can_edit estimate %} |
|||
{% include 'buttons/edit.html' with href='cotisations:edit-cost-estimate' id=estimate.id %} |
|||
{% acl_end %} |
|||
{% history_button estimate %} |
|||
{% include 'buttons/suppr.html' with href='cotisations:del-cost-estimate' id=estimate.id %} |
|||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:cost-estimate-to-invoice' estimate.id %}"> |
|||
<i class="fa fa-file"></i> |
|||
</a> |
|||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'cotisations:cost-estimate-pdf' estimate.id %}"> |
|||
<i class="fa fa-file-pdf-o"></i> {% trans "PDF" %} |
|||
</a> |
|||
</td> |
|||
</tr> |
|||
{% endfor %} |
|||
</table> |
|||
|
|||
{% if custom_invoice_list.paginator %} |
|||
{% include 'pagination.html' with list=custom_invoice_list %} |
|||
{% endif %} |
|||
</div> |
|||
@ -0,0 +1,36 @@ |
|||
{% extends "cotisations/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 acl %} |
|||
{% load i18n %} |
|||
|
|||
{% block title %}{% trans "Cost estimates" %}{% endblock %} |
|||
|
|||
{% block content %} |
|||
<h2>{% trans "Cost estimates list" %}</h2> |
|||
{% can_create CostEstimate %} |
|||
{% include "buttons/add.html" with href='cotisations:new-cost-estimate'%} |
|||
{% acl_end %} |
|||
{% include 'cotisations/aff_cost_estimate.html' %} |
|||
{% endblock %} |
|||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2018-12-24 14:00 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('machines', '0096_auto_20181013_1417'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='extension', |
|||
name='dnssec', |
|||
field=models.BooleanField(default=False, help_text='Should the zone be signed with DNSSEC'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2019-01-02 23:45 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('machines', '0097_extension_dnssec'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='role', |
|||
name='specific_role', |
|||
field=models.CharField(blank=True, choices=[('dhcp-server', 'DHCP server'), ('switch-conf-server', 'Switches configuration server'), ('dns-recursif-server', 'Recursive DNS server'), ('dns-recursive-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', 'Gateway')], max_length=32, null=True), |
|||
), |
|||
] |
|||
@ -0,0 +1,26 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2019-01-02 23:45 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
def migrate(apps, schema_editor): |
|||
Role = apps.get_model('machines', 'Role') |
|||
|
|||
for role in Role.objects.filter(specific_role='dns-recursif-server'): |
|||
role.specific_role = 'dns-recursive-server' |
|||
role.save() |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('machines', '0098_auto_20190102_1745'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.RunPython(migrate), |
|||
] |
|||
|
|||
|
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2019-01-02 23:53 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('machines', '0099_role_recursive_dns'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='role', |
|||
name='specific_role', |
|||
field=models.CharField(blank=True, choices=[('dhcp-server', 'DHCP server'), ('switch-conf-server', 'Switches configuration server'), ('dns-recursive-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', 'Gateway')], max_length=32, null=True), |
|||
), |
|||
] |
|||
Binary file not shown.
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2018-11-14 16:46 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('preferences', '0053_optionaluser_self_change_room'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='generaloption', |
|||
name='main_site_url', |
|||
field=models.URLField(default='http://re2o.example.org', max_length=255), |
|||
), |
|||
] |
|||
@ -0,0 +1,84 @@ |
|||
# -*- 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 |
|||
|
|||
|
|||
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'), |
|||
), |
|||
] |
|||
@ -0,0 +1,36 @@ |
|||
# -*- 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() |
|||
|
|||
def revert_radius(apps, schema_editor): |
|||
pass |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('machines', '0095_auto_20180919_2225'), |
|||
('preferences', '0055_generaloption_main_site_url'), |
|||
('preferences', '0056_1_radiusoption'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.RunPython(create_radius_policy, revert_radius), |
|||
] |
|||
@ -0,0 +1,31 @@ |
|||
# -*- 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 |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('machines', '0095_auto_20180919_2225'), |
|||
('preferences', '0055_generaloption_main_site_url'), |
|||
('preferences', '0056_2_radiusoption'), |
|||
] |
|||
|
|||
operations = [ |
|||
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', |
|||
), |
|||
] |
|||
@ -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_3_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'), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2019-01-05 17:15 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('preferences', '0056_4_radiusoption'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='optionaluser', |
|||
name='all_users_active', |
|||
field=models.BooleanField(default=False, help_text='If True, all new created and connected users are active. If False, only when a valid registration has been paid'), |
|||
), |
|||
] |
|||
@ -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> |
|||
|
|||
@ -0,0 +1,267 @@ |
|||
# -*- mode: python; coding: utf-8 -*- |
|||
# 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 Gabriel Détraz |
|||
# |
|||
# 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. |
|||
|
|||
# -*- coding: utf-8 -*- |
|||
""" |
|||
Regroupe les fonctions transversales utiles |
|||
|
|||
Et non corrélées/dépendantes des autres applications |
|||
""" |
|||
|
|||
import smtplib |
|||
|
|||
from django.utils.translation import ugettext_lazy as _ |
|||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger |
|||
|
|||
from re2o.settings import EMAIL_HOST |
|||
|
|||
|
|||
# Mapping of srtftime format for better understanding |
|||
# https://docs.python.org/3.6/library/datetime.html#strftime-strptime-behavior |
|||
datetime_mapping={ |
|||
'%a': '%a', |
|||
'%A': '%A', |
|||
'%w': '%w', |
|||
'%d': 'dd', |
|||
'%b': '%b', |
|||
'%B': '%B', |
|||
'%m': 'mm', |
|||
'%y': 'yy', |
|||
'%Y': 'yyyy', |
|||
'%H': 'HH', |
|||
'%I': 'HH(12h)', |
|||
'%p': 'AMPM', |
|||
'%M': 'MM', |
|||
'%S': 'SS', |
|||
'%f': 'µµ', |
|||
'%z': 'UTC(+/-HHMM)', |
|||
'%Z': 'UTC(TZ)', |
|||
'%j': '%j', |
|||
'%U': 'ww', |
|||
'%W': 'ww', |
|||
'%c': '%c', |
|||
'%x': '%x', |
|||
'%X': '%X', |
|||
'%%': '%%', |
|||
} |
|||
|
|||
|
|||
def smtp_check(local_part): |
|||
"""Return True if the local_part is already taken |
|||
False if available""" |
|||
try: |
|||
srv = smtplib.SMTP(EMAIL_HOST) |
|||
srv.putcmd("vrfy", local_part) |
|||
reply_code = srv.getreply()[0] |
|||
srv.close() |
|||
if reply_code in [250, 252]: |
|||
return True, _("This domain is already taken") |
|||
except: |
|||
return True, _("Smtp unreachable") |
|||
return False, None |
|||
|
|||
|
|||
def convert_datetime_format(format): |
|||
i=0 |
|||
new_format = "" |
|||
while i < len(format): |
|||
if format[i] == '%': |
|||
char = format[i:i+2] |
|||
new_format += datetime_mapping.get(char, char) |
|||
i += 2 |
|||
else: |
|||
new_format += format[i] |
|||
i += 1 |
|||
return new_format |
|||
|
|||
|
|||
def get_input_formats_help_text(input_formats): |
|||
"""Returns a help text about the possible input formats""" |
|||
if len(input_formats) > 1: |
|||
help_text_template="Format: {main} {more}" |
|||
else: |
|||
help_text_template="Format: {main}" |
|||
more_text_template="<i class=\"fa fa-question-circle\" title=\"{}\"></i>" |
|||
help_text = help_text_template.format( |
|||
main=convert_datetime_format(input_formats[0]), |
|||
more=more_text_template.format( |
|||
'\n'.join(map(convert_datetime_format, input_formats)) |
|||
) |
|||
) |
|||
return help_text |
|||
|
|||
|
|||
class SortTable: |
|||
""" Class gathering uselful stuff to sort the colums of a table, according |
|||
to the column and order requested. It's used with a dict of possible |
|||
values and associated model_fields """ |
|||
|
|||
# All the possible possible values |
|||
# The naming convention is based on the URL or the views function |
|||
# The syntax to describe the sort to apply is a dict where the keys are |
|||
# the url value and the values are a list of model field name to use to |
|||
# order the request. They are applied in the order they are given. |
|||
# A 'default' might be provided to specify what to do if the requested col |
|||
# doesn't match any keys. |
|||
|
|||
USERS_INDEX = { |
|||
'user_name': ['name'], |
|||
'user_surname': ['surname'], |
|||
'user_pseudo': ['pseudo'], |
|||
'user_room': ['room'], |
|||
'default': ['state', 'pseudo'] |
|||
} |
|||
USERS_INDEX_BAN = { |
|||
'ban_user': ['user__pseudo'], |
|||
'ban_start': ['date_start'], |
|||
'ban_end': ['date_end'], |
|||
'default': ['-date_end'] |
|||
} |
|||
USERS_INDEX_WHITE = { |
|||
'white_user': ['user__pseudo'], |
|||
'white_start': ['date_start'], |
|||
'white_end': ['date_end'], |
|||
'default': ['-date_end'] |
|||
} |
|||
USERS_INDEX_SCHOOL = { |
|||
'school_name': ['name'], |
|||
'default': ['name'] |
|||
} |
|||
MACHINES_INDEX = { |
|||
'machine_name': ['name'], |
|||
'default': ['pk'] |
|||
} |
|||
COTISATIONS_INDEX = { |
|||
'cotis_user': ['user__pseudo'], |
|||
'cotis_paiement': ['paiement__moyen'], |
|||
'cotis_date': ['date'], |
|||
'cotis_id': ['id'], |
|||
'default': ['-date'] |
|||
} |
|||
COTISATIONS_CUSTOM = { |
|||
'invoice_date': ['date'], |
|||
'invoice_id': ['id'], |
|||
'invoice_recipient': ['recipient'], |
|||
'invoice_address': ['address'], |
|||
'invoice_payment': ['payment'], |
|||
'default': ['-date'] |
|||
} |
|||
COTISATIONS_CONTROL = { |
|||
'control_name': ['user__adherent__name'], |
|||
'control_surname': ['user__surname'], |
|||
'control_paiement': ['paiement'], |
|||
'control_date': ['date'], |
|||
'control_valid': ['valid'], |
|||
'control_control': ['control'], |
|||
'control_id': ['id'], |
|||
'control_user-id': ['user__id'], |
|||
'default': ['-date'] |
|||
} |
|||
TOPOLOGIE_INDEX = { |
|||
'switch_dns': ['interface__domain__name'], |
|||
'switch_ip': ['interface__ipv4__ipv4'], |
|||
'switch_loc': ['switchbay__name'], |
|||
'switch_ports': ['number'], |
|||
'switch_stack': ['stack__name'], |
|||
'default': ['switchbay', 'stack', 'stack_member_id'] |
|||
} |
|||
TOPOLOGIE_INDEX_PORT = { |
|||
'port_port': ['port'], |
|||
'port_room': ['room__name'], |
|||
'port_interface': ['machine_interface__domain__name'], |
|||
'port_related': ['related__switch__name'], |
|||
'port_radius': ['radius'], |
|||
'port_vlan': ['vlan_force__name'], |
|||
'default': ['port'] |
|||
} |
|||
TOPOLOGIE_INDEX_ROOM = { |
|||
'room_name': ['name'], |
|||
'default': ['name'] |
|||
} |
|||
TOPOLOGIE_INDEX_BUILDING = { |
|||
'building_name': ['name'], |
|||
'default': ['name'] |
|||
} |
|||
TOPOLOGIE_INDEX_BORNE = { |
|||
'ap_name': ['interface__domain__name'], |
|||
'ap_ip': ['interface__ipv4__ipv4'], |
|||
'ap_mac': ['interface__mac_address'], |
|||
'default': ['interface__domain__name'] |
|||
} |
|||
TOPOLOGIE_INDEX_STACK = { |
|||
'stack_name': ['name'], |
|||
'stack_id': ['stack_id'], |
|||
'default': ['stack_id'], |
|||
} |
|||
TOPOLOGIE_INDEX_MODEL_SWITCH = { |
|||
'model-switch_name': ['reference'], |
|||
'model-switch_contructor': ['constructor__name'], |
|||
'default': ['reference'], |
|||
} |
|||
TOPOLOGIE_INDEX_SWITCH_BAY = { |
|||
'switch-bay_name': ['name'], |
|||
'switch-bay_building': ['building__name'], |
|||
'default': ['name'], |
|||
} |
|||
TOPOLOGIE_INDEX_CONSTRUCTOR_SWITCH = { |
|||
'constructor-switch_name': ['name'], |
|||
'default': ['name'], |
|||
} |
|||
LOGS_INDEX = { |
|||
'sum_date': ['revision__date_created'], |
|||
'default': ['-revision__date_created'], |
|||
} |
|||
LOGS_STATS_LOGS = { |
|||
'logs_author': ['user__name'], |
|||
'logs_date': ['date_created'], |
|||
'default': ['-date_created'] |
|||
} |
|||
|
|||
@staticmethod |
|||
def sort(request, col, order, values): |
|||
""" Check if the given values are possible and add .order_by() and |
|||
a .reverse() as specified according to those values """ |
|||
fields = values.get(col, None) |
|||
if not fields: |
|||
fields = values.get('default', []) |
|||
request = request.order_by(*fields) |
|||
if values.get(col, None) and order == 'desc': |
|||
return request.reverse() |
|||
else: |
|||
return request |
|||
|
|||
|
|||
def re2o_paginator(request, query_set, pagination_number): |
|||
"""Paginator script for list display in re2o. |
|||
:request: |
|||
:query_set: Query_set to paginate |
|||
:pagination_number: Number of entries to display""" |
|||
paginator = Paginator(query_set, pagination_number) |
|||
page = request.GET.get('page') |
|||
try: |
|||
results = paginator.page(page) |
|||
except PageNotAnInteger: |
|||
# If page is not an integer, deliver first page. |
|||
results = paginator.page(1) |
|||
except EmptyPage: |
|||
# If page is out of range (e.g. 9999), deliver last page of results. |
|||
results = paginator.page(paginator.num_pages) |
|||
return results |
|||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,33 @@ |
|||
// 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 Alexandre Iooss
|
|||
//
|
|||
// 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.
|
|||
|
|||
// This script makes URL hash controls Bootstrap collapse
|
|||
// e.g. if there is #information in the URL
|
|||
// then the collapse with id "information" will be open.
|
|||
|
|||
$(document).ready(function () { |
|||
if(location.hash != null && location.hash !== ""){ |
|||
// Open the collapse corresponding to URL hash
|
|||
$(location.hash + '.collapse').collapse('show'); |
|||
} else { |
|||
// Open default collapse
|
|||
$('.collapse-default.collapse').collapse('show'); |
|||
} |
|||
}); |
|||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,66 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2018-12-30 17:19 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
import re2o.mixins |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('topologie', '0066_modelswitch_commercial_name'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.CreateModel( |
|||
name='ModuleOnSwitch', |
|||
fields=[ |
|||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|||
('slot', models.CharField(help_text='Slot on switch', max_length=15, verbose_name='Slot')), |
|||
], |
|||
options={ |
|||
'verbose_name': 'link between switchs and modules', |
|||
'permissions': (('view_moduleonswitch', 'Can view a moduleonswitch object'),), |
|||
}, |
|||
bases=(re2o.mixins.AclMixin, re2o.mixins.RevMixin, models.Model), |
|||
), |
|||
migrations.CreateModel( |
|||
name='ModuleSwitch', |
|||
fields=[ |
|||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|||
('reference', models.CharField(help_text='Reference of a module', max_length=255, verbose_name='Module reference')), |
|||
('comment', models.CharField(blank=True, help_text='Comment', max_length=255, null=True, verbose_name='Comment')), |
|||
], |
|||
options={ |
|||
'verbose_name': 'Module of a switch', |
|||
'permissions': (('view_moduleswitch', 'Can view a module object'),), |
|||
}, |
|||
bases=(re2o.mixins.AclMixin, re2o.mixins.RevMixin, models.Model), |
|||
), |
|||
migrations.AddField( |
|||
model_name='modelswitch', |
|||
name='is_itself_module', |
|||
field=models.BooleanField(default=False, help_text='Does the switch, itself, considered as a module'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='modelswitch', |
|||
name='is_modular', |
|||
field=models.BooleanField(default=False, help_text='Is this switch model modular'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='moduleonswitch', |
|||
name='module', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='topologie.ModuleSwitch'), |
|||
), |
|||
migrations.AddField( |
|||
model_name='moduleonswitch', |
|||
name='switch', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='topologie.Switch'), |
|||
), |
|||
migrations.AlterUniqueTogether( |
|||
name='moduleonswitch', |
|||
unique_together=set([('slot', 'switch')]), |
|||
), |
|||
] |
|||
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2019-01-02 23:58 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('topologie', '0067_auto_20181230_1819'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='modelswitch', |
|||
name='is_itself_module', |
|||
field=models.BooleanField(default=False, help_text='Is the switch, itself, considered as a module'), |
|||
), |
|||
] |
|||
@ -0,0 +1,110 @@ |
|||
{% 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 logs_extra %} |
|||
{% load i18n %} |
|||
|
|||
{% if module_list.paginator %} |
|||
{% include "pagination.html" with list=module_list %} |
|||
{% endif %} |
|||
|
|||
<table class="table table-striped"> |
|||
<thead> |
|||
<tr> |
|||
<th>{% trans "Reference" %}</th> |
|||
<th>{% trans "Comment" %}</th> |
|||
<th>{% trans "Switchs" %}</th> |
|||
<th></th> |
|||
</tr> |
|||
</thead> |
|||
{% for module in module_list %} |
|||
<tr> |
|||
<td>{{ module.reference }}</td> |
|||
<td>{{ module.comment }}</td> |
|||
<td> |
|||
{% for module_switch in module.moduleonswitch_set.all %} |
|||
<b>Slot</b> {{ module_switch.slot }} <b>of</b> {{ module_switch.switch }} |
|||
{% can_edit module_switch %} |
|||
<a class="btn btn-primary btn-xs" role="button" title={% trans "Edit" %} href="{% url 'topologie:edit-module-on' module_switch.id %}"> |
|||
<i class="fa fa-edit"></i> |
|||
</a> |
|||
{% acl_end %} |
|||
{% can_delete module_switch %} |
|||
<a class="btn btn-danger btn-xs" role="button" title={% trans "Delete" %} href="{% url 'topologie:del-module-on' module_switch.id %}"> |
|||
<i class="fa fa-trash"></i> |
|||
</a> |
|||
{% acl_end %} |
|||
<br> |
|||
{% endfor %} |
|||
</td> |
|||
<td class="text-right"> |
|||
{% can_edit module %} |
|||
<a class="btn btn-primary btn-sm" role="button" title={% trans "Add" %} href="{% url 'topologie:add-module-on' %}"> |
|||
<i class="fa fa-plus"></i> |
|||
</a> |
|||
<a class="btn btn-primary btn-sm" role="button" title={% trans "Edit" %} href="{% url 'topologie:edit-module' module.id %}"> |
|||
<i class="fa fa-edit"></i> |
|||
</a> |
|||
{% acl_end %} |
|||
{% history_button module %} |
|||
{% can_delete module %} |
|||
<a class="btn btn-danger btn-sm" role="button" title={% trans "Delete" %} href="{% url 'topologie:del-module' module.id %}"> |
|||
<i class="fa fa-trash"></i> |
|||
</a> |
|||
{% acl_end %} |
|||
</td> |
|||
</tr> |
|||
{% endfor %} |
|||
</table> |
|||
|
|||
{% if module_list.paginator %} |
|||
{% include "pagination.html" with list=module_list %} |
|||
{% endif %} |
|||
|
|||
<h4>{% trans "All modular switchs" %}</h4> |
|||
|
|||
<table class="table table-striped"> |
|||
<thead> |
|||
<th>{% trans "Switch" %}</th> |
|||
<th>{% trans "Reference" %}</th> |
|||
<th>{% trans "Slot" %}</th> |
|||
<tbody> |
|||
{% for switch in modular_switchs %} |
|||
{% if switch.list_modules %} |
|||
<tr class="info"> |
|||
<td colspan="4"> |
|||
{{ switch }} |
|||
</td> |
|||
</tr> |
|||
{% for module in switch.list_modules %} |
|||
<tr> |
|||
<td></td> |
|||
<td>{{ module.1 }}</td> |
|||
<td>{{ module.0 }}</td> |
|||
</tr> |
|||
{% endfor %} |
|||
{% endif %} |
|||
{% endfor %} |
|||
</table> |
|||
@ -0,0 +1,43 @@ |
|||
{% extends "topologie/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 %}{% trans "Topology" %}{% endblock %} |
|||
|
|||
{% block content %} |
|||
<h2>{% trans "Modules of switchs" %}</h2> |
|||
{% can_create ModuleSwitch %} |
|||
<a class="btn btn-primary btn-sm" role="button" href="{% url 'topologie:add-module' %}"><i class="fa fa-plus"></i>{% trans " Add a module" %}</a> |
|||
<hr> |
|||
{% acl_end %} |
|||
{% include "topologie/aff_modules.html" with module_list=module_list modular_switchs=modular_switchs %} |
|||
<br /> |
|||
<br /> |
|||
<br /> |
|||
{% endblock %} |
|||
|
|||
Binary file not shown.
@ -0,0 +1,20 @@ |
|||
# -*- coding: utf-8 -*- |
|||
# Generated by Django 1.10.7 on 2018-12-28 19:39 |
|||
from __future__ import unicode_literals |
|||
|
|||
from django.db import migrations, models |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('users', '0078_auto_20181011_1405'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='adherent', |
|||
name='gpg_fingerprint', |
|||
field=models.CharField(blank=True, max_length=49, null=True), |
|||
), |
|||
] |
|||
Loading…
Reference in new issue