Ce serveur Gitlab sera éteint le 30 juin 2020, pensez à migrer vos projets vers les serveurs gitlab-research.centralesupelec.fr et gitlab-student.centralesupelec.fr !

Commit e690292e authored by Gabriel Detraz's avatar Gabriel Detraz Committed by chirac

Merge branch 'master' into graph_topo

parents a975efd7 05bc645a
...@@ -43,11 +43,6 @@ import radiusd # Module magique freeradius (radiusd.py is dummy) ...@@ -43,11 +43,6 @@ import radiusd # Module magique freeradius (radiusd.py is dummy)
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
from django.db.models import Q from django.db.models import Q
from machines.models import Interface, IpList, Nas, Domain
from topologie.models import Port, Switch
from users.models import User
from preferences.models import OptionalTopologie
proj_path = "/var/www/re2o/" proj_path = "/var/www/re2o/"
# This is so Django knows where to find stuff. # This is so Django knows where to find stuff.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings")
...@@ -59,6 +54,12 @@ os.chdir(proj_path) ...@@ -59,6 +54,12 @@ os.chdir(proj_path)
# This is so models get loaded. # This is so models get loaded.
application = get_wsgi_application() application = get_wsgi_application()
from machines.models import Interface, IpList, Nas, Domain
from topologie.models import Port, Switch
from users.models import User
from preferences.models import OptionalTopologie
options, created = OptionalTopologie.objects.get_or_create() options, created = OptionalTopologie.objects.get_or_create()
VLAN_NOK = options.vlan_decision_nok.vlan_id VLAN_NOK = options.vlan_decision_nok.vlan_id
VLAN_OK = options.vlan_decision_ok.vlan_id VLAN_OK = options.vlan_decision_ok.vlan_id
......
...@@ -66,7 +66,11 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -66,7 +66,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<td><p class="text-success">{{utilisateur.last}}</p></td> <td><p class="text-success">{{utilisateur.last}}</p></td>
{% endif %} {% endif %}
<td> <td>
{% if droit != 'Superuser' %}
<a href="{% url 'users:del-group' utilisateur.id droit.id %}"> <a href="{% url 'users:del-group' utilisateur.id droit.id %}">
{% else %}
<a href="{% url 'users:del-superuser' utilisateur.id %}">
{% endif %}
<button type="button" class="btn btn-danger" aria-label="Left Align"> <button type="button" class="btn btn-danger" aria-label="Left Align">
<span class="fa fa-user-times" aria-hidden="true"></span> <span class="fa fa-user-times" aria-hidden="true"></span>
</button> </button>
...@@ -79,4 +83,4 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -79,4 +83,4 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</div> </div>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
\ No newline at end of file
...@@ -41,7 +41,7 @@ from django.urls import reverse ...@@ -41,7 +41,7 @@ from django.urls import reverse
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.db.models import Count, Max from django.db.models import Count, Max, F
from reversion.models import Revision from reversion.models import Revision
from reversion.models import Version, ContentType from reversion.models import Version, ContentType
...@@ -195,9 +195,7 @@ def revert_action(request, revision_id): ...@@ -195,9 +195,7 @@ def revert_action(request, revision_id):
@login_required @login_required
@can_view_all(IpList) @can_view_all(IpList, Interface, User)
@can_view_all(Interface)
@can_view_all(User)
def stats_general(request): def stats_general(request):
"""Statistiques générales affinées sur les ip, activées, utilisées par """Statistiques générales affinées sur les ip, activées, utilisées par
range, et les statistiques générales sur les users : users actifs, range, et les statistiques générales sur les users : users actifs,
...@@ -313,10 +311,7 @@ def stats_general(request): ...@@ -313,10 +311,7 @@ def stats_general(request):
@login_required @login_required
@can_view_app('users') @can_view_app('users', 'cotisations', 'machines', 'topologie')
@can_view_app('cotisations')
@can_view_app('machines')
@can_view_app('topologie')
def stats_models(request): def stats_models(request):
"""Statistiques générales, affiche les comptages par models: """Statistiques générales, affiche les comptages par models:
nombre d'users, d'écoles, de droits, de bannissements, nombre d'users, d'écoles, de droits, de bannissements,
...@@ -469,9 +464,14 @@ def stats_droits(request): ...@@ -469,9 +464,14 @@ def stats_droits(request):
for droit in ListRight.objects.all().select_related('group_ptr'): for droit in ListRight.objects.all().select_related('group_ptr'):
stats_list[droit] = droit.user_set.all().annotate( stats_list[droit] = droit.user_set.all().annotate(
num=Count('revision'), num=Count('revision'),
last=Max('revision__date_created') last=Max('revision__date_created'),
) )
stats_list['Superuser'] = User.objects.filter(is_superuser=True).annotate(
num=Count('revision'),
last=Max('revision__date_created'),
)
return render( return render(
request, request,
'logs/stats_droits.html', 'logs/stats_droits.html',
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-05-03 04:34
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('machines', '0079_auto_20180416_0107'),
]
operations = [
migrations.AlterField(
model_name='ns',
name='ns',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='machines.Domain'),
),
]
...@@ -613,7 +613,7 @@ class Ns(RevMixin, AclMixin, models.Model): ...@@ -613,7 +613,7 @@ class Ns(RevMixin, AclMixin, models.Model):
PRETTY_NAME = "Enregistrements NS" PRETTY_NAME = "Enregistrements NS"
zone = models.ForeignKey('Extension', on_delete=models.PROTECT) zone = models.ForeignKey('Extension', on_delete=models.PROTECT)
ns = models.OneToOneField('Domain', on_delete=models.PROTECT) ns = models.ForeignKey('Domain', on_delete=models.PROTECT)
class Meta: class Meta:
permissions = ( permissions = (
......
...@@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% include "pagination.html" with list=machines_list %} {% include "pagination.html" with list=machines_list %}
{% endif %} {% endif %}
<table class="table" id="machines_table"> <table class="table" id="machines_table">
<colgroup> <colgroup>
<col> <col>
......
...@@ -1272,12 +1272,7 @@ def index_nas(request): ...@@ -1272,12 +1272,7 @@ def index_nas(request):
@login_required @login_required
@can_view_all(SOA) @can_view_all(SOA, Mx, Ns, Txt, Srv, Extension)
@can_view_all(Mx)
@can_view_all(Ns)
@can_view_all(Txt)
@can_view_all(Srv)
@can_view_all(Extension)
def index_extension(request): def index_extension(request):
""" View displaying the list of existing extensions, the list of """ View displaying the list of existing extensions, the list of
existing SOA records, the list of existing MX records , the list of existing SOA records, the list of existing MX records , the list of
......
# coding:utf-8
# Re2o est un logiciel d'administration développé initiallement au rezometz. Il # 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 # se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics. # quelques clics.
......
...@@ -58,13 +58,8 @@ from . import forms ...@@ -58,13 +58,8 @@ from . import forms
@login_required @login_required
@can_view_all(OptionalUser) @can_view_all(OptionalUser, OptionalMachine, OptionalTopologie, GeneralOption,
@can_view_all(OptionalMachine) AssoOption, MailMessageOption, HomeOption)
@can_view_all(OptionalTopologie)
@can_view_all(GeneralOption)
@can_view_all(AssoOption)
@can_view_all(MailMessageOption)
@can_view_all(HomeOption)
def display_options(request): def display_options(request):
"""Vue pour affichage des options (en vrac) classé selon les models """Vue pour affichage des options (en vrac) classé selon les models
correspondants dans un tableau""" correspondants dans un tableau"""
...@@ -149,7 +144,11 @@ def add_service(request): ...@@ -149,7 +144,11 @@ def add_service(request):
@can_edit(Service) @can_edit(Service)
def edit_service(request, service_instance, **_kwargs): def edit_service(request, service_instance, **_kwargs):
"""Edition des services affichés sur la page d'accueil""" """Edition des services affichés sur la page d'accueil"""
service = ServiceForm(request.POST or None, request.FILES or None,instance=service_instance) service = ServiceForm(
request.POST or None,
request.FILES or None,
instance=service_instance
)
if service.is_valid(): if service.is_valid():
with transaction.atomic(), reversion.create_revision(): with transaction.atomic(), reversion.create_revision():
service.save() service.save()
......
This diff is collapsed.
...@@ -30,6 +30,14 @@ msgstr "" ...@@ -30,6 +30,14 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: settings.py:140
msgid "English"
msgstr "Anglais"
#: settings.py:141
msgid "French"
msgstr "Français"
#: templates/re2o/about.html:29 templates/re2o/about.html:35 #: templates/re2o/about.html:29 templates/re2o/about.html:35
msgid "About Re2o" msgid "About Re2o"
msgstr "A propos de Re2o" msgstr "A propos de Re2o"
...@@ -147,6 +155,10 @@ msgstr "" ...@@ -147,6 +155,10 @@ msgstr ""
msgid "Dependencies" msgid "Dependencies"
msgstr "Dépendances" msgstr "Dépendances"
#: templates/re2o/buttons/setlang.html:34
msgid "Translation in development"
msgstr "Traduction en développement"
#: views.py:172 #: views.py:172
msgid "No Git repository configured" msgid "No Git repository configured"
msgstr "Aucun repository git configuré" msgstr "Aucun repository git configuré"
......
...@@ -37,6 +37,7 @@ from __future__ import unicode_literals ...@@ -37,6 +37,7 @@ from __future__ import unicode_literals
import os import os
from .settings_local import * from .settings_local import *
from django.utils.translation import ugettext_lazy as _
# The root directory for the project # The root directory for the project
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
...@@ -135,6 +136,10 @@ LOCALE_PATHS = [ ...@@ -135,6 +136,10 @@ LOCALE_PATHS = [
# For translations outside of apps # For translations outside of apps
os.path.join(BASE_DIR, 'templates', 'locale').replace('\\', '/') os.path.join(BASE_DIR, 'templates', 'locale').replace('\\', '/')
] ]
LANGUAGES = [
('en', _('English')),
('fr', _('French'))
]
# Should use time zone ? # Should use time zone ?
USE_TZ = True USE_TZ = True
......
...@@ -55,6 +55,7 @@ urlpatterns = [ ...@@ -55,6 +55,7 @@ urlpatterns = [
url(r'^about/$', about_page, name='about'), url(r'^about/$', about_page, name='about'),
url('^logout/', auth_views.logout, {'next_page': '/'}), url('^logout/', auth_views.logout, {'next_page': '/'}),
url('^', include('django.contrib.auth.urls')), url('^', include('django.contrib.auth.urls')),
url(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^admin/', include(admin.site.urls)), url(r'^admin/', include(admin.site.urls)),
url(r'^users/', include('users.urls', namespace='users')), url(r'^users/', include('users.urls', namespace='users')),
url(r'^search/', include('search.urls', namespace='search')), url(r'^search/', include('search.urls', namespace='search')),
......
...@@ -44,6 +44,49 @@ from cotisations.models import Cotisation, Facture, Vente ...@@ -44,6 +44,49 @@ from cotisations.models import Cotisation, Facture, Vente
from machines.models import Interface, Machine from machines.models import Interface, Machine
from users.models import Adherent, User, Ban, Whitelist from users.models import Adherent, User, Ban, Whitelist
# 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 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 all_adherent(search_time=None): def all_adherent(search_time=None):
""" Fonction renvoyant tous les users adherents. Optimisee pour n'est """ Fonction renvoyant tous les users adherents. Optimisee pour n'est
...@@ -318,3 +361,19 @@ def remove_user_room(room): ...@@ -318,3 +361,19 @@ def remove_user_room(room):
return return
user.room = None user.room = None
user.save() user.save()
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
...@@ -26,6 +26,7 @@ from __future__ import unicode_literals ...@@ -26,6 +26,7 @@ from __future__ import unicode_literals
from django import forms from django import forms
from django.forms import Form from django.forms import Form
from re2o.utils import get_input_formats_help_text
CHOICES_USER = ( CHOICES_USER = (
('0', 'Actifs'), ('0', 'Actifs'),
...@@ -91,12 +92,17 @@ class SearchFormPlus(Form): ...@@ -91,12 +92,17 @@ class SearchFormPlus(Form):
s = forms.DateField( s = forms.DateField(
required=False, required=False,
label="Date de début", label="Date de début",
help_text='DD/MM/YYYY',
input_formats=['%d/%m/%Y']
) )
e = forms.DateField( e = forms.DateField(
required=False, required=False,
help_text='DD/MM/YYYY',
input_formats=['%d/%m/%Y'],
label="Date de fin" label="Date de fin"
) )
def __init__(self, *args, **kwargs):
super(SearchFormPlus, self).__init__(*args, **kwargs)
self.fields['s'].help_text = get_input_formats_help_text(
self.fields['s'].input_formats
)
self.fields['e'].help_text = get_input_formats_help_text(
self.fields['e'].input_formats
)
...@@ -35,6 +35,26 @@ footer a { ...@@ -35,6 +35,26 @@ footer a {
border-radius: 0; border-radius: 0;
} }
/* Add right colors for buttons in dropdown in navbar-inverse (else it is light
* gray on white bg and white when hovered */
.navbar-inverse .dropdown-menu .btn-link {
text-decoration: none;
color: #262626;
padding: 0;
}
.navbar-inverse .dropdown-menu .btn-link:hover {
background-color: #f5f5f5;
}
@media screen and (max-width: 767px) {
.navbar-inverse .dropdown-menu .btn-link {
color: #9d9d9d;
}
.navbar-inverse .dropdown-menu .btn-link:hover {
color: #fff;
background-color: transparent;
}
}
/* Set height of the grid so .sidenav can be 100% (adjust as needed) */ /* Set height of the grid so .sidenav can be 100% (adjust as needed) */
.row.content { .row.content {
height: 100%; height: 100%;
......
...@@ -118,7 +118,7 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -118,7 +118,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</li> </li>
{% acl_end %} {% acl_end %}
<li> <li>
<a href="{% url 'about' %}"><i class="fa fa-info-circle"></i> {% trans "About" %}</a> <a href="{% url 'about' %}"><i class="fa fa-info-circle"></i> {% trans "About" %}</a>
</li> </li>
{% if not request.user.is_authenticated %} {% if not request.user.is_authenticated %}
{% if var_sa %} {% if var_sa %}
...@@ -145,48 +145,11 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -145,48 +145,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
</div> </div>
</form> </form>
</li> </li>
{% endif %} {% endif %}
</ul>
</ul>
{% comment %}
<div class="navbar-right">
<form action="{% url "search:search"%}" class="navbar-form" role="search">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search" name="q" id="search-term" {% if search_term %}value="{{ search_term }}"{% endif %}>
<div class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
<a href="{% url "search:searchp" %}" class="btn btn-default" role="button"><i class="fa fa-plus"></i></a>
</div>
</div>
</form>
</div>
<ul class="nav navbar-nav navbar-right">
{% if not request.user.is_authenticated %}
{% if var_sa %}
<li>
<a href="{% url 'users:new-user' %}">
<i class="fa fa-user-plus"></i> Créer un compte
</a>
</li>
{% endif %}
<li>
<a href="{% url 'login' %}">
<i class="fa fa-sign-in-alt"></i> Login
</a>
</li>
{% endif %}
{% can_view_app preferences %}
<li>
<a href="{% url 'preferences:display-options' %}">
<i class="fa fa-cogs"></i> Preferences
</a>
</li>
{% acl_end %}
<li> <li>
<a href="{% url 'about' %}"><i class="fa fa-info-circle"></i> A propos</a> {% include 'buttons/setlang.html' %}
</li> </li>
</ul> </ul>
{% endcomment %}
</div> </div>
</div> </div>
</nav> </nav>
......
{% 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 Maël Kervella
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 %}
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
<a class="dropdown" type="button" role="button" id="setlang"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<i class="fa fa-globe"></i> <span class="caret"></span>
</a>
<div class="dropdown-menu" aria-labelledby="setlang">
<p style="text-align: center"><small><i class="fa fa-exclamation-triangle"></i> {% trans "Translation in development" %}</small></p>
<hr>
<form method="post" action="{% url 'set_language' %}">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
{% for language in languages %}
<button type="submit" name="language" value="{{ language.code }}"
class="btn btn-link btn-block
{% if language.code == LANGUAGE_CODE %}disabled{% endif %}">
{% if language.code == LANGUAGE_CODE %}
<i class="fa fa-check"></i>
{% endif %}
{{ language.name_local | title }} ({{ language.code }})
</button>
{% endfor %}
</form>
</div>
...@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% load url_insert_param %} {% load url_insert_param %}
{% if list.paginator.num_pages > 1 %}
<ul class="pagination nav navbar-nav"> <ul class="pagination nav navbar-nav">
{% if list.has_previous %} {% if list.has_previous %}
<li><a href="{% url_insert_param request.get_full_path page=1 %}"> << </a></li> <li><a href="{% url_insert_param request.get_full_path page=1 %}"> << </a></li>
...@@ -39,5 +40,5 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -39,5 +40,5 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<li><a href="{% url_insert_param request.get_full_path page=list.next_page_number %}"> > </a></li> <li><a href="{% url_insert_param request.get_full_path page=list.next_page_number %}"> > </a></li>
<li><a href="{% url_insert_param request.get_full_path page=list.paginator.page_range|length %}"> >> </a></li> <li><a href="{% url_insert_param request.get_full_path page=list.paginator.page_range|length %}"> >> </a></li>
{% endif %} {% endif %}
</ul> </ul>
{% endif %}
...@@ -24,69 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -24,69 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% load acl %} {% load acl %}
<div class="table-responsive" style="font-size: 12px">
<table class="table table-bordered text-center text-nowrap">
<thead>
<tr>
{% for port in port_list|slice:"::2" %}
<td class="bg-primary text-white">{{ port.port }}</td>
{% endfor %}
</tr>
<tr>
{% for port in port_list|slice:"::2" %}
{% if port.room %}
<td class="p-3 mb-2 bg-success text-dark">
{{ port.room }}
{% elif port.machine_interface %}
<td class="p-3 mb-2 bg-warning text-dark">
<a href="{% url 'users:profil' userid=port.machine_interface.machine.user.id %}">{{ port.machine_interface }}</a>
{% elif port.related%}
<td class="p-3 mb-2 bg-danger text-dark">
<a href="{% url 'topologie:index-port' switchid=port.related.switch.id %}">{{ port.related }}</a>
{% else %}
<td class="p-3 mb-2 bg-info text-dark">
Vide
{% endif %}
</td>
{% endfor %}
</tr>
<tr>
{% for port in port_list|slice:"1::2" %}
<td class="bg-primary text-white">{{ port.port }}</td>
{% endfor %}
</tr>
<tr>
{% for port in port_list|slice:"1::2" %}
{% if port.room %}
<td class="p-3 mb-2 bg-success text-dark">
{{ port.room }}
{% elif port.machine_interface %}
<td class="p-3 mb-2 bg-warning text-dark">
<a href="{% url 'users:profil' userid=port.machine_interface.machine.user.id %}">{{ port.machine_interface }}</a>
{% elif port.related%}
<td class="p-3 mb-2 bg-danger text-dark">
<a href="{% url 'topologie:index-port' switchid=port.related.switch.id %}">{{ port.related }}</a>
{% else %}
<td class="p-3 mb-2 bg-info text-dark">
Vide
{% endif %}
</td>
{% endfor %}
</tr>
</table>
</div>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-striped"> <table class="table table-striped">
<thead> <thead>
...@@ -105,37 +42,47 @@ with this program; if not, write to the Free Software Foundation, Inc., ...@@ -105,37 +42,47 @@ with this program; if not, write to the Free Software Foundation, Inc.,
<tr> <tr>
<td>{{ port.port }}</td> <td>{{ port.port }}</td>
<td> <td>
{% if port.room %} {% if port.room %}{{ port.room }}{% endif %}
{{ port.room }}
{% endif %}
</td> </td>
<td> <td>
{% if port.machine_interface %} {% if port.machine_interface %}
<a href="{% url 'users:profil' userid=port.machine_interface.machine.user.id %}">{{ port.machine_interface }}</a> {% can_view port.machine_interface.machine.user %}
{% endif %} <a href="{% url 'users:profil' userid=port.machine_interface.machine.user.id %}">
{{ port.machine_interface }}
</a>
{% acl_else %}
{{ port.machine_interface }}
{% acl_end %}
{% endif %}
</td> </td>
<td> <td>
{% if port.related %} {% if port.related %}
<a href="{% url 'topologie:index-port' switchid=port.related.switch.id %}">{{ port.related }}</a> {% can_view port.related.switch %}
{% endif %} <a href="{% url 'topologie:index-port' switchid=port.related.switch.id %}">
{{ port.related }}
</a>
{% acl_else %}
{{ port.related }}
{% acl_end %}
{% endif %}
</td> </td>
<td>{{ port.radius }}</td> <td>{{ port.radius }}</td>