From 715edafcdca16ea89797628d9cea2c3d2ee5ac36 Mon Sep 17 00:00:00 2001
From: Matthew Holloway <matthew@staff.ietf.org>
Date: Thu, 29 Aug 2024 00:51:05 +1200
Subject: [PATCH] fix: return to ballotpopup (#7858)

* fix: return to ballotpopup

* fix: ballot position return to in modals

* fix: ballot return to test

* fix: ballot return to additional allow handlers

* fix: ballot return to handler syntax error in test
---
 ietf/doc/templatetags/ballot_icon.py | 13 +++++++++++--
 ietf/doc/tests_ballot.py             | 20 ++++++++------------
 ietf/doc/views_ballot.py             | 13 +++++++++++++
 ietf/doc/views_doc.py                | 10 +++++++++-
 ietf/templates/doc/ballot_popup.html |  2 +-
 5 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/ietf/doc/templatetags/ballot_icon.py b/ietf/doc/templatetags/ballot_icon.py
index ebcc605cd..5f59822c7 100644
--- a/ietf/doc/templatetags/ballot_icon.py
+++ b/ietf/doc/templatetags/ballot_icon.py
@@ -96,9 +96,14 @@ def ballot_icon(context, doc):
     positions = list(ballot.active_balloter_positions().items())
     positions.sort(key=sort_key)
 
+    request = context.get("request")
+    ballot_edit_return_point_param = f"ballot_edit_return_point={request.path}"
+
     right_click_string = ''
     if has_role(user, "Area Director"):
-        right_click_string = 'oncontextmenu="window.location.href=\'%s\';return false;"' %  urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk))
+        right_click_string = 'oncontextmenu="window.location.href=\'{}?{}\';return false;"'.format(
+            urlreverse('ietf.doc.views_ballot.edit_position', kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
+            ballot_edit_return_point_param)
 
     my_blocking = False
     for i, (balloter, pos) in enumerate(positions):
@@ -113,10 +118,14 @@ def ballot_icon(context, doc):
         typename = "RSAB"
     else:
         typename = "IESG"
+    
+    modal_url = "{}?{}".format(
+        urlreverse("ietf.doc.views_doc.ballot_popup", kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
+        ballot_edit_return_point_param)
 
     res = ['<a %s href="%s" data-bs-toggle="modal" data-bs-target="#modal-%d" aria-label="%s positions" title="%s positions (click to show more)" class="ballot-icon"><table' % (
             right_click_string,
-            urlreverse("ietf.doc.views_doc.ballot_popup", kwargs=dict(name=doc.name, ballot_id=ballot.pk)),
+            modal_url,
             ballot.pk,
             typename,
             typename,)]
diff --git a/ietf/doc/tests_ballot.py b/ietf/doc/tests_ballot.py
index 2403b6ef5..d77e2ddc9 100644
--- a/ietf/doc/tests_ballot.py
+++ b/ietf/doc/tests_ballot.py
@@ -1455,18 +1455,14 @@ class BallotContentTests(TestCase):
 
 class ReturnToUrlTests(TestCase):
     def test_invalid_return_to_url(self):
-        self.assertRaises(
-            Exception,
-            lambda: parse_ballot_edit_return_point('/doc/', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718'),
-        )
-        self.assertRaises(
-            Exception,
-            lambda: parse_ballot_edit_return_point('/a-route-that-does-not-exist/', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718'),
-        )
-        self.assertRaises(
-            Exception,
-            lambda: parse_ballot_edit_return_point('https://example.com/phishing', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718'),
-        )
+        with self.assertRaises(ValueError):
+            parse_ballot_edit_return_point('/', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718')
+
+        with self.assertRaises(ValueError):
+            parse_ballot_edit_return_point('/a-route-that-does-not-exist/', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718')
+
+        with self.assertRaises(ValueError):
+            parse_ballot_edit_return_point('https://example.com/phishing', 'draft-ietf-opsawg-ipfix-tcpo-v6eh', '998718')
 
     def test_valid_default_return_to_url(self):
         self.assertEqual(parse_ballot_edit_return_point(
diff --git a/ietf/doc/views_ballot.py b/ietf/doc/views_ballot.py
index 357bd2fa2..8d9ab0b74 100644
--- a/ietf/doc/views_ballot.py
+++ b/ietf/doc/views_ballot.py
@@ -1314,10 +1314,23 @@ def rsab_ballot_status(request):
 def parse_ballot_edit_return_point(path, doc_name, ballot_id):
     get_default_path = lambda: urlreverse("ietf.doc.views_doc.document_ballot", kwargs=dict(name=doc_name, ballot_id=ballot_id))
     allowed_path_handlers = {
+        "ietf.community.views.view_list",
         "ietf.doc.views_doc.document_ballot",
         "ietf.doc.views_doc.document_irsg_ballot",
         "ietf.doc.views_doc.document_rsab_ballot",
+        "ietf.doc.views_ballot.irsg_ballot_status",
+        "ietf.doc.views_ballot.rsab_ballot_status",
+        "ietf.doc.views_search.search",
+        "ietf.doc.views_search.docs_for_ad",
+        "ietf.doc.views_search.drafts_in_last_call",
+        "ietf.doc.views_search.recent_drafts",
+        "ietf.group.views.chartering_groups",
+        "ietf.group.views.group_documents",
+        "ietf.group.views.stream_documents",
         "ietf.iesg.views.agenda",
         "ietf.iesg.views.agenda_documents",
+        "ietf.iesg.views.discusses",
+        "ietf.iesg.views.past_documents",
     }
     return validate_return_to_path(path, get_default_path, allowed_path_handlers)
+
diff --git a/ietf/doc/views_doc.py b/ietf/doc/views_doc.py
index 0ef132c21..d12dd0418 100644
--- a/ietf/doc/views_doc.py
+++ b/ietf/doc/views_doc.py
@@ -43,7 +43,7 @@ from pathlib import Path
 
 from django.core.cache import caches
 from django.db.models import Max
-from django.http import HttpResponse, Http404
+from django.http import HttpResponse, Http404, HttpResponseBadRequest
 from django.shortcuts import render, get_object_or_404, redirect
 from django.template.loader import render_to_string
 from django.urls import reverse as urlreverse
@@ -73,6 +73,7 @@ from ietf.ietfauth.utils import ( has_role, is_authorized_in_doc_stream, user_is
     role_required, is_individual_draft_author, can_request_rfc_publication)
 from ietf.name.models import StreamName, BallotPositionName
 from ietf.utils.history import find_history_active_at
+from ietf.doc.views_ballot import parse_ballot_edit_return_point
 from ietf.doc.forms import InvestigateForm, TelechatForm, NotifyForm, ActionHoldersForm, DocAuthorForm, DocAuthorChangeBasisForm
 from ietf.doc.mails import email_comment, email_remind_action_holders
 from ietf.mailtrigger.utils import gather_relevant_expansions
@@ -1586,11 +1587,18 @@ def ballot_popup(request, name, ballot_id):
     doc = get_object_or_404(Document, name=name)
     c = document_ballot_content(request, doc, ballot_id=ballot_id, editable=False)
     ballot = get_object_or_404(BallotDocEvent,id=ballot_id)
+    
+    try:
+        return_to_url = parse_ballot_edit_return_point(request.GET.get('ballot_edit_return_point'), name, ballot_id)
+    except ValueError:
+        return HttpResponseBadRequest('ballot_edit_return_point is invalid')
+    
     return render(request, "doc/ballot_popup.html",
                               dict(doc=doc,
                                    ballot_content=c,
                                    ballot_id=ballot_id,
                                    ballot_type_slug=ballot.ballot_type.slug,
+                                   ballot_edit_return_point=return_to_url,
                                    editable=True,
                                    ))
 
diff --git a/ietf/templates/doc/ballot_popup.html b/ietf/templates/doc/ballot_popup.html
index 2c0863ab6..d2589cd54 100644
--- a/ietf/templates/doc/ballot_popup.html
+++ b/ietf/templates/doc/ballot_popup.html
@@ -27,7 +27,7 @@
             {% if editable and user|has_role:"Area Director,Secretariat,IRSG Member,RSAB Member" %}
                 {% if user|can_ballot:doc %}
                     <a class="btn btn-primary"
-                       href="{% url "ietf.doc.views_ballot.edit_position" name=doc.name ballot_id=ballot_id %}?ballot_edit_return_point={{ request.path|urlencode }}">
+                       href="{% url "ietf.doc.views_ballot.edit_position" name=doc.name ballot_id=ballot_id %}?ballot_edit_return_point={{ ballot_edit_return_point|urlencode }}">
                         Edit position
                     </a>
                 {% endif %}