Skip to content

Commit 40c33b1

Browse files
fix: better handle corner cases for pre-IETF-64 agenda redirects (ietf-tools#3775)
Fixes ietf-tools#3669
1 parent 1c107d2 commit 40c33b1

4 files changed

Lines changed: 78 additions & 12 deletions

File tree

ietf/meeting/helpers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@ def get_current_ietf_meeting():
5555
return meetings.first()
5656

5757
def get_current_ietf_meeting_num():
58-
return get_current_ietf_meeting().number
58+
cur = get_current_ietf_meeting()
59+
return cur.number if cur else None
5960

6061
def get_ietf_meeting(num=None):
6162
if num:
62-
meeting = Meeting.objects.filter(number=num).first()
63+
meeting = Meeting.objects.filter(type='ietf', number=num).first()
6364
else:
6465
meeting = get_current_ietf_meeting()
6566
return meeting

ietf/meeting/tests_helpers.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Copyright The IETF Trust 2020, All Rights Reserved
22
# -*- coding: utf-8 -*-
3+
import datetime
4+
35
from unittest.mock import patch, Mock
46

57
from django.conf import settings
@@ -11,7 +13,7 @@
1113
from ietf.meeting.factories import SessionFactory, MeetingFactory, TimeSlotFactory
1214
from ietf.meeting.helpers import (AgendaFilterOrganizer, AgendaKeywordTagger,
1315
delete_interim_session_conferences, sessions_post_save, sessions_post_cancel,
14-
create_interim_session_conferences)
16+
create_interim_session_conferences, get_ietf_meeting)
1517
from ietf.meeting.models import SchedTimeSessAssignment, Session
1618
from ietf.meeting.test_data import make_meeting_test_data
1719
from ietf.utils.meetecho import Conference
@@ -615,3 +617,18 @@ def test_sessions_post_save_creates_meetecho_conferences(self, mock_create_metho
615617
msgs = [str(msg) for msg in messages]
616618
self.assertEqual(len(msgs), 1)
617619
self.assertIn('An error occurred', msgs[0])
620+
621+
622+
class HelperTests(TestCase):
623+
def test_get_ietf_meeting(self):
624+
"""get_ietf_meeting() should only return IETF meetings"""
625+
# put the IETF far in the past so it's not "current"
626+
ietf = MeetingFactory(type_id='ietf', date=datetime.date.today() - datetime.timedelta(days=5 * 365))
627+
# put the interim meeting now so it will be picked up as "current" if there's a bug
628+
interim = MeetingFactory(type_id='interim', date=datetime.date.today())
629+
self.assertEqual(get_ietf_meeting(ietf.number), ietf, 'Return IETF meeting by number')
630+
self.assertIsNone(get_ietf_meeting(interim.number), 'Ignore non-IETF meetings')
631+
self.assertIsNone(get_ietf_meeting(), 'Return None if there is no current IETF meeting')
632+
ietf.date = datetime.date.today()
633+
ietf.save()
634+
self.assertEqual(get_ietf_meeting(), ietf, 'Return current meeting if there is one')

ietf/meeting/tests_views.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,54 @@ def test_meeting_agenda(self):
280280
self.assertContains(r, session.group.acronym)
281281
self.assertContains(r, slot.location.name)
282282

283+
@override_settings(PROCEEDINGS_V1_BASE_URL='https://example.com/{meeting.number}')
284+
def test_agenda_redirects_for_old_meetings(self):
285+
"""Meetings before 64 should be forwarded to their proceedings"""
286+
# meeting with record but no schedule
287+
MeetingFactory(type_id='ietf', number='35', populate_schedule=False)
288+
r = self.client.get(
289+
urlreverse(
290+
'ietf.meeting.views.agenda',
291+
kwargs={'num': '35', 'ext': '.html'},
292+
))
293+
self.assertRedirects(r, 'https://example.com/35', fetch_redirect_response=False)
294+
295+
# meeting with record and schedule but no assignments
296+
meeting_with_schedule = MeetingFactory(type_id='ietf', number='36', populate_schedule=True)
297+
r = self.client.get(
298+
urlreverse(
299+
'ietf.meeting.views.agenda',
300+
kwargs={'num': '36', 'ext': '.html'},
301+
))
302+
self.assertRedirects(r, 'https://example.com/36', fetch_redirect_response=False)
303+
304+
# meeting with an assignment
305+
SessionFactory(meeting=meeting_with_schedule)
306+
r = self.client.get(
307+
urlreverse(
308+
'ietf.meeting.views.agenda',
309+
kwargs={'num': '36', 'ext': '.html'},
310+
))
311+
self.assertRedirects(r, 'https://example.com/36', fetch_redirect_response=False)
312+
313+
def test_agenda_for_nonexistent_meeting(self):
314+
"""Return a 404 for a bad IETF meeting number"""
315+
# Meetings pre-64 are redirected, but should be a 404 if there is no Meeting instance
316+
r = self.client.get(
317+
urlreverse(
318+
'ietf.meeting.views.agenda',
319+
kwargs={'num': '32', 'ext': '.html'},
320+
))
321+
self.assertEqual(r.status_code, 404)
322+
# Check a post-64 meeting as well
323+
r = self.client.get(
324+
urlreverse(
325+
'ietf.meeting.views.agenda',
326+
kwargs={'num': '150', 'ext': '.html'},
327+
))
328+
self.assertEqual(r.status_code, 404)
329+
330+
283331
def test_meeting_agenda_filters_ignored(self):
284332
"""The agenda view should ignore filter querystrings
285333

ietf/meeting/views.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,16 +1496,16 @@ def agenda(request, num=None, name=None, base=None, ext=None, owner=None, utc=""
14961496
raise Http404('Extension not allowed')
14971497

14981498
# We do not have the appropriate data in the datatracker for IETF 64 and earlier.
1499-
# So that we're not producing misleading pages...
1500-
1501-
assert num is None or num.isdigit()
1502-
1499+
# So that we're not producing misleading pages, redirect to their proceedings.
1500+
# The datatracker DB does include a Meeting instance for every IETF meeting, though,
1501+
# so we can use that to validate that num is a valid meeting number.
15031502
meeting = get_ietf_meeting(num)
1504-
if not meeting or (meeting.number.isdigit() and int(meeting.number) <= 64 and (not meeting.schedule or not meeting.schedule.assignments.exists())):
1505-
if ext == '.html' or (meeting and meeting.number.isdigit() and 0 < int(meeting.number) <= 64):
1506-
return HttpResponseRedirect(f'{settings.PROCEEDINGS_V1_BASE_URL.format(meeting=meeting)}')
1507-
else:
1508-
raise Http404("No such meeting")
1503+
if meeting is None:
1504+
raise Http404("No such full IETF meeting")
1505+
elif int(meeting.number) <= 64:
1506+
return HttpResponseRedirect(f'{settings.PROCEEDINGS_V1_BASE_URL.format(meeting=meeting)}')
1507+
else:
1508+
pass
15091509

15101510
# Select the schedule to show
15111511
if name is None:

0 commit comments

Comments
 (0)