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 %}