8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-12-23 15:33:45 +00:00

Merge branch 'fix_acl_multiple_instance' into 'dev'

Allow ACL to be used for two instances of the same model.

See merge request re2o/re2o!526
This commit is contained in:
chirac 2020-05-01 13:00:27 +02:00
commit f0aa4b345f
9 changed files with 217 additions and 124 deletions

View file

@ -138,7 +138,7 @@ class Facture(BaseInvoice):
abstract = False
permissions = (
# TODO : change facture to invoice
("change_facture_control", _("Can edit the \"controlled\" state")),
("change_facture_control", _('Can edit the "controlled" state')),
("view_facture", _("Can view an invoice object")),
("change_all_facture", _("Can edit all the previous invoices")),
)
@ -166,7 +166,7 @@ class Facture(BaseInvoice):
return (
False,
_("You don't have the right to edit this user's invoices."),
("cotisations.change_all_facture",) + permissions,
("cotisations.change_all_facture",) + (permissions or ()),
)
elif not user_request.has_perm("cotisations.change_all_facture") and (
self.control or not self.valid
@ -198,7 +198,7 @@ class Facture(BaseInvoice):
return (
False,
_("You don't have the right to delete this user's invoices."),
("cotisations.change_all_facture",) + permissions,
("cotisations.change_all_facture",) + (permissions or ()),
)
elif not user_request.has_perm("cotisations.change_all_facture") and (
self.control or not self.valid
@ -243,7 +243,7 @@ class Facture(BaseInvoice):
can = user_request.has_perm("cotisations.change_facture_control")
return (
can,
_("You don't have the right to edit the \"controlled\" state.")
_('You don\'t have the right to edit the "controlled" state.')
if not can
else None,
("cotisations.change_facture_control",),
@ -297,14 +297,14 @@ class Facture(BaseInvoice):
for purchase in self.vente_set.all():
if hasattr(purchase, "cotisation"):
cotisation = purchase.cotisation
if cotisation.type_cotisation == 'Connexion':
if cotisation.type_cotisation == "Connexion":
cotisation.date_start = date_con
date_con += relativedelta(
months=(purchase.duration or 0) * purchase.number,
days=(purchase.duration_days or 0) * purchase.number,
)
cotisation.date_end = date_con
elif cotisation.type_cotisation == 'Adhesion':
elif cotisation.type_cotisation == "Adhesion":
cotisation.date_start = date_adh
date_adh += relativedelta(
months=(purchase.duration or 0) * purchase.number,
@ -566,7 +566,7 @@ class Vente(RevMixin, AclMixin, models.Model):
return (
False,
_("You don't have the right to edit this user's purchases."),
("cotisations.change_all_facture",) + permissions,
("cotisations.change_all_facture",) + (permissions or ()),
)
elif not user_request.has_perm("cotisations.change_all_vente") and (
self.facture.control or not self.facture.valid

View file

@ -104,13 +104,10 @@ from .models import (
ActionsSearch,
RevisionAction,
MachineHistorySearch,
get_history_class
get_history_class,
)
from .forms import (
ActionsSearchForm,
MachineHistorySearchForm
)
from .forms import ActionsSearchForm, MachineHistorySearchForm
@login_required
@ -180,7 +177,9 @@ def stats_logs(request):
revisions.object_list = [RevisionAction(r) for r in revisions.object_list]
return render(request, "logs/stats_logs.html", {"revisions_list": revisions})
return render(request, "logs/search_stats_logs.html", {"actions_form": actions_form})
return render(
request, "logs/search_stats_logs.html", {"actions_form": actions_form}
)
@login_required
@ -305,19 +304,29 @@ def stats_general(request):
"email_state_verified_users": [
_("Users with a confirmed email"),
User.objects.filter(email_state=User.EMAIL_STATE_VERIFIED).count(),
Adherent.objects.filter(email_state=User.EMAIL_STATE_VERIFIED).count(),
Adherent.objects.filter(
email_state=User.EMAIL_STATE_VERIFIED
).count(),
Club.objects.filter(email_state=User.EMAIL_STATE_VERIFIED).count(),
],
"email_state_unverified_users": [
_("Users with an unconfirmed email"),
User.objects.filter(email_state=User.EMAIL_STATE_UNVERIFIED).count(),
Adherent.objects.filter(email_state=User.EMAIL_STATE_UNVERIFIED).count(),
Club.objects.filter(email_state=User.EMAIL_STATE_UNVERIFIED).count(),
User.objects.filter(
email_state=User.EMAIL_STATE_UNVERIFIED
).count(),
Adherent.objects.filter(
email_state=User.EMAIL_STATE_UNVERIFIED
).count(),
Club.objects.filter(
email_state=User.EMAIL_STATE_UNVERIFIED
).count(),
],
"email_state_pending_users": [
_("Users pending email confirmation"),
User.objects.filter(email_state=User.EMAIL_STATE_PENDING).count(),
Adherent.objects.filter(email_state=User.EMAIL_STATE_PENDING).count(),
Adherent.objects.filter(
email_state=User.EMAIL_STATE_PENDING
).count(),
Club.objects.filter(email_state=User.EMAIL_STATE_PENDING).count(),
],
"actives_interfaces": [
@ -449,32 +458,36 @@ def stats_users(request):
de bannissement par user, etc"""
stats = {
User._meta.verbose_name: {
Machine._meta.verbose_name_plural: User.objects.annotate(num=Count("machine")).order_by("-num")[
:10
],
Facture._meta.verbose_name_plural: User.objects.annotate(num=Count("facture")).order_by("-num")[
:10
],
Ban._meta.verbose_name_plural: User.objects.annotate(num=Count("ban")).order_by("-num")[:10],
Whitelist._meta.verbose_name_plural: User.objects.annotate(num=Count("whitelist")).order_by(
"-num"
)[:10],
Machine._meta.verbose_name_plural: User.objects.annotate(
num=Count("machine")
).order_by("-num")[:10],
Facture._meta.verbose_name_plural: User.objects.annotate(
num=Count("facture")
).order_by("-num")[:10],
Ban._meta.verbose_name_plural: User.objects.annotate(
num=Count("ban")
).order_by("-num")[:10],
Whitelist._meta.verbose_name_plural: User.objects.annotate(
num=Count("whitelist")
).order_by("-num")[:10],
_("rights"): User.objects.annotate(num=Count("groups")).order_by("-num")[
:10
],
},
School._meta.verbose_name: {
User._meta.verbose_name_plural: School.objects.annotate(num=Count("user")).order_by("-num")[:10]
User._meta.verbose_name_plural: School.objects.annotate(
num=Count("user")
).order_by("-num")[:10]
},
Paiement._meta.verbose_name: {
User._meta.verbose_name_plural: Paiement.objects.annotate(num=Count("facture")).order_by("-num")[
:10
]
User._meta.verbose_name_plural: Paiement.objects.annotate(
num=Count("facture")
).order_by("-num")[:10]
},
Banque._meta.verbose_name: {
User._meta.verbose_name_plural: Banque.objects.annotate(num=Count("facture")).order_by("-num")[
:10
]
User._meta.verbose_name_plural: Banque.objects.annotate(
num=Count("facture")
).order_by("-num")[:10]
},
}
return render(request, "logs/stats_users.html", {"stats_list": stats})
@ -505,22 +518,15 @@ def stats_search_machine_history(request):
if history_form.is_valid():
history = MachineHistorySearch()
events = history.get(
history_form.cleaned_data.get("q", ""),
history_form.cleaned_data
history_form.cleaned_data.get("q", ""), history_form.cleaned_data
)
max_result = GeneralOption.get_cached_value("pagination_number")
events = re2o_paginator(
request,
events,
max_result
)
events = re2o_paginator(request, events, max_result)
return render(request, "logs/machine_history.html", {"events": events},)
return render(
request,
"logs/machine_history.html",
{ "events": events },
request, "logs/search_machine_history.html", {"history_form": history_form}
)
return render(request, "logs/search_machine_history.html", {"history_form": history_form})
def get_history_object(request, model, object_name, object_id):
@ -528,9 +534,7 @@ def get_history_object(request, model, object_name, object_id):
Handles permissions and DoesNotExist errors
"""
try:
object_name_id = object_name + "id"
kwargs = {object_name_id: object_id}
instance = model.get_instance(**kwargs)
instance = model.get_instance(object_id)
except model.DoesNotExist:
instance = None
@ -544,8 +548,9 @@ def get_history_object(request, model, object_name, object_id):
messages.error(
request, msg or _("You don't have the right to access this menu.")
)
return False, redirect(
reverse("users:profil", kwargs={"userid": str(request.user.id)})
return (
False,
redirect(reverse("users:profil", kwargs={"userid": str(request.user.id)})),
)
return True, instance

View file

@ -21,7 +21,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 2.5\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-04-24 18:45+0200\n"
"POT-Creation-Date: 2020-04-30 22:19+0200\n"
"PO-Revision-Date: 2018-06-23 16:35+0200\n"
"Last-Translator: Laouen Fernet <laouen.fernet@supelec.fr>\n"
"Language-Team: \n"
@ -192,8 +192,7 @@ msgstr ""
"Vous avez atteint le nombre maximal d'interfaces que vous pouvez créer vous-"
"même (%s)."
#: machines/models.py:189 machines/models.py:1354 machines/models.py:1373
#: machines/models.py:1476 machines/models.py:1494
#: machines/models.py:189
msgid "You don't have the right to edit a machine of another user."
msgstr ""
"Vous n'avez pas le droit de modifier une machine d'un autre utilisateur."
@ -588,9 +587,19 @@ msgstr ""
msgid "You don't have the right to edit the machine."
msgstr "Vous n'avez pas le droit d'éditer une machine."
#: machines/models.py:1391 machines/models.py:1511
msgid "You don't have the right to view machines other than yours."
msgstr "Vous n'avez pas le droit de voir d'autres machines que les vôtres."
#: machines/models.py:1354
msgid "You don't have the right to edit interfaces of another user."
msgstr ""
"Vous n'avez pas le droit de modifier une interface d'un autre utilisateur."
#: machines/models.py:1373
msgid "You don't have the right to delete interfaces of another user."
msgstr ""
"Vous n'avez pas le droit de supprimer une interface d'une autre utilisateur."
#: machines/models.py:1391
msgid "You don't have the right to view interfaces other than yours."
msgstr "Vous n'avez pas le droit de voir d'autres interfaces que les vôtres."
#: machines/models.py:1419
msgid "Can view an IPv6 addresses list object"
@ -612,17 +621,30 @@ msgstr "Listes d'adresses IPv6"
msgid "Nonexistent interface."
msgstr "Interface inexistante."
#: machines/models.py:1444 machines/models.py:1688
msgid "You don't have the right to add an alias to a machine of another user."
#: machines/models.py:1444
msgid "You don't have the right to add ipv6 to a machine of another user."
msgstr ""
"Vous n'avez pas le droit d'ajouter un alias à une machine d'un autre "
"utilisateur."
"Vous n'avez pas le droit d'ajouter des ipv6 à une machine d'un autre utilisateur."
#: machines/models.py:1457
msgid "You don't have the right to change the SLAAC value of an IPv6 address."
msgstr ""
"Vous n'avez pas le droit de changer la valeur SLAAC d'une adresse IPv6."
#: machines/models.py:1476
msgid "You don't have the right to edit ipv6 of a machine of another user."
msgstr ""
"Vous n'avez pas le droit de modifier les ipv6 d'une machine d'un autre utilisateur."
#: machines/models.py:1494
msgid "You don't have the right to delete ipv6 of a machine of another user."
msgstr ""
"Vous n'avez pas le droit de supprimer les ipv6 d'une machine d'une autre utilisateur."
#: machines/models.py:1511
msgid "You don't have the right to view ipv6 of machines other than yours."
msgstr "Vous n'avez pas le droit de voir les ipv6 d'autres machines que les vôtres."
#: machines/models.py:1543
msgid "A SLAAC IP address is already registered."
msgstr "Une adresse IP SLAAC est déjà enregistrée."
@ -677,6 +699,12 @@ msgstr "Le nom de domaine %s contient des caractères interdits."
msgid "Invalid extension."
msgstr "Extension invalide."
#: machines/models.py:1688
msgid "You don't have the right to add an alias to a machine of another user."
msgstr ""
"Vous n'avez pas le droit d'ajouter un alias à une machine d'un autre "
"utilisateur."
#: machines/models.py:1704
#, python-format
msgid ""

View file

@ -62,7 +62,7 @@ from re2o.field_permissions import FieldPermissionModelMixin
from re2o.mixins import AclMixin, RevMixin
class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
class Machine(RevMixin, FieldPermissionModelMixin, AclMixin, models.Model):
""" Class définissant une machine, object parent user, objets fils
interfaces"""
@ -80,14 +80,6 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
verbose_name = _("machine")
verbose_name_plural = _("machines")
@classmethod
def get_instance(cls, machineid, *_args, **_kwargs):
"""Get the Machine instance with machineid.
:param userid: The id
:return: The user
"""
return cls.objects.get(pk=machineid)
def linked_objects(self):
"""Return linked objects : machine and domain.
Usefull in history display"""
@ -157,8 +149,7 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
if user != user_request:
return (
False,
_("You don't have the right to add a machine to another"
" user."),
_("You don't have the right to add a machine to another" " user."),
("machines.add_machine",),
)
if user.user_interfaces().count() >= max_lambdauser_interfaces:
@ -186,9 +177,8 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
if not (user_request.has_perm("machines.change_interface") and can_user):
return (
False,
_("You don't have the right to edit a machine of another"
" user."),
("machines.change_interface",) + permissions,
_("You don't have the right to edit a machine of another" " user."),
("machines.change_interface",) + (permissions or ()),
)
return True, None, None
@ -202,14 +192,14 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
can_user, _message, permissions = self.user.can_edit(
self.user, user_request, *args, **kwargs
)
if not (user_request.has_perm("machines.change_interface") and can_user):
if not (user_request.has_perm("machines.delete_interface") and can_user):
return (
False,
_(
"You don't have the right to delete a machine"
" of another user."
),
("machines.change_interface",) + permissions,
("machines.delete_interface",) + (permissions or ()),
)
return True, None, None
@ -225,8 +215,7 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
):
return (
False,
_("You don't have the right to view other machines than"
" yours."),
_("You don't have the right to view other machines than" " yours."),
("machines.view_machine",),
)
return True, None, None
@ -558,8 +547,7 @@ class IpType(RevMixin, AclMixin, models.Model):
for element in IpType.objects.all().exclude(pk=self.pk):
if not self.ip_set.isdisjoint(element.ip_set):
raise ValidationError(
_("The specified range is not disjoint from existing"
" ranges.")
_("The specified range is not disjoint from existing" " ranges.")
)
# On formate le prefix v6
if self.prefix_v6:
@ -1302,7 +1290,11 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
if not (
preferences.models.OptionalMachine.get_cached_value("create_machine")
):
return False, _("You don't have the right to add a machine."), ("machines.add_interface",)
return (
False,
_("You don't have the right to add a machine."),
("machines.add_interface",),
)
max_lambdauser_interfaces = preferences.models.OptionalMachine.get_cached_value(
"max_lambdauser_interfaces"
)
@ -1351,9 +1343,8 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
if not (user_request.has_perm("machines.change_interface") and can_user):
return (
False,
_("You don't have the right to edit a machine of another"
" user."),
("machines.change_interface",) + permissions,
_("You don't have the right to edit a machine of another user."),
("machines.change_interface",) + (permissions or ()),
)
return True, None, None
@ -1367,12 +1358,14 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
can_user, _message, permissions = self.machine.user.can_edit(
user_request, *args, **kwargs
)
if not (user_request.has_perm("machines.change_interface") and can_user):
if not (user_request.has_perm("machines.delete_interface") and can_user):
return (
False,
_("You don't have the right to edit a machine of another"
" user."),
("machines.change_interface",) + permissions,
_(
"You don't have the right to delete interfaces of another"
" user."
),
("machines.delete_interface",) + (permissions or ()),
)
return True, None, None
@ -1388,7 +1381,7 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
):
return (
False,
_("You don't have the right to view machines other than yours."),
_("You don't have the right to view interfaces other than yours."),
("machines.view_interface",),
)
return True, None, None
@ -1441,7 +1434,7 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
return (
False,
_(
"You don't have the right to add an alias to a"
"You don't have the right to add ipv6 to a"
" machine of another user."
),
("machines.add_ipv6list",),
@ -1473,7 +1466,9 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
if not (user_request.has_perm("machines.change_ipv6list") and can_user):
return (
False,
_("You don't have the right to edit a machine of another user."),
_(
"You don't have the right to edit ipv6 of a machine of another user."
),
("machines.change_ipv6list",),
)
return True, None, None
@ -1488,11 +1483,13 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
can_user, _message, permissions = self.interface.machine.user.can_edit(
user_request, *args, **kwargs
)
if not (user_request.has_perm("machines.change_ipv6list") and can_user):
if not (user_request.has_perm("machines.delete_ipv6list") and can_user):
return (
False,
_("You don't have the right to edit a machine of another user."),
("machines.change_ipv6list",) + permissions,
_(
"You don't have the right to delete ipv6 of a machine of another user."
),
("machines.delete_ipv6list",) + (permissions or ()),
)
return True, None, None
@ -1508,7 +1505,9 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
):
return (
False,
_("You don't have the right to view machines other than yours."),
_(
"You don't have the right to view ipv6 of machines other than yours."
),
("machines.view_ipv6list",),
)
return True, None, None
@ -1761,8 +1760,7 @@ class Domain(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
):
return (
False,
_("You don't have the right to view other machines than"
" yours."),
_("You don't have the right to view other machines than" " yours."),
("machines.view_domain",),
)
return True, None, None
@ -1979,8 +1977,7 @@ class OuverturePortList(RevMixin, AclMixin, models.Model):
class Meta:
permissions = (
("view_ouvertureportlist", _("Can view a ports opening list"
" object")),
("view_ouvertureportlist", _("Can view a ports opening list" " object")),
)
verbose_name = _("ports opening list")
verbose_name_plural = _("ports opening lists")

View file

@ -47,8 +47,7 @@ def acl_error_message(msg, permissions):
message = msg or _("You don't have the right to edit this option.")
if groups:
return (
message
+ _("You need to be a member of one of these groups: %s.") % groups
message + _("You need to be a member of one of these groups: %s.") % groups
)
else:
return message + _("No group has the %s permission(s)!") % " or ".join(
@ -153,7 +152,7 @@ ModelC)
"""The wrapper used for a specific request"""
instances = []
def process_target(target, fields):
def process_target(target, fields, target_id=None):
"""This function calls the methods on the target and checks for
the can_change_`field` method with the given fields. It also
stores the instances of models in order to avoid duplicate DB
@ -161,7 +160,7 @@ ModelC)
"""
if on_instance:
try:
target = target.get_instance(*args, **kwargs)
target = target.get_instance(target_id, *args, **kwargs)
instances.append(target)
except target.DoesNotExist:
yield False, _("Nonexistent entry."), []
@ -175,8 +174,12 @@ ModelC)
error_messages = []
warning_messages = []
for target, fields in group_targets():
for can, msg, permissions in process_target(target, fields):
for arg_key, (target, fields) in zip(kwargs.keys(), group_targets()):
if on_instance:
target_id = int(kwargs[arg_key])
else:
target_id = None
for can, msg, permissions in process_target(target, fields, target_id):
if not can:
error_messages.append(acl_error_message(msg, permissions))
elif msg:

View file

@ -61,8 +61,7 @@ class FormRevMixin(object):
)
elif self.changed_data:
reversion.set_comment(
"Field(s) edited: %s"
% ", ".join(field for field in self.changed_data)
"Field(s) edited: %s" % ", ".join(field for field in self.changed_data)
)
return super(FormRevMixin, self).save(*args, **kwargs)
@ -93,11 +92,9 @@ class AclMixin(object):
return str(cls.__module__).split(".")[0].lower()
@classmethod
def get_instance(cls, *_args, **kwargs):
def get_instance(cls, object_id, *_args, **kwargs):
"""Récupère une instance
:param objectid: Instance id à trouver
:return: Une instance de la classe évidemment"""
object_id = kwargs.get(cls.get_classname() + "id")
return cls.objects.get(pk=object_id)
@classmethod

View file

@ -197,13 +197,13 @@ class CommentTicket(AclMixin, models.Model):
""" Check that the user has the right to edit the ticket comment
or that it is the author"""
if (
not user_request.has_perm("tickets.edit_commentticket")
not user_request.has_perm("tickets.change_commentticket")
and (self.parent_ticket.user != user_request or self.parent_ticket.user != self.created_by)
):
return (
False,
_("You don't have the right to edit other tickets comments than yours."),
("tickets.edit_commentticket",),
("tickets.change_commentticket",),
)
else:
return True, None, None

View file

@ -88,7 +88,7 @@ class Stack(AclMixin, RevMixin, models.Model):
)
class AccessPoint(AclMixin, Machine):
class AccessPoint(Machine):
"""Define a wireless AP. Inherit from machines.interfaces
Definition pour une borne wifi , hérite de machines.interfaces
@ -135,6 +135,27 @@ class AccessPoint(AclMixin, Machine):
def __str__(self):
return str(self.interface_set.first())
# We want to retrieve the default behaviour given by AclMixin rather
# than the one overwritten by Machine. If you are not familiar with
# the behaviour of `super`, please check https://docs.python.org/3/library/functions.html#super
@classmethod
def get_instance(cls, *args, **kwargs):
return super(Machine, cls).get_instance(*args, **kwargs)
@classmethod
def can_create(cls, *args, **kwargs):
return super(Machine, cls).can_create(*args, **kwargs)
def can_edit(self, *args, **kwargs):
return super(Machine, self).can_edit(*args, **kwargs)
def can_delete(self, *args, **kwargs):
return super(Machine, self).can_delete(*args, **kwargs)
def can_view(self, *args, **kwargs):
return super(Machine, self).can_view(*args, **kwargs)
class Server(Machine):
"""
@ -173,8 +194,29 @@ class Server(Machine):
def __str__(self):
return str(self.interface_set.first())
# We want to retrieve the default behaviour given by AclMixin rather
# than the one overwritten by Machine. If you are not familiar with
# the behaviour of `super`, please check https://docs.python.org/3/library/functions.html#super
class Switch(AclMixin, Machine):
@classmethod
def get_instance(cls, *args, **kwargs):
return super(Machine, cls).get_instance(*args, **kwargs)
@classmethod
def can_create(cls, *args, **kwargs):
return super(Machine, cls).can_create(*args, **kwargs)
def can_edit(self, *args, **kwargs):
return super(Machine, self).can_edit(*args, **kwargs)
def can_delete(self, *args, **kwargs):
return super(Machine, self).can_delete(*args, **kwargs)
def can_view(self, *args, **kwargs):
return super(Machine, self).can_view(*args, **kwargs)
class Switch(Machine):
""" Definition d'un switch. Contient un nombre de ports (number),
un emplacement (location), un stack parent (optionnel, stack)
et un id de membre dans le stack (stack_member_id)
@ -457,6 +499,27 @@ class Switch(AclMixin, Machine):
def __str__(self):
return str(self.get_name)
# We want to retrieve the default behaviour given by AclMixin rather
# than the one overwritten by Machine. If you are not familiar with
# the behaviour of `super`, please check https://docs.python.org/3/library/functions.html#super
@classmethod
def get_instance(cls, *args, **kwargs):
return super(Machine, cls).get_instance(*args, **kwargs)
@classmethod
def can_create(cls, *args, **kwargs):
return super(Machine, cls).can_create(*args, **kwargs)
def can_edit(self, *args, **kwargs):
return super(Machine, self).can_edit(*args, **kwargs)
def can_delete(self, *args, **kwargs):
return super(Machine, self).can_delete(*args, **kwargs)
def can_view(self, *args, **kwargs):
return super(Machine, self).can_view(*args, **kwargs)
class ModelSwitch(AclMixin, RevMixin, models.Model):
"""Un modèle (au sens constructeur) de switch"""
@ -532,7 +595,9 @@ class ModuleOnSwitch(AclMixin, RevMixin, models.Model):
unique_together = ["slot", "switch"]
def __str__(self):
return _("On slot %(slot)s of %(switch)s").format(slot=str(self.slot), switch=str(self.switch))
return _("On slot %(slot)s of %(switch)s").format(
slot=str(self.slot), switch=str(self.switch)
)
class ConstructorSwitch(AclMixin, RevMixin, models.Model):
@ -842,9 +907,7 @@ class PortProfile(AclMixin, RevMixin, models.Model):
radius_type = models.CharField(
max_length=32,
choices=TYPES,
help_text=_(
"Type of RADIUS authentication: inactive, MAC-address or 802.1X."
),
help_text=_("Type of RADIUS authentication: inactive, MAC-address or 802.1X."),
verbose_name=_("RADIUS type"),
)
radius_mode = models.CharField(