You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@steve.apache.org by gs...@apache.org on 2026/02/20 11:50:49 UTC
(steve) branch trunk updated (600b33f -> 1caa49b)
This is an automated email from the ASF dual-hosted git repository.
gstein pushed a change to branch trunk
in repository https://gitbox.apache.org/repos/asf/steve.git
from 600b33f style: rename do_vote route to do-vote with dash
new cc6eaa3 feat: allow recasting ballots without warning
new 1caa49b refactor: update voting to use form-based submission with submitFormWithLoading
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
v3/TODO.md | 12 +++++++++++-
v3/server/pages.py | 21 +++++++++++----------
v3/server/templates/vote-on.ezt | 29 ++++++++---------------------
3 files changed, 30 insertions(+), 32 deletions(-)
(steve) 01/02: feat: allow recasting ballots without warning
Posted by gs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
gstein pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/steve.git
commit cc6eaa3821c34068c409ede7fb7b3667441c5fa0
Author: Greg Stein <gs...@gmail.com>
AuthorDate: Fri Feb 20 05:08:03 2026 -0600
feat: allow recasting ballots without warning
Co-authored-by: aider (openrouter/x-ai/grok-code-fast-1) <ai...@aider.chat>
---
v3/server/pages.py | 6 ------
1 file changed, 6 deletions(-)
diff --git a/v3/server/pages.py b/v3/server/pages.py
index da65fa9..83a4e31 100644
--- a/v3/server/pages.py
+++ b/v3/server/pages.py
@@ -391,12 +391,6 @@ async def do_vote_endpoint(election):
await flash_danger(f'Invalid issue ID: {iid}')
return quart.redirect(f'/vote-on/{election.eid}', code=303)
- # Check if already voted on this issue
- voted_upon = election.has_voted_upon(result.uid)
- if voted_upon.get(iid, False):
- await flash_warning(f'Already voted on issue {iid}; vote not updated.')
- continue
-
try:
election.add_vote(result.uid, iid, votestring)
_LOGGER.info(f'User[U:{result.uid}] voted on issue[I:{iid}] in election[E:{election.eid}]')
(steve) 02/02: refactor: update voting to use form-based submission with submitFormWithLoading
Posted by gs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
gstein pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/steve.git
commit 1caa49b1ea136209a5b9a74cf6da3a3a2f64ff67
Author: Greg Stein <gs...@gmail.com>
AuthorDate: Fri Feb 20 05:49:34 2026 -0600
refactor: update voting to use form-based submission with submitFormWithLoading
Co-authored-by: aider (openrouter/x-ai/grok-code-fast-1) <ai...@aider.chat>
---
v3/TODO.md | 12 +++++++++++-
v3/server/pages.py | 15 +++++++++++----
v3/server/templates/vote-on.ezt | 29 ++++++++---------------------
3 files changed, 30 insertions(+), 26 deletions(-)
diff --git a/v3/TODO.md b/v3/TODO.md
index ddbd3ee..dcc1129 100644
--- a/v3/TODO.md
+++ b/v3/TODO.md
@@ -39,4 +39,14 @@ Based on a review of `v3/server/pages.py` (and related templates like `voter.ezt
- **Imports/Constants**: All seem correct and follow conventions.
- **No Obvious Syntax/Logic Errors**: The code parses and runs logically, but the above are functional gaps.
-If you'd like to implement any of these fixes (e.g., add the date endpoints or fix upcoming elections), provide confirmation and details. Let me know if you have more context or want me to check specific sections!
+If you'd like to implement any of these fixes (e.g., add the date endpoints or fix upcoming elections), provide confirmation and details. Let me know if you have more context or want to check specific sections!
+
+## 8. CSRF Checking
+- **Issue**: CSRF tokens are placeholders and not validated in POST endpoints.
+- **Impact**: Vulnerable to CSRF attacks.
+- **Suggested Fix**: Implement a decorator to check CSRF tokens on POST endpoints (e.g., compare form/session token). Generate real tokens per session.
+
+## 9. Error Handling in `submitFormWithLoading`
+- **Issue**: If the server returns an error during form submission via `submitFormWithLoading`, the page doesn't reload, and the button stays disabled, potentially confusing users.
+- **Impact**: Poor UX on submission failures.
+- **Suggested Fix**: Investigate and add client-side error handling (e.g., re-enable button on failure, show error message).
diff --git a/v3/server/pages.py b/v3/server/pages.py
index 83a4e31..7b160bf 100644
--- a/v3/server/pages.py
+++ b/v3/server/pages.py
@@ -375,18 +375,25 @@ async def do_vote_endpoint(election):
### check authz
- # Parse the JSON payload
- data = await quart.request.get_json()
- if not data:
+ # Parse the form data
+ form = edict(await quart.request.form)
+ if not form:
await flash_danger('No vote data provided.')
return quart.redirect(f'/vote-on/{election.eid}', code=303)
+ # Extract votes from form (keys like 'vote-<iid>')
+ votes = {}
+ for key, value in form.items():
+ if key.startswith('vote-'):
+ iid = key.split('-', 1)[1]
+ votes[iid] = value
+
# Get the list of issues for this election
issues = election.list_issues()
issue_dict = {i.iid: i for i in issues}
# Process each vote
- for iid, votestring in data.items():
+ for iid, votestring in votes.items():
if iid not in issue_dict:
await flash_danger(f'Invalid issue ID: {iid}')
return quart.redirect(f'/vote-on/{election.eid}', code=303)
diff --git a/v3/server/templates/vote-on.ezt b/v3/server/templates/vote-on.ezt
index f46cab0..9c1e4fd 100644
--- a/v3/server/templates/vote-on.ezt
+++ b/v3/server/templates/vote-on.ezt
@@ -21,6 +21,10 @@
</button>
</div>
+ <form id="voteForm" method="POST" action="/do-vote/[eid]">
+ <!-- CSRF token for form submission -->
+ <input type="hidden" name="csrf_token" value="[csrf_token]">
+
<div id="issues-list" class="list-group">
[for issues]
<div class="list-group-item issue-item">
@@ -51,8 +55,9 @@
<!-- Submit Button -->
<div class="mt-4">
- <button type="button" class="btn btn-primary" onclick="submitVotes()">Submit Votes</button>
+ <button type="button" class="btn btn-primary" id="submitVoteBtn" onclick="submitVotes()">Submit Votes</button>
</div>
+ </form>
</div>
</div>
@@ -105,7 +110,7 @@
// Submit votes
function submitVotes() {
const votes = {};
- [# careful! be wary of open-brackets within ezt ]
+ // careful! be wary of open-brackets within ezt
document.querySelectorAll('.vote-radio input[[]type="radio"]:checked').forEach(radio => {
const issueId = radio.name.split('-')[[]1];
votes[[]issueId] = radio.value;
@@ -116,24 +121,6 @@
return;
}
- fetch('/do-vote/[eid]', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(votes),
- })
- .then(response => {
- if (!response.ok) throw new Error('Network response was not ok');
- return response.json();
- })
- .then(data => {
- alert('Votes submitted successfully!');
- console.log('Server response:', data);
- })
- .catch(error => {
- alert('Error submitting votes: ' + error.message);
- console.error('Error:', error);
- });
+ submitFormWithLoading('voteForm', 'submitVoteBtn', 'Submitting Votes...');
}
</script>