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:
commit
f0aa4b345f
9 changed files with 217 additions and 124 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 ""
|
||||||
|
|
|
@ -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")
|
||||||
|
|
17
re2o/acl.py
17
re2o/acl.py
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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">
|
||||||
|
|
Loading…
Reference in a new issue