Commit dc38c32a authored by LEVY-FALK Hugo's avatar LEVY-FALK Hugo Committed by root

ACL dans un fichier dédié dans chaque application.

parent 8fbcecd3
......@@ -21,3 +21,4 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from .acl import *
# 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.
""".acl
Here are defined some functions to check acl on the application.
"""
def can_view(user):
"""Check if an user can view the application.
Args:
user: The user who wants to view the application.
Returns:
A couple (allowed, msg) where allowed is a boolean which is True if
viewing is granted and msg is a message (can be None).
"""
can = user.has_perms(('cableur',))
return can, None if can else "Vous ne pouvez pas voir cette application."
......@@ -43,8 +43,8 @@ from users.models import User
from re2o.settings import LOGO_PATH
from re2o import settings
from re2o.views import form
from re2o.utils import (
SortTable,
from re2o.utils import SortTable
from re2o.acl import (
can_create,
can_edit,
can_delete,
......
......@@ -21,3 +21,4 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from .acl import *
# 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.
"""logs.acl
Here are defined some functions to check acl on the application.
"""
def can_view(user):
"""Check if an user can view the application.
Args:
user: The user who wants to view the application.
Returns:
A couple (allowed, msg) where allowed is a boolean which is True if
viewing is granted and msg is a message (can be None).
"""
can = user.has_perms(('cableur',))
return can, None if can else "Vous ne pouvez pas voir cette application."
......@@ -98,6 +98,8 @@ from re2o.utils import (
all_baned,
all_has_access,
all_adherent,
)
from re2o.acl import (
can_view_all,
can_view_app,
can_edit_history,
......
......@@ -21,3 +21,4 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from .acl import *
# 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.
"""machines.acl
Here are defined some functions to check acl on the application.
"""
def can_view(user):
"""Check if an user can view the application.
Args:
user: The user who wants to view the application.
Returns:
A couple (allowed, msg) where allowed is a boolean which is True if
viewing is granted and msg is a message (can be None).
"""
can = user.has_perms(('cableur',))
return can, None if can else "Vous ne pouvez pas voir cette application."
......@@ -124,6 +124,8 @@ from re2o.utils import (
all_has_access,
filter_active_interfaces,
SortTable,
)
from re2o.acl import (
can_create,
can_edit,
can_delete,
......@@ -219,7 +221,7 @@ def generate_ipv4_mbf_param( form, is_type_tt ):
@can_create(Machine)
@can_edit(User)
def new_machine(request, user, userid):
""" Fonction de creation d'une machine. Cree l'objet machine,
""" Fonction de creation d'une machine. Cree l'objet machine,
le sous objet interface et l'objet domain à partir de model forms.
Trop complexe, devrait être simplifié"""
......@@ -568,7 +570,7 @@ def add_mx(request):
@login_required
@can_edit(Mx)
def edit_mx(request, mx_instance, mxid):
mx = MxForm(request.POST or None, instance=mx_instance)
if mx.is_valid():
with transaction.atomic(), reversion.create_revision():
......@@ -746,7 +748,7 @@ def add_alias(request, interface, interfaceid):
reversion.set_comment("Création")
messages.success(request, "Cet alias a été ajouté")
return redirect(reverse(
'machines:index-alias',
'machines:index-alias',
kwargs={'interfaceid':str(interfaceid)}
))
return form({'aliasform': alias}, 'machines/machine.html', request)
......@@ -763,7 +765,7 @@ def edit_alias(request, domain_instance, domainid):
reversion.set_comment("Champs modifié(s) : %s" % ', '.join(field for field in alias.changed_data))
messages.success(request, "Alias modifié")
return redirect(reverse(
'machines:index-alias',
'machines:index-alias',
kwargs={'interfaceid':str(domain_instance.cname.interface_parent.id)}
))
return form({'aliasform': alias}, 'machines/machine.html', request)
......@@ -783,7 +785,7 @@ def del_alias(request, interface, interfaceid):
except ProtectedError:
messages.error(request, "Erreur l'alias suivant %s ne peut être supprimé" % alias_del)
return redirect(reverse(
'machines:index-alias',
'machines:index-alias',
kwargs={'interfaceid':str(interfaceid)}
))
return form({'aliasform': alias}, 'machines/machine.html', request)
......
# 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.
"""preferences.acl
Here are defined some functions to check acl on the application.
"""
def can_view(user):
"""Check if an user can view the application.
Args:
user: The user who wants to view the application.
Returns:
A couple (allowed, msg) where allowed is a boolean which is True if
viewing is granted and msg is a message (can be None).
"""
can = user.has_perms(('cableur',))
return can, None if can else "Vous ne pouvez pas voir cette application."
......@@ -42,7 +42,7 @@ from reversion.models import Version
from reversion import revisions as reversion
from re2o.views import form
from re2o.utils import can_create, can_edit, can_delete_set, can_view_all
from re2o.acl import can_create, can_edit, can_delete_set, can_view_all
from .forms import ServiceForm, DelServiceForm
from .models import Service, OptionalUser, OptionalMachine, AssoOption
from .models import MailMessageOption, GeneralOption, OptionalTopologie
......
# -*- 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 © 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.
"""Handles ACL for re2o.
Here are defined some decorators that can be used in views to handle ACL.
"""
from __future__ import unicode_literals
import sys
from django.contrib import messages
from django.shortcuts import redirect
from django.urls import reverse
import cotisations, logs, machines, preferences, search, topologie, users
def can_create(model):
"""Decorator to check if an user can create a model.
It assumes that a valid user exists in the request and that the model has a
method can_create(user) which returns true if the user can create this kind
of models.
"""
def decorator(view):
def wrapper(request, *args, **kwargs):
can, msg = model.can_create(request.user, *args, **kwargs)
if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return view(request, *args, **kwargs)
return wrapper
return decorator
def can_edit(model, *field_list):
"""Decorator to check if an user can edit a model.
It tries to get an instance of the model, using
`model.get_instance(*args, **kwargs)` and assumes that the model has a
method `can_edit(user)` which returns `true` if the user can edit this
kind of models.
"""
def decorator(view):
def wrapper(request, *args, **kwargs):
try:
instance = model.get_instance(*args, **kwargs)
except model.DoesNotExist:
messages.error(request, u"Entrée inexistante")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
can, msg = instance.can_edit(request.user)
if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
for field in field_list:
can_create = getattr(model, 'can_change_' + field)
can, msg = can_create(instance, request.user, *args, **kwargs)
if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return view(request, instance, *args, **kwargs)
return wrapper
return decorator
def can_change(model, *field_list):
"""Decorator to check if an user can edit a field of a model class.
Difference with can_edit : take a class and not an instance
"""
def decorator(view):
def wrapper(request, *args, **kwargs):
for field in field_list:
can_create = getattr(model, 'can_change_' + field)
can, msg = can_create(request.user, *args, **kwargs)
if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return view(request, *args, **kwargs)
return wrapper
return decorator
def can_delete(model):
"""Decorator to check if an user can delete a model.
It tries to get an instance of the model, using
`model.get_instance(*args, **kwargs)` and assumes that the model has a
method `can_delete(user)` which returns `true` if the user can delete this
kind of models.
"""
def decorator(view):
def wrapper(request, *args, **kwargs):
try:
instance = model.get_instance(*args, **kwargs)
except model.DoesNotExist:
messages.error(request, u"Entrée inexistante")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
can, msg = instance.can_delete(request.user)
if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return view(request, instance, *args, **kwargs)
return wrapper
return decorator
def can_delete_set(model):
"""Decorator which returns a list of detable models by request user.
If none of them, return an error"""
def decorator(view):
def wrapper(request, *args, **kwargs):
all_objects = model.objects.all()
instances_id = []
for instance in all_objects:
can, msg = instance.can_delete(request.user)
if can:
instances_id.append(instance.id)
instances = model.objects.filter(id__in=instances_id)
if not instances:
messages.error(request, "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return view(request, instances, *args, **kwargs)
return wrapper
return decorator
def can_view(model):
"""Decorator to check if an user can view a model.
It tries to get an instance of the model, using
`model.get_instance(*args, **kwargs)` and assumes that the model has a
method `can_view(user)` which returns `true` if the user can view this
kind of models.
"""
def decorator(view):
def wrapper(request, *args, **kwargs):
try:
instance = model.get_instance(*args, **kwargs)
except model.DoesNotExist:
messages.error(request, u"Entrée inexistante")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
can, msg = instance.can_view(request.user)
if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return view(request, instance, *args, **kwargs)
return wrapper
return decorator
def can_view_all(model):
"""Decorator to check if an user can view a class of model.
"""
def decorator(view):
def wrapper(request, *args, **kwargs):
can, msg = model.can_view_all(request.user)
if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return view(request, *args, **kwargs)
return wrapper
return decorator
def can_view_app(app_name):
"""Decorator to check if an user can view an application.
"""
assert app_name in sys.modules.keys()
def decorator(view):
def wrapper(request, *args, **kwargs):
app = sys.modules[app_name]
can,msg = app.can_view(request.user)
if can:
return view(request, *args, **kwargs)
messages.error(request, msg)
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return wrapper
return decorator
def can_edit_history(view):
"""Decorator to check if an user can edit history."""
def wrapper(request, *args, **kwargs):
if request.user.has_perms(('admin',)):
return view(request, *args, **kwargs)
messages.error(
request,
"Vous ne pouvez pas éditer l'historique."
)
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return wrapper
......@@ -2,19 +2,19 @@
# 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 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.
......
......@@ -48,7 +48,7 @@ an instance of a model (either Model.can_xxx or instance.can_xxx)
**Example**:
{% can_create Machine targeted_user %}
<p>I'm authorized to create new machines for this guy \\o/</p>
<p>I'm authorized to create new machines.models.for this guy \\o/</p>
{% acl_else %}
<p>Why can't I create a little machine for this guy ? :(</p>
{% acl_end %}
......@@ -70,72 +70,71 @@ an instance of a model (either Model.can_xxx or instance.can_xxx)
the acl function exists in the model definition
"""
import sys
from django import template
from django.template.base import Node, NodeList
from re2o.utils import APP_VIEWING_RIGHT
import cotisations.models as cotisations
import machines.models as machines
import preferences.models as preferences
import topologie.models as topologie
import users.models as users
import cotisations
import machines
import preferences
import topologie
import users
register = template.Library()
MODEL_NAME = {
# cotisations
'Facture' : cotisations.Facture,
'Vente' : cotisations.Vente,
'Article' : cotisations.Article,
'Banque' : cotisations.Banque,
'Paiement' : cotisations.Paiement,
'Cotisation' : cotisations.Cotisation,
'Facture' : cotisations.models.Facture,
'Vente' : cotisations.models.Vente,
'Article' : cotisations.models.Article,
'Banque' : cotisations.models.Banque,
'Paiement' : cotisations.models.Paiement,
'Cotisation' : cotisations.models.Cotisation,
# machines
'Machine' : machines.Machine,
'MachineType' : machines.MachineType,
'IpType' : machines.IpType,
'Vlan' : machines.Vlan,
'Nas' : machines.Nas,
'SOA' : machines.SOA,
'Extension' : machines.Extension,
'Mx' : machines.Mx,
'Ns' : machines.Ns,
'Txt' : machines.Txt,
'Srv' : machines.Srv,
'Interface' : machines.Interface,
'Domain' : machines.Domain,
'IpList' : machines.IpList,
'Service' : machines.Service,
'Service_link' : machines.Service_link,
'OuverturePortList' : machines.OuverturePortList,
'OuverturePort' : machines.OuverturePort,
'Machine' : machines.models.Machine,
'MachineType' : machines.models.MachineType,
'IpType' : machines.models.IpType,
'Vlan' : machines.models.Vlan,
'Nas' : machines.models.Nas,
'SOA' : machines.models.SOA,
'Extension' : machines.models.Extension,
'Mx' : machines.models.Mx,
'Ns' : machines.models.Ns,
'Txt' : machines.models.Txt,
'Srv' : machines.models.Srv,
'Interface' : machines.models.Interface,
'Domain' : machines.models.Domain,
'IpList' : machines.models.IpList,
'Service' : machines.models.Service,
'Service_link' : machines.models.Service_link,
'OuverturePortList' : machines.models.OuverturePortList,
'OuverturePort' : machines.models.OuverturePort,
# preferences
'OptionalUser': preferences.OptionalUser,
'OptionalMachine': preferences.OptionalMachine,
'OptionalTopologie': preferences.OptionalTopologie,
'GeneralOption': preferences.GeneralOption,
'Service': preferences.Service,
'AssoOption': preferences.AssoOption,
'MailMessageOption': preferences.MailMessageOption,
'OptionalUser': preferences.models.OptionalUser,
'OptionalMachine': preferences.models.OptionalMachine,
'OptionalTopologie': preferences.models.OptionalTopologie,
'GeneralOption': preferences.models.GeneralOption,
'Service': preferences.models.Service,
'AssoOption': preferences.models.AssoOption,
'MailMessageOption': preferences.models.MailMessageOption,
# topologie
'Stack' : topologie.Stack,
'Switch' : topologie.Switch,
'ModelSwitch' : topologie.ModelSwitch,
'ConstructorSwitch' : topologie.ConstructorSwitch,
'Port' : topologie.Port,
'Room' : topologie.Room,
'Stack' : topologie.models.Stack,
'Switch' : topologie.models.Switch,
'ModelSwitch' : topologie.models.ModelSwitch,
'ConstructorSwitch' : topologie.models.ConstructorSwitch,
'Port' : topologie.models.Port,
'Room' : topologie.models.Room,
# users
'User' : users.User,
'Adherent' : users.Adherent,
'Club' : users.Club,
'ServiceUser' : users.ServiceUser,
'Right' : users.Right,
'School' : users.School,
'ListRight' : users.ListRight,
'Ban' : users.Ban,
'Whitelist' : users.Whitelist,
'User' : users.models.User,
'Adherent' : users.models.Adherent,
'Club' : users.models.Club,
'ServiceUser' : users.models.ServiceUser,
'Right' : users.models.Right,
'School' : users.models.School,
'ListRight' : users.models.ListRight,
'Ban' : users.models.Ban,
'Whitelist' : users.models.Whitelist,
}
......@@ -181,21 +180,9 @@ def get_callback(tag_name, obj=None):
if tag_name == 'cannot_view_all':
return acl_fct(obj.can_view_all, True)
if tag_name == 'can_view_app':
return acl_fct(
lambda user:(
user.has_perms((APP_VIEWING_RIGHT[obj],)),
"Vous ne pouvez pas voir cette application."
),
False
)
return acl_fct(sys.modules[obj].can_view, False)
if tag_name == 'cannot_view_app':
return acl_fct(
lambda user:(
user.has_perms((APP_VIEWING_RIGHT[obj],)),
"Vous ne pouvez pas voir cette application."
),
True
)
return acl_fct(sys.modules[obj].can_view, True)
if tag_name == 'can_edit_history':
return acl_fct(lambda user:(user.has_perms(('admin',)),None),False)
if tag_name == 'cannot_edit_history':
......@@ -252,7 +239,7 @@ def acl_app_filter(parser, token):
"%r tag require 1 argument : the application"
% token.contents.split()[0]
)
if not app_name in APP_VIEWING_RIGHT.keys():
if not app_name in sys.modules.keys():
raise template.TemplateSyntaxError(
"%r is not a registered application for acl."
% app_name
......
......@@ -50,214 +50,6 @@ from preferences.models import Service
DT_NOW = timezone.now()
def can_create(model):
"""Decorator to check if an user can create a model.
It assumes that a valid user exists in the request and that the model has a
method can_create(user) which returns true if the user can create this kind
of models.
"""
def decorator(view):
def wrapper(request, *args, **kwargs):
can, msg = model.can_create(request.user, *args, **kwargs)
if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
return view(request, *args, **kwargs)
return wrapper
return decorator
def can_edit(model, *field_list):
"""Decorator to check if an user can edit a model.
It tries to get an instance of the model, using
`model.get_instance(*args, **kwargs)` and assumes that the model has a
method `can_edit(user)` which returns `true` if the user can edit this
kind of models.
"""
def decorator(view):
def wrapper(request, *args, **kwargs):
try:
instance = model.get_instance(*args, **kwargs)
except model.DoesNotExist:
messages.error(request, u"Entrée inexistante")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}
))
can, msg = instance.can_edit(request.user)
if not can:
messages.error(request, msg or "Vous ne pouvez pas accéder à ce menu")
return redirect(reverse('users:profil',
kwargs={'userid':str(request.user.id)}