Skip to content

Commit

Permalink
added checks for frozen elections and such with nice decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
benadida committed Dec 31, 2008
1 parent 7dbf664 commit 637bed2
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 57 deletions.
80 changes: 66 additions & 14 deletions helios/security.py
Expand Up @@ -10,6 +10,8 @@
from django.http import *

from models import *

from django.core.exceptions import *

# get authenticated user
def get_user(request):
Expand All @@ -18,26 +20,76 @@ def get_user(request):
else:
return None

#
# some common election checks
#
def do_election_checks(election, props):
# frozen
if props.has_key('frozen'):
frozen = props['frozen']
else:
frozen = None

# newvoters (open for registration)
if props.has_key('newvoters'):
newvoters = props['newvoters']
else:
newvoters = None

# frozen check
if frozen != None:
if frozen and not election.frozen_at:
raise PermissionDenied()
if not frozen and election.frozen_at:
raise PermissionDenied()

# open for new voters check
if newvoters != None:
import pdb; pdb.set_trace()
if election.can_add_voters() != newvoters:
raise PermissionDenied()


# decorator for views that pertain to an election
def election_view(func):
def election_view_wrapper(request, election_id, *args, **kw):
election = Election.objects.get(election_id = election_id)
# takes parameters:
# frozen - is the election frozen
# newvoters - does the election accept new voters
def election_view(**checks):

def election_view_decorator(func):
def election_view_wrapper(request, election_id, *args, **kw):
election = Election.objects.get(election_id = election_id)

# do checks
do_election_checks(election, checks)

return func(request, election, *args, **kw)
return func(request, election, *args, **kw)

return update_wrapper(election_view_wrapper, func)
return update_wrapper(election_view_wrapper, func)

return election_view_decorator

def user_can_admin_election(user, election):
return election.admin == user

# decorator for checking election admin access
def election_admin(func):
def election_admin_wrapper(request, election_id, *args, **kw):
election = Election.objects.get(election_id = election_id)

if not user_can_admin_election(get_user(request), election):
raise PermissionDenied()
# decorator for checking election admin access, and some properties of the election
# frozen - is the election frozen
# newvoters - does the election accept new voters
def election_admin(**checks):

def election_admin_decorator(func):
def election_admin_wrapper(request, election_id, *args, **kw):
election = Election.objects.get(election_id = election_id)

return func(request, election, *args, **kw)
if not user_can_admin_election(get_user(request), election):
raise PermissionDenied()

# do checks
do_election_checks(election, checks)

return func(request, election, *args, **kw)

return update_wrapper(election_admin_wrapper, func)
return update_wrapper(election_admin_wrapper, func)

return election_admin_decorator

85 changes: 42 additions & 43 deletions helios/views.py
Expand Up @@ -107,13 +107,16 @@ def election_single_ballot_verifier(request):
def election_js_api(request):
return render_template(request, "js_api")

@login_required
def election_new(request):
return render_template(request, "election_new")

@login_required
def election_new_2(request):
return render_template(request, "election_new_2", {'eg_params_json' : utils.to_json(ELGAMAL_PARAMS.toJSONDict()),
'name': request.GET['name'], 'election_type': request.GET['election_type']})


@login_required
def election_new_3(request):
"""
Create the new election.
Expand Down Expand Up @@ -175,58 +178,58 @@ def election_new_3(request):
## Specific election features
##

@election_admin
@election_admin()
def one_election_keyshares_manage(request, election):
return HttpResponse("election keyshares %s" % election.election_id)

@election_admin
@election_admin()
def one_election_keyshares_tally_manage(request, election):
return HttpResponse("election keyshares tally %s" % election.election_id)

@election_view
@election_view()
@json
def one_election(request, election):
return election.toElection().toJSONDict()

@election_view
@election_view()
def one_election_view(request, election):
user = get_user(request)
admin_p = user_can_admin_election(user, election)
election_obj = election.toElection()
return render_template(request, 'election_view', {'election' : election, 'election_obj' : election_obj, 'admin_p': admin_p})

@election_admin
@election_admin(frozen=True)
def one_election_open_submit(request, election):
return HttpResponse("election open submit %s" % election.election_id)

@election_view
@election_view()
@json
def one_election_result(request, election):
return election.result

@election_view
@election_view()
@json
def one_election_result_proof(request, election):
return election.decryption_proof


@election_view
@election_view()
@json
def one_election_get_voter_by_email(request, election):
return Voter.objects.get(election = election, email = request.GET['email']).toJSONDict()

@election_view
@election_view()
def one_election_get_voter_by_openid(request, election):
return HttpResponse("election get voter by openid %s" % election.election_id)

@election_view
@election_view(frozen=True)
def one_election_vote(request, election):
"""
UI to vote in an election
"""
return render_template(request, "vote", {'election': election})

@election_view
@election_view(frozen=True)
def one_election_bboard(request, election):
"""
UI to show election bboard
Expand Down Expand Up @@ -257,21 +260,19 @@ def one_election_bboard(request, election):
'next_offset': next_offset, 'voter_email': request.GET.get('voter_email', ''),
'offset_plus_one': offset+1, 'offset_plus_limit': offset+limit})

@election_admin
@election_admin(frozen=False)
def one_election_set_pk(request, election):
return HttpResponse("election set pk %s" % election.election_id)

@election_admin
@election_admin()
def one_election_voters_manage(request, election):
voters = election.get_voters()
voters_json = utils.to_json([v.toJSONDict() for v in voters])

return render_template(request, "election_voters_manage", {'voters_json' : voters_json, 'voters': voters,'election': election})

@election_admin
@election_admin(newvoters=True)
def one_election_voters_bulk_upload(request, election):
# FIXME: check if either open reg or not frozen

voters_csv_lines = request.POST['voters_csv'].split("\n")
reader = csv.reader(voters_csv_lines)

Expand All @@ -293,10 +294,8 @@ def one_election_voters_bulk_upload(request, election):

return HttpResponseRedirect("./voters_manage")

@election_admin
@election_admin(frozen=False)
def one_election_voters_delete(request, election):
## FIXME: check if election is frozen and can have voter deletion

voter_id_list = request.POST['voter_ids'].split(",")
voters = [Voter.objects.get(voter_id = voter_id) for voter_id in voter_id_list]
for voter in voters:
Expand All @@ -308,7 +307,7 @@ def one_election_voters_delete(request, election):

return SUCCESS

@election_admin
@election_admin(frozen=True)
def one_election_voters_email(request, election):
if request.POST.has_key('voter_ids'):
voter_id_list = request.POST['voter_ids'].split(",")
Expand All @@ -321,7 +320,7 @@ def one_election_voters_email(request, election):

return render_template(request, 'voters_email', {'voter_ids' : request.POST['voter_ids'], 'voters': voters, 'election': election})

@election_admin
@election_admin(frozen=True)
def one_election_voters_email_2(request, election):
after = request.POST.get('after', None)
limit = request.POST.get('limit', None)
Expand Down Expand Up @@ -402,7 +401,7 @@ def one_election_voters_email_2(request, election):
# hack for now, no more batching
return HttpResponse(last_id or "DONE")

@election_admin
@election_admin(frozen=False)
def one_election_set_reg(request, election):
"""
Set whether this is open registration or not
Expand All @@ -416,7 +415,7 @@ def one_election_set_reg(request, election):
else:
return SUCCESS

@election_admin
@election_admin()
def one_election_archive(request, election):

archive_p = request.GET.get('archive_p', True)
Expand All @@ -429,19 +428,19 @@ def one_election_archive(request, election):

return HttpResponseRedirect('./view')

@election_admin
@election_admin(frozen=False)
def one_election_build(request, election):
return render_template(request, 'election_build', {'election': election})

@election_admin
@election_admin(frozen=False)
def one_election_save_questions(request, election):
election.questions = utils.from_json(request.POST['questions_json']);
election.save()

# always a machine API
return SUCCESS

@election_admin
@election_admin(frozen=False)
def one_election_freeze(request, election):
if request.method == "GET":
return render_template(request, 'election_freeze', {'election': election})
Expand All @@ -453,19 +452,19 @@ def one_election_freeze(request, election):
else:
return SUCCESS

@election_admin
@election_admin()
def one_election_email_trustees(request, election):
pass

@election_admin
@election_admin(frozen=True)
def one_election_compute_tally(request, election):
return HttpResponse("election compute tally %s" % election.election_id)

@election_admin
@election_admin(frozen=True)
def one_election_drive_tally_chunk(request, election):
return HttpResponse("election drive tally chunk %s" % election.election_id)

@election_admin
@election_admin(frozen=True)
def one_election_drive_tally(request, election):
"""
JavaScript-based driver for the entire tallying process, now done in JavaScript.
Expand All @@ -481,7 +480,7 @@ def one_election_drive_tally(request, election):

return render_template(request, 'drive_tally', {'election': election, 'election_pk_json' : election_pk_json, 'election_sk_json' : election_sk_json})

@election_admin
@election_admin(frozen=True)
def one_election_set_tally(request, election):
"""
Set the tally and proof.
Expand All @@ -491,12 +490,12 @@ def one_election_set_tally(request, election):
election.save()
return SUCCESS

@election_admin
@election_admin(frozen=True)
def one_election_compute_tally_chunk(request, election):
return HttpResponse("election compute tally chunk %s" % election.election_id)

# Individual Voters
@election_view
@election_view()
@json
def voter_list(request, election):
# normalize limit
Expand All @@ -507,7 +506,7 @@ def voter_list(request, election):
return [v.toJSONDict(with_vote=request.GET.get('with_vote')) for v in voters]


@election_admin
@election_admin(newvoters=True)
def voter_add(request, election):
v = Voter.objects.create(election = election, email = request.POST['email'], name = request.POST['name'],
category = request.POST['category'])
Expand All @@ -516,7 +515,7 @@ def voter_add(request, election):

return HttpResponseRedirect("../voters_manage")

@election_view
@election_view()
@json
def one_voter(request, election, voter_id):
"""
Expand All @@ -525,11 +524,11 @@ def one_voter(request, election, voter_id):
voter = Voter.objects.get(voter_id = voter_id)
return voter.toJSONDict(with_vote=True)

@election_admin
@election_admin(frozen=False)
def one_voter_delete(request, election, voter_id):
return HttpResponse("voter delete for election %s" % election.election_id)

@election_view
@election_view(frozen=True)
def one_voter_submit(request, election, voter_id):
election_obj = election.toElection()

Expand Down Expand Up @@ -570,25 +569,25 @@ def one_voter_submit(request, election, voter_id):
return SUCCESS

# Trustees
@election_view
@election_view()
@json
def trustees_list(request, election):
keyshares = election.get_keyshares()
return [k.toJSONDict() for k in keyshares]

@election_view
@election_view()
def trustee_home(request, election, trustee_email):
return HttpResponse("trustees home for election %s" % election.election_id)

@election_view
@election_view(frozen=False)
def trustee_upload_pk(request, election, trustee_email):
return HttpResponse("trustees upload pk for election %s" % election.election_id)

@election_view
@election_view(frozen=True)
def trustee_tally(request, election, trustee_email):
return HttpResponse("trustees tally for election %s" % election.election_id)

@election_view
@election_view(frozen=True)
def trustee_upload_decryption_factor(request, election, trustee_email):
return HttpResponse("trustees upload dec factor for election %s" % election.election_id)

0 comments on commit 637bed2

Please sign in to comment.