tickets #152993
openCannot delete voter on Helios election platform
0%
Description
Hello,
We are currently running the openSUSE Board Election on the Helios election platform.
We need to delete a voter and then re-issue a voter crendential for the latter.
When deleting the voter, Helios displays the following error (also see attached screenshot):
Environment:
Request Method: GET
Request URL: https://elections.opensuse.org/helios/elections/b53b657a-ee2c-4752-aa95-4773ee2bc288/voters/5aed22c9-7eee-4a15-95c9-0fdcfd85fcaf/delete
Django Version: 1.11.29
Python Version: 3.6.15
Installed Applications:
('django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'helios_auth',
'helios',
'server_ui')
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'helios.security.HSTSMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware']
Traceback:
File "/usr/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/usr/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/usr/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "./helios/security.py" in election_admin_wrapper
182. return func(request, election, *args, **kw)
File "./helios/views.py" in voter_delete
890. voter.user.send_message(subject, body)
Exception Type: AttributeError at /helios/elections/b53b657a-ee2c-4752-aa95-4773ee2bc288/voters/5aed22c9-7eee-4a15-95c9-0fdcfd85fcaf/delete
Exception Value: 'NoneType' object has no attribute 'send_message
Grateful if you can look into the matter and advise.
Regards,
Ish Sookun
// On behalf of the Election Committee
Files
Updated by cboltz 11 months ago
Hmm, that's interesting[tm].
The function is (most comments removed, and some ### comments added)
def voter_delete(request, election, voter_uuid):
if election.encrypted_tally:
raise PermissionDenied()
voter = Voter.get_by_election_and_uuid(election, voter_uuid)
if voter: ### voter found
if voter.vote_hash: ### user has voted
# send email to voter
subject = "Vote removed"
body = "Your vote were removed from the election %s." % (election.name) ### message text shortened for readability
voter.user.send_message(subject, body) ### the line triggering the error -> "user" seems to be None.
### code execution aborts here
# log it
election.append_log("Voter %s/%s and their vote were removed after election frozen" % (voter.voter_type,voter.voter_id))
elif election.frozen_at:
# log it
election.append_log("Voter %s/%s removed after election frozen" % (voter.voter_type,voter.voter_id))
voter.delete()
return HttpResponseRedirect(settings.SECURE_URL_HOST + reverse(voters_list_pretty, args=[election.uuid]))
voter.user
is only used for sending the notification mail, therefore a possible workaround might be to comment out the line that sends the notification mail. However, I'm not the biggest fan of doing hotfixes during a running election (at least it would only be in an administrative function that voters never use, so the risk is quite low).
Let me ask first:
We need to delete a voter and then re-issue a voter crendential for the latter.
That sounds like someone accidentally voted for a wrong person.
The question might sounds too easy, but - is the voter aware that they can just submit a new ballot which will replace the first one?
If the problem is more interesting[tm], I'd be interested in a few details ;-)
Please also tell me if I should apply the workaround (disabling the notification mail) so that you can continue with your original plan of deleting and re-creating the voter.
Updated by Ishwon 11 months ago
A voter accidentally shared the voter credential received by Helios, when replying to the email and cc'ing the project mailing list. Anybody else from the mailing list can now use that credential to submit a ballot for that voter.
Okay for the workaround, since there is no other way to invalidate that vote on Helios.
Updated by Ishwon 11 months ago
I got the same error when deleting the voter:
AttributeError at /helios/elections/b53b657a-ee2c-4752-aa95-4773ee2bc288/voters/5aed22c9-7eee-4a15-95c9-0fdcfd85fcaf/delete
'NoneType' object has no attribute 'send_message'
Request Method: GET
Request URL: https://elections.opensuse.org/helios/elections/b53b657a-ee2c-4752-aa95-4773ee2bc288/voters/5aed22c9-7eee-4a15-95c9-0fdcfd85fcaf/delete
Django Version: 1.11.29
Exception Type: AttributeError
Exception Value:
'NoneType' object has no attribute 'send_message'
Exception Location: ./helios/views.py in voter_delete, line 890
Python Executable: /usr/sbin/uwsgi
Python Version: 3.6.15
Python Path:
['/usr/lib/python3.6/site-packages/helios-server',
'.',
'',
'/usr/lib/python36.zip',
'/usr/lib64/python3.6',
'/usr/lib64/python3.6/lib-dynload',
'/usr/lib64/python3.6/site-packages',
'/usr/lib64/python3.6/site-packages/PIL',
'/usr/lib64/python3.6/_import_failed',
'/usr/lib/python3.6/site-packages']
Server time: Tue, 2 Jan 2024 21:29:42 +0000
Updated by cboltz 11 months ago
Turns out there's another helios/views.py: /usr/lib/python3.6/site-packages/helios-server/helios/views.py - and this seems to be the one that is actually used.
I've also applied the workaround there.
[Note to myself: we'll have to clean up the server (or, easier: re-deploy with salt) after the elections.]
Updated by cboltz 11 months ago
Thanks for the update! I'm glad it worked.
I've re-enabled the [attempt to] mail the user. In case you need to delete another voter and hit the same issue again, I can of course apply the workaround again.
I'll leave the ticket open for the server cleanup and a possible helios update - but that has to wait until the election is done.