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

View file

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

View file

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

View file

@ -62,7 +62,7 @@ from re2o.field_permissions import FieldPermissionModelMixin
from re2o.mixins import AclMixin, RevMixin 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 """ Class définissant une machine, object parent user, objets fils
interfaces""" interfaces"""
@ -80,14 +80,6 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
verbose_name = _("machine") verbose_name = _("machine")
verbose_name_plural = _("machines") 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): def linked_objects(self):
"""Return linked objects : machine and domain. """Return linked objects : machine and domain.
Usefull in history display""" Usefull in history display"""
@ -157,8 +149,7 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
if user != user_request: if user != user_request:
return ( return (
False, False,
_("You don't have the right to add a machine to another" _("You don't have the right to add a machine to another" " user."),
" user."),
("machines.add_machine",), ("machines.add_machine",),
) )
if user.user_interfaces().count() >= max_lambdauser_interfaces: 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): if not (user_request.has_perm("machines.change_interface") and can_user):
return ( return (
False, False,
_("You don't have the right to edit a machine of another" _("You don't have the right to edit a machine of another" " user."),
" user."), ("machines.change_interface",) + (permissions or ()),
("machines.change_interface",) + permissions,
) )
return True, None, None return True, None, None
@ -202,14 +192,14 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
can_user, _message, permissions = self.user.can_edit( can_user, _message, permissions = self.user.can_edit(
self.user, user_request, *args, **kwargs 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 ( return (
False, False,
_( _(
"You don't have the right to delete a machine" "You don't have the right to delete a machine"
" of another user." " of another user."
), ),
("machines.change_interface",) + permissions, ("machines.delete_interface",) + (permissions or ()),
) )
return True, None, None return True, None, None
@ -225,8 +215,7 @@ class Machine(RevMixin, FieldPermissionModelMixin, models.Model):
): ):
return ( return (
False, False,
_("You don't have the right to view other machines than" _("You don't have the right to view other machines than" " yours."),
" yours."),
("machines.view_machine",), ("machines.view_machine",),
) )
return True, None, None return True, None, None
@ -558,8 +547,7 @@ class IpType(RevMixin, AclMixin, models.Model):
for element in IpType.objects.all().exclude(pk=self.pk): for element in IpType.objects.all().exclude(pk=self.pk):
if not self.ip_set.isdisjoint(element.ip_set): if not self.ip_set.isdisjoint(element.ip_set):
raise ValidationError( raise ValidationError(
_("The specified range is not disjoint from existing" _("The specified range is not disjoint from existing" " ranges.")
" ranges.")
) )
# On formate le prefix v6 # On formate le prefix v6
if self.prefix_v6: if self.prefix_v6:
@ -1302,7 +1290,11 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
if not ( if not (
preferences.models.OptionalMachine.get_cached_value("create_machine") 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 = preferences.models.OptionalMachine.get_cached_value(
"max_lambdauser_interfaces" "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): if not (user_request.has_perm("machines.change_interface") and can_user):
return ( return (
False, False,
_("You don't have the right to edit a machine of another" _("You don't have the right to edit a machine of another user."),
" user."), ("machines.change_interface",) + (permissions or ()),
("machines.change_interface",) + permissions,
) )
return True, None, None return True, None, None
@ -1367,12 +1358,14 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
can_user, _message, permissions = self.machine.user.can_edit( can_user, _message, permissions = self.machine.user.can_edit(
user_request, *args, **kwargs 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 ( return (
False, False,
_("You don't have the right to edit a machine of another" _(
" user."), "You don't have the right to delete interfaces of another"
("machines.change_interface",) + permissions, " user."
),
("machines.delete_interface",) + (permissions or ()),
) )
return True, None, None return True, None, None
@ -1388,7 +1381,7 @@ class Interface(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
): ):
return ( return (
False, 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",), ("machines.view_interface",),
) )
return True, None, None return True, None, None
@ -1441,7 +1434,7 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
return ( return (
False, 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." " machine of another user."
), ),
("machines.add_ipv6list",), ("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): if not (user_request.has_perm("machines.change_ipv6list") and can_user):
return ( return (
False, 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",), ("machines.change_ipv6list",),
) )
return True, None, None 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( can_user, _message, permissions = self.interface.machine.user.can_edit(
user_request, *args, **kwargs 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 ( return (
False, 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 return True, None, None
@ -1508,7 +1505,9 @@ class Ipv6List(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
): ):
return ( return (
False, 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",), ("machines.view_ipv6list",),
) )
return True, None, None return True, None, None
@ -1761,8 +1760,7 @@ class Domain(RevMixin, AclMixin, FieldPermissionModelMixin, models.Model):
): ):
return ( return (
False, False,
_("You don't have the right to view other machines than" _("You don't have the right to view other machines than" " yours."),
" yours."),
("machines.view_domain",), ("machines.view_domain",),
) )
return True, None, None return True, None, None
@ -1979,8 +1977,7 @@ class OuverturePortList(RevMixin, AclMixin, models.Model):
class Meta: class Meta:
permissions = ( permissions = (
("view_ouvertureportlist", _("Can view a ports opening list" ("view_ouvertureportlist", _("Can view a ports opening list" " object")),
" object")),
) )
verbose_name = _("ports opening list") verbose_name = _("ports opening list")
verbose_name_plural = _("ports opening lists") 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.") message = msg or _("You don't have the right to edit this option.")
if groups: if groups:
return ( return (
message message + _("You need to be a member of one of these groups: %s.") % groups
+ _("You need to be a member of one of these groups: %s.") % groups
) )
else: else:
return message + _("No group has the %s permission(s)!") % " or ".join( return message + _("No group has the %s permission(s)!") % " or ".join(
@ -124,7 +123,7 @@ ModelC)
``` ```
The view will be called like this: The view will be called like this:
``` ```
view(request, instance_of_A, instance_of_b, *args, **kwargs) view(request, instance_of_A, instance_of_b, *args, **kwargs)
``` ```
where `*args` and `**kwargs` are the original view arguments. where `*args` and `**kwargs` are the original view arguments.
""" """
@ -153,7 +152,7 @@ ModelC)
"""The wrapper used for a specific request""" """The wrapper used for a specific request"""
instances = [] 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 """This function calls the methods on the target and checks for
the can_change_`field` method with the given fields. It also the can_change_`field` method with the given fields. It also
stores the instances of models in order to avoid duplicate DB stores the instances of models in order to avoid duplicate DB
@ -161,7 +160,7 @@ ModelC)
""" """
if on_instance: if on_instance:
try: try:
target = target.get_instance(*args, **kwargs) target = target.get_instance(target_id, *args, **kwargs)
instances.append(target) instances.append(target)
except target.DoesNotExist: except target.DoesNotExist:
yield False, _("Nonexistent entry."), [] yield False, _("Nonexistent entry."), []
@ -175,8 +174,12 @@ ModelC)
error_messages = [] error_messages = []
warning_messages = [] warning_messages = []
for target, fields in group_targets(): for arg_key, (target, fields) in zip(kwargs.keys(), group_targets()):
for can, msg, permissions in process_target(target, fields): 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: if not can:
error_messages.append(acl_error_message(msg, permissions)) error_messages.append(acl_error_message(msg, permissions))
elif msg: elif msg:

View file

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

View file

@ -197,13 +197,13 @@ class CommentTicket(AclMixin, models.Model):
""" Check that the user has the right to edit the ticket comment """ Check that the user has the right to edit the ticket comment
or that it is the author""" or that it is the author"""
if ( 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) and (self.parent_ticket.user != user_request or self.parent_ticket.user != self.created_by)
): ):
return ( return (
False, False,
_("You don't have the right to edit other tickets comments than yours."), _("You don't have the right to edit other tickets comments than yours."),
("tickets.edit_commentticket",), ("tickets.change_commentticket",),
) )
else: else:
return True, None, None 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 """Define a wireless AP. Inherit from machines.interfaces
Definition pour une borne wifi , hérite de machines.interfaces Definition pour une borne wifi , hérite de machines.interfaces
@ -135,6 +135,27 @@ class AccessPoint(AclMixin, Machine):
def __str__(self): def __str__(self):
return str(self.interface_set.first()) 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): class Server(Machine):
""" """
@ -173,8 +194,29 @@ class Server(Machine):
def __str__(self): def __str__(self):
return str(self.interface_set.first()) 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), """ Definition d'un switch. Contient un nombre de ports (number),
un emplacement (location), un stack parent (optionnel, stack) un emplacement (location), un stack parent (optionnel, stack)
et un id de membre dans le stack (stack_member_id) et un id de membre dans le stack (stack_member_id)
@ -457,6 +499,27 @@ class Switch(AclMixin, Machine):
def __str__(self): def __str__(self):
return str(self.get_name) 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): class ModelSwitch(AclMixin, RevMixin, models.Model):
"""Un modèle (au sens constructeur) de switch""" """Un modèle (au sens constructeur) de switch"""
@ -532,7 +595,9 @@ class ModuleOnSwitch(AclMixin, RevMixin, models.Model):
unique_together = ["slot", "switch"] unique_together = ["slot", "switch"]
def __str__(self): 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): class ConstructorSwitch(AclMixin, RevMixin, models.Model):
@ -842,9 +907,7 @@ class PortProfile(AclMixin, RevMixin, models.Model):
radius_type = models.CharField( radius_type = models.CharField(
max_length=32, max_length=32,
choices=TYPES, choices=TYPES,
help_text=_( help_text=_("Type of RADIUS authentication: inactive, MAC-address or 802.1X."),
"Type of RADIUS authentication: inactive, MAC-address or 802.1X."
),
verbose_name=_("RADIUS type"), verbose_name=_("RADIUS type"),
) )
radius_mode = models.CharField( radius_mode = models.CharField(

View file

@ -56,7 +56,7 @@ function toggle_graph() {
</button> </button>
<a target="_blank" href="/media/images/switchs.png" class="btn btn-primary"> <a target="_blank" href="/media/images/switchs.png" class="btn btn-primary">
<span class="fa fa-arrows-alt"></span> <span class="fa fa-arrows-alt"></span>
</a> </a>
<div id="collImg" class="collapse" aria-expanded="false"> <div id="collImg" class="collapse" aria-expanded="false">