From 78bbef821b3baca3c496753cc5bb50d72150c043 Mon Sep 17 00:00:00 2001 From: Jean-Romain Garnier Date: Thu, 23 Apr 2020 20:26:44 +0200 Subject: [PATCH] Allow viewing history of deleted elements --- logs/models.py | 48 ++++++++++++++++++++---------------------------- logs/views.py | 32 +++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/logs/models.py b/logs/models.py index 3b088b87..970b8902 100644 --- a/logs/models.py +++ b/logs/models.py @@ -291,18 +291,19 @@ class History: self._last_version = None self.event_type = HistoryEvent - def get(self, instance): + def get(self, instance_id, model): """ - :param interface: The instance to lookup + :param instance_id: int, The id of the instance to lookup + :param model: class, The type of object to lookup :return: list or None, a list of HistoryEvent, in reverse chronological order """ self.events = [] - # Get all the versions for this interface, with the oldest first + # Get all the versions for this instance, with the oldest first self._last_version = None interface_versions = filter( - lambda x: x.field_dict["id"] == instance.id, - Version.objects.get_for_model(type(instance)).order_by("revision__date_created") + lambda x: x.field_dict["id"] == instance_id, + Version.objects.get_for_model(model).order_by("revision__date_created") ) for version in interface_versions: @@ -346,16 +347,6 @@ class History: class UserHistoryEvent(HistoryEvent): - def __init__(self, user, version, previous_version=None, edited_fields=None): - """ - :param user: User, The user who's history is being built - :param version: Version, the version of the user for this event - :param previous_version: Version, the version of the user before this event - :param edited_fields: list, The list of modified fields by this event - """ - super(UserHistoryEvent, self).__init__(version, previous_version, edited_fields) - self.user = user - def _repr(self, name, value): """ Returns the best representation of the given field @@ -425,7 +416,6 @@ class UserHistoryEvent(HistoryEvent): def __eq__(self, other): return ( - self.user.id == other.user.id and self.edited_fields == other.edited_fields and self.date == other.date and self.performed_by == other.performed_by @@ -433,13 +423,12 @@ class UserHistoryEvent(HistoryEvent): ) def __hash__(self): - return hash((self.user.id, frozenset(self.edited_fields), self.date, self.performed_by, self.comment)) + return hash((frozenset(self.edited_fields), self.date, self.performed_by, self.comment)) def __repr__(self): - return "{} edited fields {} of {} ({})".format( + return "{} edited fields {} ({})".format( self.performed_by, self.edited_fields or "nothing", - self.user, self.comment or "No comment" ) @@ -449,23 +438,23 @@ class UserHistory(History): super(UserHistory, self).__init__() self.event_type = UserHistoryEvent - def get(self, user): + def get(self, user_id): """ - :param user: User, the user to lookup + :param user_id: int, the id of the user to lookup :return: list or None, a list of UserHistoryEvent, in reverse chronological order """ self.events = [] # Find whether this is a Club or an Adherent try: - obj = Adherent.objects.get(user_ptr_id=user.id) + obj = Adherent.objects.get(user_ptr_id=user_id) except Adherent.DoesNotExist: - obj = Club.objects.get(user_ptr_id=user.id) + obj = Club.objects.get(user_ptr_id=user_id) # Add as "related" histories the list of Machine objects # that were once owned by this user self.related = filter( - lambda x: x.field_dict["user_id"] == user.id, + lambda x: x.field_dict["user_id"] == user_id, Version.objects.get_for_model(Machine).order_by("revision__date_created") ) self.related = [RelatedHistory( @@ -477,7 +466,7 @@ class UserHistory(History): # Get all the versions for this user, with the oldest first self._last_version = None user_versions = filter( - lambda x: x.field_dict["id"] == user.id, + lambda x: x.field_dict["id"] == user_id, Version.objects.get_for_model(User).order_by("revision__date_created") ) @@ -548,11 +537,11 @@ class MachineHistory(History): super(MachineHistory, self).__init__() self.event_type = MachineHistoryEvent - def get(self, machine): + def get(self, machine_id): # Add as "related" histories the list of Interface objects # that were once assigned to this machine self.related = list(filter( - lambda x: x.field_dict["machine_id"] == machine.id, + lambda x: x.field_dict["machine_id"] == machine_id, Version.objects.get_for_model(Interface).order_by("revision__date_created") )) @@ -563,7 +552,7 @@ class MachineHistory(History): i.field_dict["id"]) for i in self.related] self.related = list(dict.fromkeys(self.related)) - return super(MachineHistory, self).get(machine) + return super(MachineHistory, self).get(machine_id, Machine) class InterfaceHistoryEvent(HistoryEvent): @@ -607,3 +596,6 @@ class InterfaceHistory(History): def __init__(self): super(InterfaceHistory, self).__init__() self.event_type = InterfaceHistoryEvent + + def get(self, interface_id): + return super(InterfaceHistory, self).get(machine_id, Interface) diff --git a/logs/views.py b/logs/views.py index 54432794..c0f3d6e9 100644 --- a/logs/views.py +++ b/logs/views.py @@ -514,22 +514,44 @@ def stats_search_machine_history(request): 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, allow_deleted=False): """Get the objet of type model with the given object_id Handles permissions and DoesNotExist errors """ + instance = None + is_deleted = False + try: object_name_id = object_name + "id" kwargs = {object_name_id: object_id} instance = model.get_instance(**kwargs) except model.DoesNotExist: + pass + + if instance is None and allow_deleted: + # Try to find an instance among the Version objects + is_deleted = True + versions = filter( + lambda x: x.field_dict["id"] == object_id, + Version.objects.get_for_model(model) + ) + versions = list(versions) + if len(versions): + instance = versions[0] + + if instance is None: messages.error(request, _("Nonexistent entry.")) return False, redirect( reverse("users:profil", kwargs={"userid": str(request.user.id)}) ) - can, msg, _permissions = instance.can_view(request.user) - if not can: + if is_deleted: + can_view = can_view_app("logs") + msg = None + else: + can_view, msg, _permissions = instance.can_view(request.user) + + if not can_view: messages.error( request, msg or _("You don't have the right to access this menu.") ) @@ -559,7 +581,7 @@ def detailed_history(request, object_name, object_id): raise Http404(_("No model found.")) # Get instance and check permissions - can_view, instance = get_history_object(request, model, object_name, object_id) + can_view, instance = get_history_object(request, model, object_name, object_id, allow_deleted=True) if not can_view: return instance @@ -567,7 +589,7 @@ def detailed_history(request, object_name, object_id): max_result = GeneralOption.get_cached_value("pagination_number") events = re2o_paginator( request, - history.get(instance), + history.get(object_id), max_result )