Open
Conversation
Slashes aren't deemed necessary at start of URL patterns, but the actual check author recognized the too-strict approach for his check: https://stackoverflow.com/a/41450355
…ults to models.CASCADE.
Should probably integrate with django-celery-results and/or django-celery-beat
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Twitter authentication is no longer supported. This removes: - Twitter auth backend (twitter.py) - Twitter follow template - Twitter URL configuration - Twitter settings (API keys, DM tokens, etc.) - Twitter share button from social buttons - Twitter-related comments in LinkedIn module
* Add case-insensitive GitHub username matching at login time Done by allowing an auth system to declare that it is case insensitive. --------- Co-authored-by: Claude <noreply@anthropic.com>
…440) * add a devlogin auth method for dev mode only to make testing easier Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add CSV export for election audit log --------- Co-authored-by: Claude <noreply@anthropic.com>
* Prevent tabulation when votes are still pending verification When votes are cast, they are queued for asynchronous verification via Celery. If the queue is backed up, attempting to tally would exclude these pending votes. This change: - Adds num_pending_votes property to Election model to count unverified votes - Excludes quarantined votes from pending count (they are intentionally held) - Blocks the compute tally action when pending votes exist - Shows a warning on the compute tally page if votes are pending - Disables the tally button until all votes are verified - Provides clear error messaging --------- Co-authored-by: Claude <noreply@anthropic.com>
* Truncate email recipient names at 70 characters Add format_recipient() helper in helios_auth/utils.py to centralize email recipient formatting with 70-character name truncation. This prevents Python3's email module from choking on long names. The name is quoted per RFC 5322 to safely handle special characters. Updated all auth system backends to use the helper function. Added unit tests for the format_recipient helper. * Fix validate_email API for py3-validate-email compatibility Disable DNS and SMTP checks in validate_email calls to maintain compatibility with py3-validate-email package which has a different API than the original validate_email package. --------- Co-authored-by: Claude <noreply@anthropic.com>
These flags were incorrectly added to validate_email calls. The validate_email library handles DNS/SMTP checking appropriately by default.
* Audit and update dependencies for security and maintenance - Remove deprecated/unused packages: - boto (deprecated, superseded by boto3, django-ses uses boto3 internally) - unicodecsv (unnecessary on Python 3, not used in codebase) - oauth2client (deprecated Jan 2025, archived on GitHub) - Update outdated packages with security fixes: - celery: 5.4.0 → 5.6.1 (memory leak fixes, Python 3.14 support) - pycryptodome: 3.20.0 → 3.23.0 (timing attack fixes) - rollbar: 1.0.0 → 1.3.0 (credential sanitization fixes) - Add modern OAuth replacements: - google-auth + google-auth-oauthlib (replaces oauth2client for Google) - requests-oauthlib (for GitHub/GitLab OAuth flows) - requests (for Clever API calls) - Migrate OAuth implementations: - google.py: Use google_auth_oauthlib.flow.Flow - github.py: Use requests_oauthlib.OAuth2Session - gitlab.py: Use requests_oauthlib.OAuth2Session - clever.py: Use requests with HTTPBasicAuth * Remove Clever authentication system Clever auth appears to be unused/unmaintained. Removes: - helios_auth/auth_systems/clever.py - Clever settings from settings.py - Clever registration from auth_systems/__init__.py - Special case in tests for Clever's restricted can_create_election --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add admin user search feature This commit adds a new admin feature to search for users and view all their associated elections. Site administrators can now search for users by name or user ID and see: - Elections where the user is an administrator (creator or additional admin) - Elections where the user is a registered voter - Elections where the user is a trustee Changes: - Added user_search() view in helios/stats_views.py - Created stats_user_search.html template - Added /helios/stats/user-search route - Added link to user search in admin dashboard --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Migrate CI/CD from Travis CI to GitHub Actions Replace outdated Travis CI configuration with modern GitHub Actions workflow: - Use Python 3.12 (matching runtime.txt) - Test against PostgreSQL 14, 15, and 16 - Add pip caching for faster builds - Install required LDAP system dependencies --------- Co-authored-by: Claude <noreply@anthropic.com>
Update runtime.txt, CLAUDE.md, and GitHub Actions CI workflow to use Python 3.13. All 183 tests pass with the new version. Co-authored-by: Claude <noreply@anthropic.com>
Add a modular `can_add_voters_file()` method to the Election model that returns whether voter file uploads are allowed. Uploads are blocked when: - encrypted tally exists (encrypted_tally is set) - tallying has started (tallying_started_at is set) The method is used in both the view (to raise PermissionDenied) and the template (to show a disabled button with explanation). Note: We intentionally do NOT block on voting_ended_at because the admin can extend voting, so ending voting alone doesn't mean the election is truly closed. Co-authored-by: Claude <noreply@anthropic.com>
* Add dual timezone display (UTC + local) for all timestamps This change enhances timestamp display throughout Helios to show both UTC and the user's local timezone, improving usability for voters and administrators in different timezones. Changes: - Created JavaScript utility (timezone-display.js) to automatically convert UTC timestamps to show both UTC and local timezone - Added CSS styling (timezone-display.css) for professional display - Created Django template filter 'utc_time' to mark timestamps for conversion - Updated DateTimeLocalWidget to include timezone display assets - Enhanced base template to load timezone JS/CSS globally - Updated key templates (election_view, voters_list, etc.) to use the new timezone filter - DateTime input fields now show helper text with both timezones The solution is client-side JavaScript based, using the browser's timezone for local conversion. This requires no server-side changes to timezone handling and works seamlessly with existing UTC storage. --------- Co-authored-by: Claude <noreply@anthropic.com>
- Replace requirements.txt with pyproject.toml for modern dependency management - Add uv.lock for reproducible builds - Update INSTALL.md with uv installation instructions - Update CLAUDE.md commands to use uv run - Add .venv to .gitignore for uv's virtual environment Closes #458 Co-authored-by: Claude <noreply@anthropic.com>
Replace pip-style runtime.txt (python-3.13.11) with uv-style .python-version file (3.13) for Heroku Python version pinning. Only specifies major.minor version as requested. Co-authored-by: Claude <noreply@anthropic.com>
GitHub changed to expect comma-separated scopes instead of space-separated. The requests_oauthlib library joins scope lists with spaces by default, producing "read:user user:email", but GitHub now expects "read:user,user:email". Changed the scope parameter from a list to a comma-separated string to match GitHub's current requirements. Co-authored-by: Claude <noreply@anthropic.com>
* Propagate LinkedIn OAuth errors for debugging Remove bare except clauses that were silently swallowing errors during LinkedIn authentication. Previously, failures in get_request_token() would return None and errors in http_wrapper() would return empty strings, making it impossible to diagnose OAuth issues. Now exceptions propagate up to Django, allowing debug mode to display the full traceback with the actual error message. --------- Co-authored-by: Claude <noreply@anthropic.com>
* Migrate LinkedIn auth from OAuth 1.0a to OAuth 2.0 - Rewrite linkedin.py to use requests_oauthlib.OAuth2Session - Use LinkedIn's OpenID Connect userinfo endpoint for user data - Add CSRF protection with OAuth state parameter validation - Update settings to use LINKEDIN_CLIENT_ID and LINKEDIN_CLIENT_SECRET - Remove custom oauthclient directory (no longer needed) The custom OAuth 1.0a client was used solely for LinkedIn. Now that LinkedIn supports OAuth 2.0, we can use the same pattern as GitHub and other OAuth2 providers. --------- Co-authored-by: Claude <noreply@anthropic.com>
) Add include_client_id=True to fetch_token() call so that client_id and client_secret are sent as POST body parameters instead of in HTTP Basic Auth headers. LinkedIn's token endpoint expects credentials in the request body and returns "missing client_secret" when they are only sent via Basic Auth. Co-authored-by: Claude <noreply@anthropic.com>
LinkedIn returns scopes as comma-separated (e.g., "email,openid,profile") in token responses, but we were sending space-separated scopes. This caused the OAuth library's scope validation to fail due to format mismatch. Changed scope format to match LinkedIn's response format. Co-authored-by: Claude <noreply@anthropic.com>
- Renamed can_add_voters_file() to can_modify_voters() to better reflect that it controls both voter uploads and deletions - Refactored voter_delete view to reuse can_modify_voters() instead of duplicating the check logic - Updated voter list template to hide the delete [x] button when voter modifications are blocked, providing better UX - Updated template variable names: upload_disabled_reason -> modify_voters_disabled_reason for consistency Co-authored-by: Claude <noreply@anthropic.com>
* Fix button styling to use consistent Foundation CSS classes Updated action buttons throughout the application to use proper Foundation CSS button classes instead of default browser styling or inline style overrides. --------- Co-authored-by: Claude <noreply@anthropic.com>
) Completed brainstorming session. Design includes: - Lit 3.x web components with props-drilling state management - Crypto layer copied unchanged for independence - 4 implementation phases: setup, voting flow, crypto, polish - Runs at /booth2026/ alongside existing booth 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
* Add soft delete functionality for elections Implements soft delete for elections using a deleted_at timestamp. Elections marked as deleted are hidden from everyone except the site admins. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Add database index on election deleted_at field The deleted_at field is used by ElectionActiveManager to filter out soft-deleted elections on every query (deleted_at__isnull=True). Adding an index improves query performance. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Reduce PostgreSQL test matrix from versions 14, 15, 16 to just 16. This speeds up CI builds while still ensuring compatibility with the latest stable PostgreSQL release. Co-authored-by: Claude <noreply@anthropic.com>
Uses Django's conditional aggregation (filter=Q(...)) to correctly count and find the max cast_at only for votes within the cutoff period, and create a more efficient query. Co-authored-by: Claude <noreply@anthropic.com>
Based on analysis of query patterns across the codebase, add indexes to improve performance for common lookups: Priority 1 (Critical): - Voter.uuid: Used in get_by_election_and_uuid() for voter detail pages - CastVote(verified_at, invalidated_at): Used in num_pending_votes, admin dashboard, and verify_cast_votes background task - CastVote.vote_hash: Used in ballot verification lookups - Trustee.uuid: Used in trustee dashboard access Priority 2 (High): - Election.featured_p: Used in get_featured() for homepage display - ElectionLog(election, at): Used in audit log display with ordering Priority 3 (Medium): - AuditedBallot(election, vote_hash): Used in ballot audit lookups Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.