Skip to content
Snippets Groups Projects
Select Git revision
  • 56d3ab18268f532498f5d68797ab9b6fd393c7fb
  • test default
  • master protected
3 results

models.py

Blame
  • 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