Select Git revision
security.py 4.98 KiB
"""
Helios Security -- mostly access control
Ben Adida (ben@adida.net)
"""
# nicely update the wrapper function
from functools import update_wrapper
from django.core.urlresolvers import reverse
from django.core.exceptions import *
from django.http import *
from django.conf import settings
from models import *
from auth.security import get_user
from django.http import HttpResponseRedirect
import urllib
import helios
# current voter
def get_voter(request, user, election):
"""
return the current voter
"""
voter = None
if request.session.has_key('CURRENT_VOTER'):
voter = request.session['CURRENT_VOTER']
if voter.election != election:
voter = None
if not voter:
if user:
voter = Voter.get_by_election_and_user(election, user)
return voter
# a function to check if the current user is a trustee
HELIOS_TRUSTEE_UUID = 'helios_trustee_uuid'
def get_logged_in_trustee(request):
if request.session.has_key(HELIOS_TRUSTEE_UUID):
return Trustee.get_by_uuid(request.session[HELIOS_TRUSTEE_UUID])
else:
return None
def set_logged_in_trustee(request, trustee):
request.session[HELIOS_TRUSTEE_UUID] = trustee.uuid
#
# 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:
if election.can_add_voters() != newvoters:
raise PermissionDenied()
def get_election_by_uuid(uuid):
if not uuid:
raise Exception("no election ID")
return Election.get_by_uuid(uuid)
# decorator for views that pertain to an election
# 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_uuid=None, *args, **kw):
election = get_election_by_uuid(election_uuid)
if not election:
raise Http404
# do checks
do_election_checks(election, checks)
# if private election, only logged in voters
if election.private_p and not checks.get('allow_logins',False):
from views import password_voter_login
if not user_can_see_election(request, election):
return_url = request.get_full_path()
return HttpResponseRedirect("%s?%s" % (reverse(password_voter_login, args=[election.uuid]), urllib.urlencode({
'return_url' : return_url
})))
return func(request, election, *args, **kw)
return update_wrapper(election_view_wrapper, func)
return election_view_decorator
def user_can_admin_election(user, election):
if not user:
return False
# election or site administrator
return election.admin == user or user.admin_p
def user_can_see_election(request, election):
user = get_user(request)
if not election.private_p:
return True
# election is private
# but maybe this user is the administrator?
if user_can_admin_election(user, election):
return True
# then this user has to be a voter
return (get_voter(request, user, election) != None)
def api_client_can_admin_election(api_client, election):
return election.api_client == api_client and api_client != None
# 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_uuid=None, *args, **kw):
election = get_election_by_uuid(election_uuid)
user = get_user(request)
if not user_can_admin_election(user, election):
raise PermissionDenied()
# do checks
do_election_checks(election, checks)
return func(request, election, *args, **kw)
return update_wrapper(election_admin_wrapper, func)
return election_admin_decorator
def trustee_check(func):
def trustee_check_wrapper(request, election_uuid, trustee_uuid, *args, **kwargs):
election = get_election_by_uuid(election_uuid)
trustee = Trustee.get_by_election_and_uuid(election, trustee_uuid)
if trustee == get_logged_in_trustee(request):
return func(request, election, trustee, *args, **kwargs)
else:
raise PermissionDenied()
return update_wrapper(trustee_check_wrapper, func)
def can_create_election(request):
user = get_user(request)
if not user:
return False
if helios.ADMIN_ONLY:
return user.admin_p
else:
return user != None
def user_can_feature_election(user, election):
if not user:
return False
return user.admin_p