<s> """<STR_LIT>""" <EOL> from django . db import models , transaction <EOL> import json <EOL> from django . conf import settings <EOL> from django . core . mail import send_mail <EOL> import datetime , logging , uuid , random , io <EOL> import bleach <EOL> from crypto import electionalgs , algs , utils <EOL> from helios import utils as heliosutils <EOL> import helios . views <EOL> from helios import datatypes <EOL> from helios_auth . models import User , AUTH_SYSTEMS <EOL> from helios_auth . jsonfield import JSONField <EOL> from helios . datatypes . djangofield import LDObjectField <EOL> import csv , copy <EOL> import unicodecsv <EOL> class HeliosModel ( models . Model , datatypes . LDObjectContainer ) : <EOL> class Meta : <EOL> abstract = True <EOL> class Election ( HeliosModel ) : <EOL> admin = models . ForeignKey ( User ) <EOL> uuid = models . CharField ( max_length = <NUM_LIT:50> , null = False ) <EOL> datatype = models . CharField ( max_length = <NUM_LIT> , null = False , default = "<STR_LIT>" ) <EOL> short_name = models . CharField ( max_length = <NUM_LIT:100> ) <EOL> name = models . CharField ( max_length = <NUM_LIT> ) <EOL> ELECTION_TYPES = ( <EOL> ( '<STR_LIT>' , '<STR_LIT>' ) , <EOL> ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> ) <EOL> election_type = models . CharField ( max_length = <NUM_LIT> , null = False , default = '<STR_LIT>' , choices = ELECTION_TYPES ) <EOL> private_p = models . BooleanField ( default = False , null = False ) <EOL> description = models . TextField ( ) <EOL> public_key = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> private_key = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> questions = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> eligibility = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> openreg = models . BooleanField ( default = False ) <EOL> featured_p = models . BooleanField ( default = False ) <EOL> use_voter_aliases = models . BooleanField ( default = False ) <EOL> use_advanced_audit_features = models . BooleanField ( default = True , null = False ) <EOL> randomize_answer_order = models . BooleanField ( default = False , null = False ) <EOL> cast_url = models . CharField ( max_length = <NUM_LIT> ) <EOL> created_at = models . DateTimeField ( auto_now_add = True ) <EOL> modified_at = models . DateTimeField ( auto_now_add = True ) <EOL> frozen_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> archived_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> registration_starts_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> voting_starts_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> voting_ends_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> complaint_period_ends_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> tallying_starts_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> voting_started_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> voting_extended_until = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> voting_ended_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> tallying_started_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> tallying_finished_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> tallies_combined_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> result_released_at = models . DateTimeField ( auto_now_add = False , default = None , null = True ) <EOL> voters_hash = models . CharField ( max_length = <NUM_LIT:100> , null = True ) <EOL> encrypted_tally = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> result = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> result_proof = JSONField ( null = True ) <EOL> help_email = models . EmailField ( null = True ) <EOL> election_info_url = models . CharField ( max_length = <NUM_LIT> , null = True ) <EOL> @ property <EOL> def metadata ( self ) : <EOL> return { <EOL> '<STR_LIT>' : self . help_email or '<STR_LIT>' , <EOL> '<STR_LIT>' : self . private_p , <EOL> '<STR_LIT>' : self . use_advanced_audit_features , <EOL> '<STR_LIT>' : self . randomize_answer_order <EOL> } <EOL> @ property <EOL> def pretty_type ( self ) : <EOL> return dict ( self . ELECTION_TYPES ) [ self . election_type ] <EOL> @ property <EOL> def num_cast_votes ( self ) : <EOL> return self . voter_set . exclude ( vote = None ) . count ( ) <EOL> @ property <EOL> def num_voters ( self ) : <EOL> return self . voter_set . count ( ) <EOL> @ property <EOL> def num_trustees ( self ) : <EOL> return self . trustee_set . count ( ) <EOL> @ property <EOL> def last_alias_num ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . use_voter_aliases : <EOL> return None <EOL> return heliosutils . one_val_raw_sql ( "<STR_LIT>" + Voter . _meta . db_table + "<STR_LIT>" , [ self . id ] ) or <NUM_LIT:0> <EOL> @ property <EOL> def encrypted_tally_hash ( self ) : <EOL> if not self . encrypted_tally : <EOL> return None <EOL> return utils . hash_b64 ( self . encrypted_tally . toJSON ( ) ) <EOL> @ property <EOL> def is_archived ( self ) : <EOL> return self . archived_at != None <EOL> @ property <EOL> def description_bleached ( self ) : <EOL> return bleach . clean ( self . description , tags = bleach . ALLOWED_TAGS + [ '<STR_LIT:p>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:u>' ] ) <EOL> @ classmethod <EOL> def get_featured ( cls ) : <EOL> return cls . objects . filter ( featured_p = True ) . order_by ( '<STR_LIT>' ) <EOL> @ classmethod <EOL> def get_or_create ( cls , ** kwargs ) : <EOL> return cls . objects . get_or_create ( short_name = kwargs [ '<STR_LIT>' ] , defaults = kwargs ) <EOL> @ classmethod <EOL> def get_by_user_as_admin ( cls , user , archived_p = None , limit = None ) : <EOL> query = cls . objects . filter ( admin = user ) <EOL> if archived_p == True : <EOL> query = query . exclude ( archived_at = None ) <EOL> if archived_p == False : <EOL> query = query . filter ( archived_at = None ) <EOL> query = query . order_by ( '<STR_LIT>' ) <EOL> if limit : <EOL> return query [ : limit ] <EOL> else : <EOL> return query <EOL> @ classmethod <EOL> def get_by_user_as_voter ( cls , user , archived_p = None , limit = None ) : <EOL> query = cls . objects . filter ( voter__user = user ) <EOL> if archived_p == True : <EOL> query = query . exclude ( archived_at = None ) <EOL> if archived_p == False : <EOL> query = query . filter ( archived_at = None ) <EOL> query = query . order_by ( '<STR_LIT>' ) <EOL> if limit : <EOL> return query [ : limit ] <EOL> else : <EOL> return query <EOL> @ classmethod <EOL> def get_by_uuid ( cls , uuid ) : <EOL> try : <EOL> return cls . objects . select_related ( ) . get ( uuid = uuid ) <EOL> except cls . DoesNotExist : <EOL> return None <EOL> @ classmethod <EOL> def get_by_short_name ( cls , short_name ) : <EOL> try : <EOL> return cls . objects . get ( short_name = short_name ) <EOL> except cls . DoesNotExist : <EOL> return None <EOL> def add_voters_file ( self , uploaded_file ) : <EOL> """<STR_LIT>""" <EOL> new_voter_file = VoterFile ( election = self , voter_file_content = uploaded_file . read ( ) ) <EOL> new_voter_file . save ( ) <EOL> self . append_log ( ElectionLog . VOTER_FILE_ADDED ) <EOL> return new_voter_file <EOL> def user_eligible_p ( self , user ) : <EOL> """<STR_LIT>""" <EOL> if not self . openreg : <EOL> return False <EOL> if self . eligibility == None : <EOL> return True <EOL> for eligibility_case in self . eligibility : <EOL> if user . is_eligible_for ( eligibility_case ) : <EOL> return True <EOL> return False <EOL> def eligibility_constraint_for ( self , user_type ) : <EOL> if not self . eligibility : <EOL> return [ ] <EOL> relevant_constraints = [ constraint [ '<STR_LIT>' ] for constraint in self . eligibility if constraint [ '<STR_LIT>' ] == user_type and constraint . has_key ( '<STR_LIT>' ) ] <EOL> if len ( relevant_constraints ) > <NUM_LIT:0> : <EOL> return relevant_constraints [ <NUM_LIT:0> ] <EOL> else : <EOL> return [ ] <EOL> def eligibility_category_id ( self , user_type ) : <EOL> "<STR_LIT>" <EOL> if not self . eligibility : <EOL> return None <EOL> constraint_for = self . eligibility_constraint_for ( user_type ) <EOL> if len ( constraint_for ) > <NUM_LIT:0> : <EOL> constraint = constraint_for [ <NUM_LIT:0> ] <EOL> return AUTH_SYSTEMS [ user_type ] . eligibility_category_id ( constraint ) <EOL> else : <EOL> return None <EOL> @ property <EOL> def pretty_eligibility ( self ) : <EOL> if not self . eligibility : <EOL> return "<STR_LIT>" <EOL> else : <EOL> return_val = "<STR_LIT>" <EOL> for constraint in self . eligibility : <EOL> if constraint . has_key ( '<STR_LIT>' ) : <EOL> for one_constraint in constraint [ '<STR_LIT>' ] : <EOL> return_val += "<STR_LIT>" % AUTH_SYSTEMS [ constraint [ '<STR_LIT>' ] ] . pretty_eligibility ( one_constraint ) <EOL> else : <EOL> return_val += "<STR_LIT>" % constraint [ '<STR_LIT>' ] <EOL> return_val += "<STR_LIT>" <EOL> return return_val <EOL> def voting_has_started ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . frozen_at != None and ( self . voting_starts_at == None or ( datetime . datetime . utcnow ( ) >= ( self . voting_started_at or self . voting_starts_at ) ) ) <EOL> def voting_has_stopped ( self ) : <EOL> """<STR_LIT>""" <EOL> voting_end = self . voting_ended_at or self . voting_extended_until or self . voting_ends_at <EOL> return ( voting_end != None and datetime . datetime . utcnow ( ) >= voting_end ) or self . encrypted_tally <EOL> @ property <EOL> def issues_before_freeze ( self ) : <EOL> issues = [ ] <EOL> if self . questions == None or len ( self . questions ) == <NUM_LIT:0> : <EOL> issues . append ( <EOL> { '<STR_LIT:type>' : '<STR_LIT>' , <EOL> '<STR_LIT:action>' : "<STR_LIT>" } <EOL> ) <EOL> trustees = Trustee . get_by_election ( self ) <EOL> if len ( trustees ) == <NUM_LIT:0> : <EOL> issues . append ( { <EOL> '<STR_LIT:type>' : '<STR_LIT>' , <EOL> '<STR_LIT:action>' : "<STR_LIT>" <EOL> } ) <EOL> for t in trustees : <EOL> if t . public_key == None : <EOL> issues . append ( { <EOL> '<STR_LIT:type>' : '<STR_LIT>' , <EOL> '<STR_LIT:action>' : '<STR_LIT>' % t . name <EOL> } ) <EOL> if self . voter_set . count ( ) == <NUM_LIT:0> and not self . openreg : <EOL> issues . append ( { <EOL> "<STR_LIT:type>" : "<STR_LIT>" , <EOL> "<STR_LIT:action>" : '<STR_LIT>' <EOL> } ) <EOL> return issues <EOL> def ready_for_tallying ( self ) : <EOL> return datetime . datetime . utcnow ( ) >= self . tallying_starts_at <EOL> def compute_tally ( self ) : <EOL> """<STR_LIT>""" <EOL> tally = self . init_tally ( ) <EOL> for voter in self . voter_set . exclude ( vote = None ) : <EOL> tally . add_vote ( voter . vote , verify_p = False ) <EOL> self . encrypted_tally = tally <EOL> self . save ( ) <EOL> def ready_for_decryption ( self ) : <EOL> return self . encrypted_tally != None <EOL> def ready_for_decryption_combination ( self ) : <EOL> """<STR_LIT>""" <EOL> for t in Trustee . get_by_election ( self ) : <EOL> if not t . decryption_factors : <EOL> return False <EOL> return True <EOL> def release_result ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . result : <EOL> return <EOL> self . result_released_at = datetime . datetime . utcnow ( ) <EOL> def combine_decryptions ( self ) : <EOL> """<STR_LIT>""" <EOL> trustees = Trustee . get_by_election ( self ) <EOL> decryption_factors = [ t . decryption_factors for t in trustees ] <EOL> self . result = self . encrypted_tally . decrypt_from_factors ( decryption_factors , self . public_key ) <EOL> self . append_log ( ElectionLog . DECRYPTIONS_COMBINED ) <EOL> self . save ( ) <EOL> def generate_voters_hash ( self ) : <EOL> """<STR_LIT>""" <EOL> return <EOL> if self . openreg : <EOL> self . voters_hash = None <EOL> else : <EOL> voters = Voter . get_by_election ( self ) <EOL> voters_json = utils . to_json ( [ v . toJSONDict ( ) for v in voters ] ) <EOL> self . voters_hash = utils . hash_b64 ( voters_json ) <EOL> def increment_voters ( self ) : <EOL> return <NUM_LIT:0> <EOL> def increment_cast_votes ( self ) : <EOL> return <NUM_LIT:0> <EOL> def set_eligibility ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . eligibility != None : <EOL> return <EOL> auth_systems = copy . copy ( settings . AUTH_ENABLED_AUTH_SYSTEMS ) <EOL> voter_types = [ r [ '<STR_LIT>' ] for r in self . voter_set . values ( '<STR_LIT>' ) . distinct ( ) if r [ '<STR_LIT>' ] != None ] <EOL> if self . voter_set . filter ( user = None ) . count ( ) > <NUM_LIT:0> : <EOL> voter_types . append ( '<STR_LIT:password>' ) <EOL> else : <EOL> if '<STR_LIT:password>' in auth_systems : <EOL> auth_systems . remove ( '<STR_LIT:password>' ) <EOL> if not self . openreg : <EOL> auth_systems = [ vt for vt in voter_types if vt in auth_systems ] <EOL> self . eligibility = [ { '<STR_LIT>' : auth_system } for auth_system in auth_systems ] <EOL> self . save ( ) <EOL> def freeze ( self ) : <EOL> """<STR_LIT>""" <EOL> if len ( self . issues_before_freeze ) > <NUM_LIT:0> : <EOL> raise Exception ( "<STR_LIT>" ) <EOL> self . frozen_at = datetime . datetime . utcnow ( ) <EOL> self . generate_voters_hash ( ) <EOL> self . set_eligibility ( ) <EOL> trustees = Trustee . get_by_election ( self ) <EOL> combined_pk = trustees [ <NUM_LIT:0> ] . public_key <EOL> for t in trustees [ <NUM_LIT:1> : ] : <EOL> combined_pk = combined_pk * t . public_key <EOL> self . public_key = combined_pk <EOL> self . append_log ( ElectionLog . FROZEN ) <EOL> self . save ( ) <EOL> def generate_trustee ( self , params ) : <EOL> """<STR_LIT>""" <EOL> keypair = params . generate_keypair ( ) <EOL> trustee = Trustee ( election = self ) <EOL> trustee . uuid = str ( uuid . uuid4 ( ) ) <EOL> trustee . name = settings . DEFAULT_FROM_NAME <EOL> trustee . email = settings . DEFAULT_FROM_EMAIL <EOL> trustee . public_key = keypair . pk <EOL> trustee . secret_key = keypair . sk <EOL> trustee . public_key_hash = datatypes . LDObject . instantiate ( trustee . public_key , datatype = '<STR_LIT>' ) . hash <EOL> trustee . pok = trustee . secret_key . prove_sk ( algs . DLog_challenge_generator ) <EOL> trustee . save ( ) <EOL> def get_helios_trustee ( self ) : <EOL> trustees_with_sk = self . trustee_set . exclude ( secret_key = None ) <EOL> if len ( trustees_with_sk ) > <NUM_LIT:0> : <EOL> return trustees_with_sk [ <NUM_LIT:0> ] <EOL> else : <EOL> return None <EOL> def has_helios_trustee ( self ) : <EOL> return self . get_helios_trustee ( ) != None <EOL> def helios_trustee_decrypt ( self ) : <EOL> tally = self . encrypted_tally <EOL> tally . init_election ( self ) <EOL> trustee = self . get_helios_trustee ( ) <EOL> factors , proof = tally . decryption_factors_and_proofs ( trustee . secret_key ) <EOL> trustee . decryption_factors = factors <EOL> trustee . decryption_proofs = proof <EOL> trustee . save ( ) <EOL> def append_log ( self , text ) : <EOL> item = ElectionLog ( election = self , log = text , at = datetime . datetime . utcnow ( ) ) <EOL> item . save ( ) <EOL> return item <EOL> def get_log ( self ) : <EOL> return self . electionlog_set . order_by ( '<STR_LIT>' ) <EOL> @ property <EOL> def url ( self ) : <EOL> return helios . views . get_election_url ( self ) <EOL> def init_tally ( self ) : <EOL> from helios . workflows import homomorphic <EOL> return homomorphic . Tally ( election = self ) <EOL> @ property <EOL> def registration_status_pretty ( self ) : <EOL> if self . openreg : <EOL> return "<STR_LIT>" <EOL> else : <EOL> return "<STR_LIT>" <EOL> @ classmethod <EOL> def one_question_winner ( cls , question , result , num_cast_votes ) : <EOL> """<STR_LIT>""" <EOL> counts = sorted ( enumerate ( result ) , key = lambda ( x ) : x [ <NUM_LIT:1> ] ) <EOL> counts . reverse ( ) <EOL> the_max = question [ '<STR_LIT>' ] or <NUM_LIT:1> <EOL> the_min = question [ '<STR_LIT>' ] or <NUM_LIT:0> <EOL> if the_max > <NUM_LIT:1> : <EOL> return [ c [ <NUM_LIT:0> ] for c in counts [ : the_max ] ] <EOL> if question [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> if counts [ <NUM_LIT:0> ] [ <NUM_LIT:1> ] >= ( num_cast_votes / <NUM_LIT:2> + <NUM_LIT:1> ) : <EOL> return [ counts [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] ] <EOL> else : <EOL> return [ ] <EOL> else : <EOL> return [ counts [ <NUM_LIT:0> ] [ <NUM_LIT:0> ] ] <EOL> @ property <EOL> def winners ( self ) : <EOL> """<STR_LIT>""" <EOL> return [ self . one_question_winner ( self . questions [ i ] , self . result [ i ] , self . num_cast_votes ) for i in range ( len ( self . questions ) ) ] <EOL> @ property <EOL> def pretty_result ( self ) : <EOL> if not self . result : <EOL> return None <EOL> winners = self . winners <EOL> raw_result = self . result <EOL> prettified_result = [ ] <EOL> for i in range ( len ( self . questions ) ) : <EOL> q = self . questions [ i ] <EOL> pretty_question = [ ] <EOL> for j in range ( len ( q [ '<STR_LIT>' ] ) ) : <EOL> a = q [ '<STR_LIT>' ] [ j ] <EOL> count = raw_result [ i ] [ j ] <EOL> pretty_question . append ( { '<STR_LIT>' : a , '<STR_LIT:count>' : count , '<STR_LIT>' : ( j in winners [ i ] ) } ) <EOL> prettified_result . append ( { '<STR_LIT>' : q [ '<STR_LIT>' ] , '<STR_LIT>' : pretty_question } ) <EOL> return prettified_result <EOL> class ElectionLog ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> FROZEN = "<STR_LIT>" <EOL> VOTER_FILE_ADDED = "<STR_LIT>" <EOL> DECRYPTIONS_COMBINED = "<STR_LIT>" <EOL> election = models . ForeignKey ( Election ) <EOL> log = models . CharField ( max_length = <NUM_LIT> ) <EOL> at = models . DateTimeField ( auto_now_add = True ) <EOL> def unicode_csv_reader ( unicode_csv_data , dialect = csv . excel , ** kwargs ) : <EOL> csv_reader = csv . reader ( utf_8_encoder ( unicode_csv_data ) , <EOL> dialect = dialect , ** kwargs ) <EOL> for row in csv_reader : <EOL> try : <EOL> yield [ unicode ( cell , '<STR_LIT:utf-8>' ) for cell in row ] <EOL> except : <EOL> yield [ unicode ( cell , '<STR_LIT>' ) for cell in row ] <EOL> def utf_8_encoder ( unicode_csv_data ) : <EOL> for line in unicode_csv_data : <EOL> yield line <EOL> class VoterFile ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> PATH = settings . VOTER_UPLOAD_REL_PATH <EOL> election = models . ForeignKey ( Election ) <EOL> voter_file = models . FileField ( upload_to = PATH , max_length = <NUM_LIT> , null = True ) <EOL> voter_file_content = models . TextField ( null = True ) <EOL> uploaded_at = models . DateTimeField ( auto_now_add = True ) <EOL> processing_started_at = models . DateTimeField ( auto_now_add = False , null = True ) <EOL> processing_finished_at = models . DateTimeField ( auto_now_add = False , null = True ) <EOL> num_voters = models . IntegerField ( null = True ) <EOL> def itervoters ( self ) : <EOL> if self . voter_file_content : <EOL> if type ( self . voter_file_content ) == unicode : <EOL> content = self . voter_file_content . encode ( '<STR_LIT:utf-8>' ) <EOL> else : <EOL> content = self . voter_file_content <EOL> content = content . replace ( '<STR_LIT:\r>' , '<STR_LIT:\n>' ) . replace ( '<STR_LIT>' , '<STR_LIT:\n>' ) <EOL> voter_stream = io . BytesIO ( content ) <EOL> else : <EOL> voter_stream = open ( self . voter_file . path , "<STR_LIT>" ) <EOL> reader = unicodecsv . reader ( voter_stream , encoding = '<STR_LIT:utf-8>' ) <EOL> for voter_fields in reader : <EOL> if len ( voter_fields ) < <NUM_LIT:1> : <EOL> continue <EOL> return_dict = { '<STR_LIT>' : voter_fields [ <NUM_LIT:0> ] . strip ( ) } <EOL> if len ( voter_fields ) > <NUM_LIT:1> : <EOL> return_dict [ '<STR_LIT:email>' ] = voter_fields [ <NUM_LIT:1> ] . strip ( ) <EOL> else : <EOL> return_dict [ '<STR_LIT:email>' ] = voter_fields [ <NUM_LIT:0> ] . strip ( ) <EOL> if len ( voter_fields ) > <NUM_LIT:2> : <EOL> return_dict [ '<STR_LIT:name>' ] = voter_fields [ <NUM_LIT:2> ] . strip ( ) <EOL> else : <EOL> return_dict [ '<STR_LIT:name>' ] = return_dict [ '<STR_LIT:email>' ] <EOL> yield return_dict <EOL> def process ( self ) : <EOL> self . processing_started_at = datetime . datetime . utcnow ( ) <EOL> self . save ( ) <EOL> election = self . election <EOL> last_alias_num = election . last_alias_num <EOL> num_voters = <NUM_LIT:0> <EOL> new_voters = [ ] <EOL> for voter in self . itervoters ( ) : <EOL> num_voters += <NUM_LIT:1> <EOL> existing_voter = Voter . get_by_election_and_voter_id ( election , voter [ '<STR_LIT>' ] ) <EOL> if not existing_voter : <EOL> voter_uuid = str ( uuid . uuid4 ( ) ) <EOL> existing_voter = Voter ( uuid = voter_uuid , user = None , voter_login_id = voter [ '<STR_LIT>' ] , <EOL> voter_name = voter [ '<STR_LIT:name>' ] , voter_email = voter [ '<STR_LIT:email>' ] , election = election ) <EOL> existing_voter . generate_password ( ) <EOL> new_voters . append ( existing_voter ) <EOL> existing_voter . save ( ) <EOL> if election . use_voter_aliases : <EOL> voter_alias_integers = range ( last_alias_num + <NUM_LIT:1> , last_alias_num + <NUM_LIT:1> + num_voters ) <EOL> random . shuffle ( voter_alias_integers ) <EOL> for i , voter in enumerate ( new_voters ) : <EOL> voter . alias = '<STR_LIT>' % voter_alias_integers [ i ] <EOL> voter . save ( ) <EOL> self . num_voters = num_voters <EOL> self . processing_finished_at = datetime . datetime . utcnow ( ) <EOL> self . save ( ) <EOL> return num_voters <EOL> class Voter ( HeliosModel ) : <EOL> election = models . ForeignKey ( Election ) <EOL> uuid = models . CharField ( max_length = <NUM_LIT:50> ) <EOL> user = models . ForeignKey ( '<STR_LIT>' , null = True ) <EOL> voter_login_id = models . CharField ( max_length = <NUM_LIT:100> , null = True ) <EOL> voter_password = models . CharField ( max_length = <NUM_LIT:100> , null = True ) <EOL> voter_name = models . CharField ( max_length = <NUM_LIT:200> , null = True ) <EOL> voter_email = models . CharField ( max_length = <NUM_LIT> , null = True ) <EOL> alias = models . CharField ( max_length = <NUM_LIT:100> , null = True ) <EOL> vote = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> vote_hash = models . CharField ( max_length = <NUM_LIT:100> , null = True ) <EOL> cast_at = models . DateTimeField ( auto_now_add = False , null = True ) <EOL> class Meta : <EOL> unique_together = ( ( '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( Voter , self ) . __init__ ( * args , ** kwargs ) <EOL> if not self . user : <EOL> self . user = User ( user_type = '<STR_LIT:password>' , user_id = self . voter_email , name = self . voter_name ) <EOL> @ classmethod <EOL> @ transaction . atomic <EOL> def register_user_in_election ( cls , user , election ) : <EOL> voter_uuid = str ( uuid . uuid4 ( ) ) <EOL> voter = Voter ( uuid = voter_uuid , user = user , election = election ) <EOL> if election . use_voter_aliases : <EOL> heliosutils . lock_row ( Election , election . id ) <EOL> alias_num = election . last_alias_num + <NUM_LIT:1> <EOL> voter . alias = "<STR_LIT>" % alias_num <EOL> voter . save ( ) <EOL> return voter <EOL> @ classmethod <EOL> def get_by_election ( cls , election , cast = None , order_by = '<STR_LIT>' , after = None , limit = None ) : <EOL> """<STR_LIT>""" <EOL> query = cls . objects . filter ( election = election ) <EOL> if cast == True : <EOL> query = query . exclude ( cast_at = None ) <EOL> elif cast == False : <EOL> query = query . filter ( cast_at = None ) <EOL> if cast == None or order_by == '<STR_LIT>' or order_by == '<STR_LIT>' : <EOL> query = query . order_by ( order_by ) <EOL> if after : <EOL> if order_by [ <NUM_LIT:0> ] == '<STR_LIT:->' : <EOL> field_name = "<STR_LIT>" % order_by [ <NUM_LIT:1> : ] <EOL> else : <EOL> field_name = "<STR_LIT>" % order_by <EOL> conditions = { field_name : after } <EOL> query = query . filter ( ** conditions ) <EOL> if limit : <EOL> query = query [ : limit ] <EOL> return query <EOL> @ classmethod <EOL> def get_all_by_election_in_chunks ( cls , election , cast = None , chunk = <NUM_LIT:100> ) : <EOL> return cls . get_by_election ( election ) <EOL> @ classmethod <EOL> def get_by_election_and_voter_id ( cls , election , voter_id ) : <EOL> try : <EOL> return cls . objects . get ( election = election , voter_login_id = voter_id ) <EOL> except cls . DoesNotExist : <EOL> return None <EOL> @ classmethod <EOL> def get_by_election_and_user ( cls , election , user ) : <EOL> try : <EOL> return cls . objects . get ( election = election , user = user ) <EOL> except cls . DoesNotExist : <EOL> return None <EOL> @ classmethod <EOL> def get_by_election_and_uuid ( cls , election , uuid ) : <EOL> query = cls . objects . filter ( election = election , uuid = uuid ) <EOL> try : <EOL> return query [ <NUM_LIT:0> ] <EOL> except : <EOL> return None <EOL> @ classmethod <EOL> def get_by_user ( cls , user ) : <EOL> return cls . objects . select_related ( ) . filter ( user = user ) . order_by ( '<STR_LIT>' ) <EOL> @ property <EOL> def datatype ( self ) : <EOL> return self . election . datatype . replace ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> @ property <EOL> def vote_tinyhash ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . vote_hash : <EOL> return None <EOL> return CastVote . objects . get ( vote_hash = self . vote_hash ) . vote_tinyhash <EOL> @ property <EOL> def election_uuid ( self ) : <EOL> return self . election . uuid <EOL> @ property <EOL> def name ( self ) : <EOL> return self . user . name <EOL> @ property <EOL> def voter_id ( self ) : <EOL> return self . user . user_id <EOL> @ property <EOL> def voter_id_hash ( self ) : <EOL> if self . voter_login_id : <EOL> value_to_hash = self . voter_login_id <EOL> else : <EOL> value_to_hash = self . voter_id <EOL> try : <EOL> return utils . hash_b64 ( value_to_hash ) <EOL> except : <EOL> try : <EOL> return utils . hash_b64 ( value_to_hash . encode ( '<STR_LIT>' ) ) <EOL> except : <EOL> return utils . hash_b64 ( value_to_hash . encode ( '<STR_LIT:utf-8>' ) ) <EOL> @ property <EOL> def voter_type ( self ) : <EOL> return self . user . user_type <EOL> @ property <EOL> def display_html_big ( self ) : <EOL> return self . user . display_html_big <EOL> def send_message ( self , subject , body ) : <EOL> self . user . send_message ( subject , body ) <EOL> def generate_password ( self , length = <NUM_LIT:10> ) : <EOL> if self . voter_password : <EOL> raise Exception ( "<STR_LIT>" ) <EOL> self . voter_password = heliosutils . random_string ( length , alphabet = '<STR_LIT>' ) <EOL> def store_vote ( self , cast_vote ) : <EOL> if self . cast_at and cast_vote . cast_at < self . cast_at : <EOL> return <EOL> self . vote = cast_vote . vote <EOL> self . vote_hash = cast_vote . vote_hash <EOL> self . cast_at = cast_vote . cast_at <EOL> self . save ( ) <EOL> def last_cast_vote ( self ) : <EOL> return CastVote ( vote = self . vote , vote_hash = self . vote_hash , cast_at = self . cast_at , voter = self ) <EOL> class CastVote ( HeliosModel ) : <EOL> voter = models . ForeignKey ( Voter ) <EOL> vote = LDObjectField ( type_hint = '<STR_LIT>' ) <EOL> vote_hash = models . CharField ( max_length = <NUM_LIT:100> ) <EOL> vote_tinyhash = models . CharField ( max_length = <NUM_LIT:50> , null = True , unique = True ) <EOL> cast_at = models . DateTimeField ( auto_now_add = True ) <EOL> quarantined_p = models . BooleanField ( default = False , null = False ) <EOL> released_from_quarantine_at = models . DateTimeField ( auto_now_add = False , null = True ) <EOL> verified_at = models . DateTimeField ( null = True ) <EOL> invalidated_at = models . DateTimeField ( null = True ) <EOL> @ property <EOL> def datatype ( self ) : <EOL> return self . voter . datatype . replace ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> @ property <EOL> def voter_uuid ( self ) : <EOL> return self . voter . uuid <EOL> @ property <EOL> def voter_hash ( self ) : <EOL> return self . voter . hash <EOL> @ property <EOL> def is_quarantined ( self ) : <EOL> return self . quarantined_p and not self . released_from_quarantine_at <EOL> def set_tinyhash ( self ) : <EOL> """<STR_LIT>""" <EOL> safe_hash = self . vote_hash <EOL> for c in [ '<STR_LIT:/>' , '<STR_LIT:+>' ] : <EOL> safe_hash = safe_hash . replace ( c , '<STR_LIT>' ) <EOL> length = <NUM_LIT:8> <EOL> while True : <EOL> vote_tinyhash = safe_hash [ : length ] <EOL> if CastVote . objects . filter ( vote_tinyhash = vote_tinyhash ) . count ( ) == <NUM_LIT:0> : <EOL> break <EOL> length += <NUM_LIT:1> <EOL> self . vote_tinyhash = vote_tinyhash <EOL> def save ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if not self . vote_tinyhash : <EOL> self . set_tinyhash ( ) <EOL> super ( CastVote , self ) . save ( * args , ** kwargs ) <EOL> @ classmethod <EOL> def get_by_voter ( cls , voter ) : <EOL> return cls . objects . filter ( voter = voter ) . order_by ( '<STR_LIT>' ) <EOL> def verify_and_store ( self ) : <EOL> if self . is_quarantined : <EOL> raise Exception ( "<STR_LIT>" ) <EOL> result = self . vote . verify ( self . voter . election ) <EOL> if result : <EOL> self . verified_at = datetime . datetime . utcnow ( ) <EOL> else : <EOL> self . invalidated_at = datetime . datetime . utcnow ( ) <EOL> self . save ( ) <EOL> if result : <EOL> self . voter . store_vote ( self ) <EOL> return result <EOL> def issues ( self , election ) : <EOL> """<STR_LIT>""" <EOL> issues = [ ] <EOL> if self . vote . election_uuid != election . uuid : <EOL> issues . append ( "<STR_LIT>" ) <EOL> return issues <EOL> class AuditedBallot ( models . Model ) : <EOL> """<STR_LIT>""" <EOL> election = models . ForeignKey ( Election ) <EOL> raw_vote = models . TextField ( ) <EOL> vote_hash = models . CharField ( max_length = <NUM_LIT:100> ) <EOL> added_at = models . DateTimeField ( auto_now_add = True ) <EOL> @ classmethod <EOL> def get ( cls , election , vote_hash ) : <EOL> return cls . objects . get ( election = election , vote_hash = vote_hash ) <EOL> @ classmethod <EOL> def get_by_election ( cls , election , after = None , limit = None ) : <EOL> query = cls . objects . filter ( election = election ) . order_by ( '<STR_LIT>' ) <EOL> if after : <EOL> query = query . filter ( vote_hash__gt = after ) <EOL> if limit : <EOL> query = query [ : limit ] <EOL> return query <EOL> class Trustee ( HeliosModel ) : <EOL> election = models . ForeignKey ( Election ) <EOL> uuid = models . CharField ( max_length = <NUM_LIT:50> ) <EOL> name = models . CharField ( max_length = <NUM_LIT:200> ) <EOL> email = models . EmailField ( ) <EOL> secret = models . CharField ( max_length = <NUM_LIT:100> ) <EOL> public_key = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> public_key_hash = models . CharField ( max_length = <NUM_LIT:100> ) <EOL> secret_key = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> pok = LDObjectField ( type_hint = '<STR_LIT>' , <EOL> null = True ) <EOL> decryption_factors = LDObjectField ( type_hint = datatypes . arrayOf ( datatypes . arrayOf ( '<STR_LIT>' ) ) , <EOL> null = True ) <EOL> decryption_proofs = LDObjectField ( type_hint = datatypes . arrayOf ( datatypes . arrayOf ( '<STR_LIT>' ) ) , <EOL> null = True ) <EOL> class Meta : <EOL> unique_together = ( ( '<STR_LIT>' , '<STR_LIT:email>' ) ) <EOL> def save ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> if not self . secret : <EOL> self . secret = heliosutils . random_string ( <NUM_LIT:12> ) <EOL> self . election . append_log ( "<STR_LIT>" % self . name ) <EOL> super ( Trustee , self ) . save ( * args , ** kwargs ) <EOL> @ classmethod <EOL> def get_by_election ( cls , election ) : <EOL> return cls . objects . filter ( election = election ) <EOL> @ classmethod <EOL> def get_by_uuid ( cls , uuid ) : <EOL> return cls . objects . get ( uuid = uuid ) <EOL> @ classmethod <EOL> def get_by_election_and_uuid ( cls , election , uuid ) : <EOL> return cls . objects . get ( election = election , uuid = uuid ) <EOL> @ classmethod <EOL> def get_by_election_and_email ( cls , election , email ) : <EOL> try : <EOL> return cls . objects . get ( election = election , email = email ) <EOL> except cls . DoesNotExist : <EOL> return None <EOL> @ property <EOL> def datatype ( self ) : <EOL> return self . election . datatype . replace ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> def verify_decryption_proofs ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . election . encrypted_tally . verify_decryption_proofs ( self . decryption_factors , self . decryption_proofs , self . public_key , algs . EG_fiatshamir_challenge_generator ) </s>
