From 399c2a97b69971d352527dd3f888c0150063de3b Mon Sep 17 00:00:00 2001
From: James Antill <james@and.org>
Date: May 06 2024 17:44:46 +0000
Subject: [PATCH 1/8] Add some regexp validation to fix #213


Signed-off-by: James Antill <james@and.org>

---

diff --git a/fedocal/forms.py b/fedocal/forms.py
index f070c83..517f088 100644
--- a/fedocal/forms.py
+++ b/fedocal/forms.py
@@ -52,12 +52,23 @@ def validate_time(form, field):
 
 
 def validate_meeting_location(form, field):
-    """ Validate if location doesn't contain #irc-chan format
-        More info: https://fedorahosted.org/fedocal/ticket/118
+    """ Validate if location for compatibility to IRC and Matrix.
+        More info: https://fedorahosted.org/fedocal/ticket/213
     """
-    if '#' in field.data.strip():
-        raise wtforms.ValidationError(
-            _('Please use channel@server format!')
+    # As always, try: https://regex101.com/
+    # These aren't "perfect" but close enough: [-\w] allows alphanum '_' and '-'
+    loc = field.data.strip()
+    # - ircroom@irc.server
+    if re.match(r'^[-\w]+@[-\w]+([.][-\w]+)*$', loc):
+        return
+    # - #room:host.name.tld
+    if re.match(r'^#[-\w]+:[-\w]+([.][-\w]+)*$', loc):
+        return
+    # - https://matrix.to/#/#room:host.name.tld
+    if re.match(r'^https?://matrix.to/#/#[-\w]+:[-\w]+([.][-\w]+)*$', loc):
+        return
+    raise wtforms.ValidationError(
+            _('Please use channel@server or #room:server formats!')
         )
 
 
diff --git a/tests/test_flask.py b/tests/test_flask.py
index 02105a7..2db5523 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1579,7 +1579,7 @@ class Flasktests(Modeltests):
             self.assertEqual(output.status_code, 200)
             output_text = output.get_data(as_text=True)
             self.assertIn(
-                '<td>Please use channel@server format!</td>', output_text)
+                '<td>Please use channel@server or #room:server formats!</td>', output_text)
             self.assertIn(
                 '<title>Add meeting - Fedocal</title>', output_text)
 

From cfed440e1d985cdad28c75fbf28e29a3d4dc132a Mon Sep 17 00:00:00 2001
From: Dominik Wombacher <dominik@wombacher.cc>
Date: May 07 2024 16:09:18 +0000
Subject: [PATCH 2/8] tests: Validate meeting location.


Relates to PR #214 and Issue #213

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index 2db5523..a171050 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1562,7 +1562,9 @@ class Flasktests(Modeltests):
             self.assertIn(
                 '<title>Add meeting - Fedocal</title>', output_text)
 
-            # Invalid location
+            # Invalid meeting location: IRC Channel name without server
+            # Allowed: channel@irc.server.tld
+            # https://pagure.io/fedocal/issue/118
             data = {
                 'meeting_name': 'guess what?',
                 'meeting_date': TODAY,
@@ -1787,6 +1789,70 @@ class Flasktests(Modeltests):
                 self.assertNotIn(
                     'href="/meeting/20/?from_date=', output_text)
 
+            # Valid meeting location: IRC Channel with server
+            # https://pagure.io/fedocal/issue/118
+            data = {
+                'meeting_name': 'guess what?',
+                'meeting_date': TODAY,
+                'meeting_time_start': time(13, 0),
+                'meeting_time_stop': time(14, 0),
+                'meeting_timezone': 'Europe/Paris',
+                'meeting_location': 'meeting-1@fedoraproject.org',
+                'frequency': '',
+                'csrf_token': csrf_token,
+            }
+
+            with testing.mock_sends(schema.MeetingNewV1):
+                output = self.app.post('/test_calendar/add/', data=data,
+                                       follow_redirects=True)
+                self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
+                self.assertIn(
+                    '<li class="message">Meeting added</li>', output_text)
+
+            # Valid meeting location: Matrix Room
+            # https://pagure.io/fedocal/issue/213
+            data = {
+                'meeting_name': 'guess what?',
+                'meeting_date': TODAY,
+                'meeting_time_start': time(13, 0),
+                'meeting_time_stop': time(14, 0),
+                'meeting_timezone': 'Europe/Paris',
+                'meeting_location': '#meeting-1:fedoraproject.org',
+                'frequency': '',
+                'csrf_token': csrf_token,
+            }
+
+            with testing.mock_sends(schema.MeetingNewV1):
+                output = self.app.post('/test_calendar/add/', data=data,
+                                       follow_redirects=True)
+                self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
+                self.assertIn(
+                    '<li class="message">Meeting added</li>', output_text)
+
+            # Valid meeting location: Matrix Room URL
+            # https://pagure.io/fedocal/issue/213
+            data = {
+                'meeting_name': 'guess what?',
+                'meeting_date': TODAY,
+                'meeting_time_start': time(13, 0),
+                'meeting_time_stop': time(14, 0),
+                'meeting_timezone': 'Europe/Paris',
+                'meeting_location': 'https://matrix.to/#/#meeting-1:fedoraproject.org',
+                'frequency': '',
+                'csrf_token': csrf_token,
+            }
+
+            with testing.mock_sends(schema.MeetingNewV1):
+                output = self.app.post('/test_calendar/add/', data=data,
+                                       follow_redirects=True)
+                self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
+                self.assertIn(
+                    '<li class="message">Meeting added</li>', output_text)
+
+
     def test_edit_meeting(self):
         """ Test the edit_meeting function. """
         self.__setup_db()

From 188adce474d0ecafa59ede3cf2cc2e0647c93500 Mon Sep 17 00:00:00 2001
From: James Antill <james@and.org>
Date: May 07 2024 16:18:41 +0000
Subject: [PATCH 3/8] Add more validation for #213, meet/zoom/hangouts/etc.


Signed-off-by: James Antill <james@and.org>

---

diff --git a/fedocal/forms.py b/fedocal/forms.py
index 517f088..59bd900 100644
--- a/fedocal/forms.py
+++ b/fedocal/forms.py
@@ -58,17 +58,63 @@ def validate_meeting_location(form, field):
     # As always, try: https://regex101.com/
     # These aren't "perfect" but close enough: [-\w] allows alphanum '_' and '-'
     loc = field.data.strip()
+    # Allow a "blank" entry...
+    if loc == '':
+        return
+
     # - ircroom@irc.server
     if re.match(r'^[-\w]+@[-\w]+([.][-\w]+)*$', loc):
         return
+
     # - #room:host.name.tld
     if re.match(r'^#[-\w]+:[-\w]+([.][-\w]+)*$', loc):
         return
+
     # - https://matrix.to/#/#room:host.name.tld
     if re.match(r'^https?://matrix.to/#/#[-\w]+:[-\w]+([.][-\w]+)*$', loc):
         return
+
+    # - irc://irc.server/ircroom
+    # Eg.
+    #   irc://irc.libera.chat/fedora-zh
+    if re.match(r'^irc://[-\w]+([.][-\w]+)*/[-\w]+$', loc):
+        return
+
+    # - https://meet.<server>/<name>
+    # Eg.
+    #   https://meet.google.com/acq-pwxk-fhv
+    #   https://meet.jit.si/fedora-websites-apps-meeting
+    if re.match(r'^https?://meet([.][-\w]+)+/[-\w]+$', loc):
+        return
+
+    # - https://meet.<server>/b/<name>
+    # Eg.
+    #   https://meet.kde.org/b/ale-swq-39j
+    if re.match(r'^https?://meet([.][-\w]+)+/b/[-\w]+$', loc):
+        return
+
+    # - https://<server>.zoom.us/j/<name>?pwd=<pwd>
+    # Eg.
+    #   https://umich.zoom.us/j/96648123924?pwd=RitQVVQvMFVSaXJhNkFBS08vWTk0Zz09
+    if re.match(r'^https?://[-\w]+.zoom.us/j/\d+([?]pwd=\w+)?$', loc):
+        return
+
+    # - https://hangouts.google.com/hangouts/_/<name>
+    # Eg.
+    #   https://hangouts.google.com/hangouts/_/67zc3kvkovelxctlilphwodlp4e
+    if re.match(r'^https?://hangouts.google.com/hangouts/_/[-\w]+$', loc):
+        return
+
+    # podcast.fedoraproject.org
+    if loc == 'podcast.fedoraproject.org':
+        return
+    if loc == 'http://podcast.fedoraproject.org/':
+        return
+    if loc == 'https://podcast.fedoraproject.org/':
+        return
+
     raise wtforms.ValidationError(
-            _('Please use channel@server or #room:server formats!')
+            _('Please use IRC, Matrix, meet, zoom or hangouts formats!')
         )
 
 

From 601e8cc5c625bfc9c627c8ebeff690243ec91af7 Mon Sep 17 00:00:00 2001
From: James Antill <james@and.org>
Date: May 07 2024 16:35:20 +0000
Subject: [PATCH 4/8] tests: Validate meeting location using current values from calendar.


Relates to PR #214 and Issue #213

Signed-off-by: James Antill <james@and.org>

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index a171050..b01b66d 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1852,6 +1852,44 @@ class Flasktests(Modeltests):
                 self.assertIn(
                     '<li class="message">Meeting added</li>', output_text)
 
+            # Valid meeting location: List of current meeting locations:
+            meet_locations = ['',
+                'https://unomaha.zoom.us/j/609939109',
+                'https://hangouts.google.com/hangouts/_/67zc3kvkovelxctlilphwodlp4e',
+                'https://meet.opensuse.org/epel',
+                'irc://irc.libera.chat/fedora-zh',
+                'https://meet.google.com/acq-pwxk-fhv',
+                'https://meet.google.com/mic-otnv-kse',
+                'https://meet.jit.si/fedora-websites-apps-meeting',
+                'https://meet.kde.org/b/ale-swq-39j',
+                'https://umich.zoom.us/j/96648123924?pwd=RitQVVQvMFVSaXJhNkFBS08vWTk0Zz09',
+                'https://umich.zoom.us/j/99842244394?pwd=YVdkQjJTdnpBMUkySGVzK1kyTGoyZz09',
+                'https://meet.google.com/xuj-jswy-hat',
+                'podcast.fedoraproject.org',
+                'https://podcast.fedoraproject.org/',
+                'https://meet.google.com/jod-dkmw-ibd']
+            # https://pagure.io/fedocal/issue/213
+            data = {
+                'meeting_name': 'guess what?',
+                'meeting_date': TODAY,
+                'meeting_time_start': time(13, 0),
+                'meeting_time_stop': time(14, 0),
+                'meeting_timezone': 'Europe/Paris',
+                'meeting_location': None,
+                'frequency': '',
+                'csrf_token': csrf_token,
+            }
+
+            for meet_location in meet_locations:
+              with testing.mock_sends(schema.MeetingNewV1):
+                data['meeting_location'] = meet_location
+                output = self.app.post('/test_calendar/add/', data=data,
+                                       follow_redirects=True)
+                self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
+                self.assertIn(
+                    '<li class="message">Meeting added</li>', output_text)
+
 
     def test_edit_meeting(self):
         """ Test the edit_meeting function. """

From cfee527e9276dc0115cd39bd58bc8a0d3d668217 Mon Sep 17 00:00:00 2001
From: James Antill <jantill@redhat.com>
Date: May 20 2024 21:34:28 +0000
Subject: [PATCH 5/8] tests: Fix message we check for, in test error output.


Signed-off-by: James Antill <jantill@redhat.com>

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index b01b66d..9119924 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1581,7 +1581,7 @@ class Flasktests(Modeltests):
             self.assertEqual(output.status_code, 200)
             output_text = output.get_data(as_text=True)
             self.assertIn(
-                '<td>Please use channel@server or #room:server formats!</td>', output_text)
+                '<td>Please use IRC, Matrix, meet, zoom or hangouts formats!</td>', output_text)
             self.assertIn(
                 '<title>Add meeting - Fedocal</title>', output_text)
 

From cf38cb23601a2d33cd365f35be98ad57ba1ece95 Mon Sep 17 00:00:00 2001
From: James Antill <jantill@redhat.com>
Date: May 20 2024 21:35:29 +0000
Subject: [PATCH 6/8] tests: Stupid hack workaround for mock/strftime failures.


Signed-off-by: James Antill <jantill@redhat.com>

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index 9119924..c7ec38c 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1880,8 +1880,12 @@ class Flasktests(Modeltests):
                 'csrf_token': csrf_token,
             }
 
-            for meet_location in meet_locations:
-              with testing.mock_sends(schema.MeetingNewV1):
+            # Copy and paste works, but using:
+            #   for meet_location in meet_locations
+            # ...always fails on the second attempt.
+            import random
+            meet_location = random.choice(meet_locations)
+            with testing.mock_sends(schema.MeetingNewV1):
                 data['meeting_location'] = meet_location
                 output = self.app.post('/test_calendar/add/', data=data,
                                        follow_redirects=True)

From b75c4dd61267a1ada56734fb5a3b1e92cb659c9b Mon Sep 17 00:00:00 2001
From: James Antill <jantill@redhat.com>
Date: May 20 2024 21:36:11 +0000
Subject: [PATCH 7/8] Allow all URLs for a meeting location. Issue #213


Signed-off-by: James Antill <jantill@redhat.com>

---

diff --git a/fedocal/forms.py b/fedocal/forms.py
index 59bd900..75b24a9 100644
--- a/fedocal/forms.py
+++ b/fedocal/forms.py
@@ -108,9 +108,13 @@ def validate_meeting_location(form, field):
     # podcast.fedoraproject.org
     if loc == 'podcast.fedoraproject.org':
         return
-    if loc == 'http://podcast.fedoraproject.org/':
+
+    # Just let in all URLs ...
+    if loc.startswith('irc://'):
+        return
+    if loc.startswith('http://'):
         return
-    if loc == 'https://podcast.fedoraproject.org/':
+    if loc.startswith('https://'):
         return
 
     raise wtforms.ValidationError(

From fff15b096d149bfb9a57c10595e1eb320ae08f86 Mon Sep 17 00:00:00 2001
From: James Antill <jantill@redhat.com>
Date: Jun 05 2024 00:01:36 +0000
Subject: [PATCH 8/8] test: Change the meeting time to not get the testing error, and test all urls.


Signed-off-by: James Antill <jantill@redhat.com>

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index c7ec38c..628cb58 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1789,20 +1789,21 @@ class Flasktests(Modeltests):
                 self.assertNotIn(
                     'href="/meeting/20/?from_date=', output_text)
 
-            # Valid meeting location: IRC Channel with server
-            # https://pagure.io/fedocal/issue/118
-            data = {
+            _mnum = 0
+            def _tst_add_meeting_loc(loc):
+              nonlocal _mnum
+              data = {
                 'meeting_name': 'guess what?',
                 'meeting_date': TODAY,
-                'meeting_time_start': time(13, 0),
-                'meeting_time_stop': time(14, 0),
+                'meeting_time_start': time(_mnum, 0),
+                'meeting_time_stop': time(_mnum+1, 0),
                 'meeting_timezone': 'Europe/Paris',
-                'meeting_location': 'meeting-1@fedoraproject.org',
+                'meeting_location': loc,
                 'frequency': '',
                 'csrf_token': csrf_token,
-            }
-
-            with testing.mock_sends(schema.MeetingNewV1):
+              }
+              _mnum += 1
+              with testing.mock_sends(schema.MeetingNewV1):
                 output = self.app.post('/test_calendar/add/', data=data,
                                        follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
@@ -1810,89 +1811,37 @@ class Flasktests(Modeltests):
                 self.assertIn(
                     '<li class="message">Meeting added</li>', output_text)
 
+            meeting_locs = set()
+            # Valid meeting location: IRC Channel with server
+            # https://pagure.io/fedocal/issue/118
+            meeting_locs.add('meeting-1@fedoraproject.org')
+
             # Valid meeting location: Matrix Room
             # https://pagure.io/fedocal/issue/213
-            data = {
-                'meeting_name': 'guess what?',
-                'meeting_date': TODAY,
-                'meeting_time_start': time(13, 0),
-                'meeting_time_stop': time(14, 0),
-                'meeting_timezone': 'Europe/Paris',
-                'meeting_location': '#meeting-1:fedoraproject.org',
-                'frequency': '',
-                'csrf_token': csrf_token,
-            }
-
-            with testing.mock_sends(schema.MeetingNewV1):
-                output = self.app.post('/test_calendar/add/', data=data,
-                                       follow_redirects=True)
-                self.assertEqual(output.status_code, 200)
-                output_text = output.get_data(as_text=True)
-                self.assertIn(
-                    '<li class="message">Meeting added</li>', output_text)
+            meeting_locs.add('#meeting-1:fedoraproject.org')
 
             # Valid meeting location: Matrix Room URL
             # https://pagure.io/fedocal/issue/213
-            data = {
-                'meeting_name': 'guess what?',
-                'meeting_date': TODAY,
-                'meeting_time_start': time(13, 0),
-                'meeting_time_stop': time(14, 0),
-                'meeting_timezone': 'Europe/Paris',
-                'meeting_location': 'https://matrix.to/#/#meeting-1:fedoraproject.org',
-                'frequency': '',
-                'csrf_token': csrf_token,
-            }
-
-            with testing.mock_sends(schema.MeetingNewV1):
-                output = self.app.post('/test_calendar/add/', data=data,
-                                       follow_redirects=True)
-                self.assertEqual(output.status_code, 200)
-                output_text = output.get_data(as_text=True)
-                self.assertIn(
-                    '<li class="message">Meeting added</li>', output_text)
+            meeting_locs.add('https://matrix.to/#/#meeting-1:fedoraproject.org')
 
             # Valid meeting location: List of current meeting locations:
-            meet_locations = ['',
-                'https://unomaha.zoom.us/j/609939109',
-                'https://hangouts.google.com/hangouts/_/67zc3kvkovelxctlilphwodlp4e',
-                'https://meet.opensuse.org/epel',
-                'irc://irc.libera.chat/fedora-zh',
-                'https://meet.google.com/acq-pwxk-fhv',
-                'https://meet.google.com/mic-otnv-kse',
-                'https://meet.jit.si/fedora-websites-apps-meeting',
-                'https://meet.kde.org/b/ale-swq-39j',
-                'https://umich.zoom.us/j/96648123924?pwd=RitQVVQvMFVSaXJhNkFBS08vWTk0Zz09',
-                'https://umich.zoom.us/j/99842244394?pwd=YVdkQjJTdnpBMUkySGVzK1kyTGoyZz09',
-                'https://meet.google.com/xuj-jswy-hat',
-                'podcast.fedoraproject.org',
-                'https://podcast.fedoraproject.org/',
-                'https://meet.google.com/jod-dkmw-ibd']
-            # https://pagure.io/fedocal/issue/213
-            data = {
-                'meeting_name': 'guess what?',
-                'meeting_date': TODAY,
-                'meeting_time_start': time(13, 0),
-                'meeting_time_stop': time(14, 0),
-                'meeting_timezone': 'Europe/Paris',
-                'meeting_location': None,
-                'frequency': '',
-                'csrf_token': csrf_token,
-            }
-
-            # Copy and paste works, but using:
-            #   for meet_location in meet_locations
-            # ...always fails on the second attempt.
-            import random
-            meet_location = random.choice(meet_locations)
-            with testing.mock_sends(schema.MeetingNewV1):
-                data['meeting_location'] = meet_location
-                output = self.app.post('/test_calendar/add/', data=data,
-                                       follow_redirects=True)
-                self.assertEqual(output.status_code, 200)
-                output_text = output.get_data(as_text=True)
-                self.assertIn(
-                    '<li class="message">Meeting added</li>', output_text)
+            meeting_locs.add('')
+            meeting_locs.add('https://unomaha.zoom.us/j/609939109')
+            meeting_locs.add('https://hangouts.google.com/hangouts/_/67zc3kvkovelxctlilphwodlp4e')
+            meeting_locs.add('https://meet.opensuse.org/epel')
+            meeting_locs.add('irc://irc.libera.chat/fedora-zh')
+            meeting_locs.add('https://meet.google.com/acq-pwxk-fhv')
+            meeting_locs.add('https://meet.google.com/mic-otnv-kse')
+            meeting_locs.add('https://meet.jit.si/fedora-websites-apps-meeting')
+            meeting_locs.add('https://meet.kde.org/b/ale-swq-39j')
+            meeting_locs.add('https://umich.zoom.us/j/96648123924?pwd=RitQVVQvMFVSaXJhNkFBS08vWTk0Zz09')
+            meeting_locs.add('https://umich.zoom.us/j/99842244394?pwd=YVdkQjJTdnpBMUkySGVzK1kyTGoyZz09')
+            meeting_locs.add('https://meet.google.com/xuj-jswy-hat')
+            meeting_locs.add('podcast.fedoraproject.org')
+            meeting_locs.add('https://podcast.fedoraproject.org/')
+            meeting_locs.add('https://meet.google.com/jod-dkmw-ibd')
+            for loc in meeting_locs:
+                _tst_add_meeting_loc(loc)
 
 
     def test_edit_meeting(self):

