From e027627a5d6dbf3aa30f724bbe68aabad1767c55 Mon Sep 17 00:00:00 2001 From: AyushShukla1807 Date: Sat, 21 Mar 2026 18:00:26 +0530 Subject: [PATCH 1/5] Fix 500 error and CORS drop on empty round creation payloads This commit patches the admin_endpoints validation to gracefully handle empty POST bodies, and modifies MessageMiddleware to intercept MontageErrors so they correctly return 400 Bad Request JSON instead of bypassing CORS headers. Resolves Issue #357. --- montage/admin_endpoints.py | 2 ++ montage/mw/__init__.py | 30 ++++++++++++++++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/montage/admin_endpoints.py b/montage/admin_endpoints.py index a4f608d1..f2019c05 100644 --- a/montage/admin_endpoints.py +++ b/montage/admin_endpoints.py @@ -461,6 +461,8 @@ def cancel_campaign(user_dao, campaign_id): def _prepare_round_params(coord_dao, request_dict): rnd_dict = {} + if not request_dict: + request_dict = {} req_columns = ['jurors', 'name', 'vote_method', 'deadline_date'] extra_columns = ['description', 'config', 'directions', 'show_stats'] valid_vote_methods = ['ranking', 'rating', 'yesno'] diff --git a/montage/mw/__init__.py b/montage/mw/__init__.py index 773c6723..bb3cc287 100644 --- a/montage/mw/__init__.py +++ b/montage/mw/__init__.py @@ -63,16 +63,26 @@ def endpoint(self, next, response_dict, request, _route): try: ret = next() except Exception as e: - if self.debug_errors and not isinstance(e, MontageError): - import pdb; pdb.post_mortem() - import pdb;pdb.set_trace() - if self.raise_errors: - raise - ret = None - exc_info = ExceptionInfo.from_current() - err = '%s: %s' % (exc_info.exc_type, exc_info.exc_msg) - response_dict['errors'].append(err) - response_dict['status'] = 'exception' + if isinstance(e, MontageError): + err = str(e) + # Some clastic errors like BadRequest have a description property + if hasattr(e, 'description') and e.description: + err = e.description + response_dict['errors'].append(err) + response_dict['status'] = 'failure' + response_dict['_status_code'] = getattr(e, 'code', getattr(e, 'status_code', 400)) + ret = None + else: + if self.debug_errors: + import pdb; pdb.post_mortem() + if self.raise_errors: + raise + ret = None + exc_info = ExceptionInfo.from_current() + err = '%s: %s' % (exc_info.exc_type, exc_info.exc_msg) + response_dict['errors'].append(err) + response_dict['status'] = 'exception' + response_dict['_status_code'] = 500 else: status_code = response_dict.pop('_status_code', None) if response_dict.get('errors'): From f6450bbcbd178f98602b0add5f59d48e93bdd068 Mon Sep 17 00:00:00 2001 From: AyushShukla1807 Date: Sat, 21 Mar 2026 18:13:52 +0530 Subject: [PATCH 2/5] Fix TypeError on rapid clicking during voting (Issue #206) Bind :disabled='isLoading' on vote buttons to block concurrent clicks at DOM level before Vue's async re-render cycle can prevent them. --- frontend/src/components/Vote/VoteRating.vue | 4 ++-- frontend/src/components/Vote/VoteYesNo.vue | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/Vote/VoteRating.vue b/frontend/src/components/Vote/VoteRating.vue index 80c26ceb..2d2d93aa 100644 --- a/frontend/src/components/Vote/VoteRating.vue +++ b/frontend/src/components/Vote/VoteRating.vue @@ -57,7 +57,7 @@
- + @@ -85,7 +85,7 @@
- + {{ $t('montage-vote-skip') }} diff --git a/frontend/src/components/Vote/VoteYesNo.vue b/frontend/src/components/Vote/VoteYesNo.vue index 66e15503..8107efa9 100644 --- a/frontend/src/components/Vote/VoteYesNo.vue +++ b/frontend/src/components/Vote/VoteYesNo.vue @@ -56,10 +56,10 @@
- + {{ $t('montage-vote-accept') }} - + {{ $t('montage-vote-decline') }}
@@ -86,7 +86,7 @@
- + {{ $t('montage-vote-skip') }} From 32807f2fd2a065487bdd58fafb58b32b2b932179 Mon Sep 17 00:00:00 2001 From: AyushShukla1807 Date: Sat, 21 Mar 2026 18:18:19 +0530 Subject: [PATCH 3/5] Fix voting statistics not displayed when show_stats is enabled (Issue #325) getRoundVotesStats was defined in jurorService but never called. Added onMounted fetch and post-vote refresh in VoteRating.vue and VoteYesNo.vue, with conditional rendering when round.show_stats is true. --- frontend/src/components/Vote/VoteRating.vue | 51 ++++++++++++++++++++- frontend/src/components/Vote/VoteYesNo.vue | 25 +++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Vote/VoteRating.vue b/frontend/src/components/Vote/VoteRating.vue index 2d2d93aa..efa8c29a 100644 --- a/frontend/src/components/Vote/VoteRating.vue +++ b/frontend/src/components/Vote/VoteRating.vue @@ -70,6 +70,16 @@
+ +

{{ $t('montage-vote-actions') }}

@@ -166,7 +176,7 @@ diff --git a/frontend/src/components/Vote/VoteYesNo.vue b/frontend/src/components/Vote/VoteYesNo.vue index 8107efa9..1410b08e 100644 --- a/frontend/src/components/Vote/VoteYesNo.vue +++ b/frontend/src/components/Vote/VoteYesNo.vue @@ -71,6 +71,16 @@
+ +

{{ $t('montage-vote-actions') }}

@@ -170,7 +180,7 @@