def voter_file_process(election,voter_file): last_alias_num = election.last_alias_num num_voters = 0 new_voters = [] for voter in voter_file.itervoters(): num_voters += 1 # Is the voter a user? new_user = False user = User.get_by_type_and_id('password', voter['voter_id']) if not user: new_user = True random_password = generate_password() password.create_user(voter['voter_id'], random_password, voter['name'], voter['email']) user = User.get_by_type_and_id('password', voter['voter_id']) voter_registered = create_voter(user,election) if new_user: voter_send_email.delay(voter_registered.id, election.uuid, "new_user", random_password) else: voter_send_email.delay(voter_registered.id, election.uuid, "old_user") if election.use_voter_aliases: voter_alias_integers = range(last_alias_num+1, last_alias_num+1+num_voters) random.shuffle(voter_alias_integers) for i, voter in enumerate(new_voters): voter.alias = 'V%s' % voter_alias_integers[i] voter.save() voter_file.num_voters = num_voters voter_file.processing_finished_at = timezone.now() voter_file.save()
def __init__(self, *args, **kwargs): super(Voter, self).__init__(*args, **kwargs) # stub the user so code is not full of IF statements if not self.user: self.user = User(user_type='password', user_id=self.voter_email, name=self.voter_name)
def create_user(username, password, name = None): from helios_auth.models import User user = User.get_by_type_and_id('password', username) if user: raise Exception('user exists') info = {'password' : password, 'name': name} user = User.update_or_create(user_type='password', user_id=username, info = info) user.save()
def create_user(username, password, name=None): from helios_auth.models import User user = User.get_by_type_and_id("password", username) if user: raise Exception("user exists") info = {"password": password, "name": name} user = User.update_or_create(user_type="password", user_id=username, info=info) user.save()
def generate_voters(election, num_voters=1000, start_with=1): # generate the user for v_num in range(start_with, start_with + num_voters): user = User(user_type='password', user_id='testuser%s' % v_num, name='Test User %s' % v_num) user.save() voter = Voter(uuid=str(uuid.uuid1()), election=election, voter_type=user.user_type, voter_id=user.user_id) voter.save()
def create_user(username, password, name = None): from helios_auth.models import User from django.db import models try: user = User.get_by_type_and_id('password', username) raise Exception('user exists') except User.DoesNotExist: pass info = {'password' : password, 'name': name} user = User.update_or_create(user_type='password', user_id=username, info = info) user.save()
def process(self): self.processing_started_at = datetime.datetime.utcnow() self.save() election = self.election last_alias_num = election.last_alias_num num_voters = 0 new_voters = [] for voter in self.itervoters(): # does voter for this user already exist existing_voter = Voter.get_by_election_and_voter_id(election, voter['voter_id']) # create the voter if not existing_voter: num_voters += 1 user = None if 'user_type' in voter.keys(): if 'email' in voter.keys(): user = User.update_or_create(voter['user_type'], voter['voter_id'], voter['name'], {'email': voter['email']}) else: user = User.update_or_create(voter['user_type'], voter['voter_id'], voter['name'], {}) voter_uuid = str(uuid.uuid4()) if 'email' in voter.keys(): new_voter = Voter(uuid=voter_uuid, user=user, voter_name=voter['name'], voter_email=voter['email'], election=election) else: new_voter = Voter(uuid=voter_uuid, user=user, voter_name=voter['name'], election=election) new_voter.voter_login_id = voter['voter_id'] if not user: new_voter.generate_password() new_voters.append(new_voter) new_voter.save() if election.use_voter_aliases: voter_alias_integers = range(last_alias_num + 1, last_alias_num + 1 + num_voters) random.shuffle(voter_alias_integers) for i, new_voter in enumerate(new_voters): new_voter.alias = 'V%s' % voter_alias_integers[i] new_voter.save() self.num_voters = num_voters self.processing_finished_at = datetime.datetime.utcnow() self.save() return num_voters
def create_user(username, password, name=None): from helios_auth.models import User from django.db import models try: user = User.get_by_type_and_id('password', username) raise Exception('user exists') except User.DoesNotExist: pass info = {'password': password, 'name': name} user = User.update_or_create(user_type='password', user_id=username, info=info) user.save()
def password_login_view(request): from helios_auth.view_utils import render_template from helios_auth.views import after from helios_auth.models import User error = None if request.method == "GET": form = LoginForm() else: form = LoginForm(request.POST) # set this in case we came here straight from the multi-login chooser # and thus did not have a chance to hit the "start/password" URL request.session["auth_system_name"] = "password" if "return_url" in request.POST: request.session["auth_return_url"] = request.POST.get("return_url") if form.is_valid(): username = form.cleaned_data["username"].strip() password = form.cleaned_data["password"].strip() try: user = User.get_by_type_and_id("password", username) if password_check(user, password): request.session["password_user_id"] = user.user_id return HttpResponseRedirect(reverse(url_names.AUTH_AFTER)) except User.DoesNotExist: pass error = "Bad Username or Password" return render_template(request, "password/login", { "form": form, "error": error })
def password_forgotten_view(request): """ forgotten password view and submit. includes return_url """ from helios_auth.view_utils import render_template from helios_auth.models import User if request.method == "GET": return render_template(request, 'password/forgot', {'return_url': request.GET.get('return_url', '')}) else: username = request.POST['username'] return_url = request.POST['return_url'] try: user = User.get_by_type_and_id('password', username) except User.DoesNotExist: return render_template(request, 'password/forgot', {'return_url': request.GET.get('return_url', ''), 'error': 'no such username'}) body = """ This is a password reminder: Your username: %s Your password: %s -- %s """ % (user.user_id, user.info['password'], settings.SITE_TITLE) # FIXME: make this a task send_mail('password reminder', body, settings.SERVER_EMAIL, ["%s <%s>" % (user.info['name'], user.info['email'])], fail_silently=False) return HttpResponseRedirect(return_url)
def password_login_view(request): from helios_auth.view_utils import render_template from helios_auth.views import after from helios_auth.models import User error = None if request.method == "GET": form = LoginForm() else: form = LoginForm(request.POST) # set this in case we came here straight from the multi-login chooser # and thus did not have a chance to hit the "start/password" URL request.session['auth_system_name'] = 'password' if request.POST.has_key('return_url'): request.session['auth_return_url'] = request.POST.get('return_url') if form.is_valid(): username = form.cleaned_data['username'].strip() password = form.cleaned_data['password'].strip() try: user = User.get_by_type_and_id('password', username) if password_check(user, password): request.session['password_user_id'] = user.user_id return HttpResponseRedirect(reverse(after)) except User.DoesNotExist: pass error = 'Bad Username or Password' return render_template(request, 'password/login', {'form': form, 'error': error})
def load_eligible_voters(self): """ try to load voters by eligibility constraints """ if self.eligibility == None: return if self.openreg == False: return total_load = True for eligibility_case in self.eligibility: print eligibility_case auth_system = eligibility_case['auth_system'] if not eligibility_case.has_key('constraint'): total_load = False else: if hasattr(AUTH_SYSTEMS[auth_system], 'can_list_category_members'): for constraint in eligibility_case['constraint']: category_id = AUTH_SYSTEMS[auth_system].eligibility_category_id(constraint) for u in AUTH_SYSTEMS[auth_system].list_category_members(category_id): user = User.update_or_create(user_type = u['type'], user_id = u['id'], name = u['name'], info = u['info'], token = u['token']) Voter.register_user_in_election(user, self) else: total_load = False if total_load: self.openreg = False
def password_login_view(request): from helios_auth.view_utils import render_template from helios_auth.views import after from helios_auth.models import User error = None if request.method == "GET": form = LoginForm() else: form = LoginForm(request.POST) # set this in case we came here straight from the multi-login chooser # and thus did not have a chance to hit the "start/password" URL request.session['auth_system_name'] = 'password' if request.POST.has_key('return_url'): request.session['auth_return_url'] = request.POST.get('return_url') if form.is_valid(): username = form.cleaned_data['username'].strip() password = form.cleaned_data['password'].strip() try: user = User.get_by_type_and_id('password', username) if password_check(user, password): request.session['password_user'] = user return HttpResponseRedirect(reverse(after)) except User.DoesNotExist: pass error = 'Bad Username or Password' return render_template(request, 'password/login', { 'form': form, 'error': error })
def login_view(request): # imports are here because putting them in the header prevents # initialization of the database from helios_auth.view_utils import render_template from helios_auth.views import after from helios_auth.models import User if request.method == "GET": form = LoginForm() else: form = LoginForm(request.POST) request.session['auth_system_name'] = 'dummy' if request.POST.has_key('return_url'): request.session['auth_return_url'] = request.POST.get('return_url') if form.is_valid(): name = form.cleaned_data['username'].strip() admin_p = form.cleaned_data['admin_p'] user_obj = User.update_or_create(user_type='dummy', user_id=name, name=name, info={}) if user_obj.admin_p != admin_p: user_obj.admin_p = admin_p user_obj.save() request.session['dummy_user'] = name return HttpResponseRedirect(reverse(after)) return render_template(request, 'dummy/login', {'form': form})
def password_forgotten_view(request): """ forgotten password view and submit. includes return_url """ from helios_auth.view_utils import render_template from helios_auth.models import User if request.method == "GET": return render_template( request, "password/forgot", {"return_url": request.GET.get("return_url", "")}, ) else: username = request.POST["username"] return_url = request.POST["return_url"] try: user = User.get_by_type_and_id("password", username) except User.DoesNotExist: return render_template( request, "password/forgot", { "return_url": request.GET.get("return_url", ""), "error": "no such username", }, ) body = """ This is a password reminder: Your username: %s Your password: %s -- %s """ % ( user.user_id, user.info["password"], settings.SITE_TITLE, ) # FIXME: make this a task send_mail( "password reminder", body, settings.SERVER_EMAIL, ["%s <%s>" % (user.info["name"], user.info["email"])], fail_silently=False, ) return HttpResponseRedirect(return_url)
def get_user_info_after_auth(request): from helios_auth.models import User user = User.get_by_type_and_id('password', request.session['password_user_id']) del request.session['password_user_id'] return { 'type': 'password', 'user_id': user.user_id, 'name': user.name, 'info': user.info, 'token': None }
def get_user_info_after_auth(request): from helios_auth.models import User user = User.get_by_type_and_id("password", request.session["password_user_id"]) del request.session["password_user_id"] return { "type": "password", "user_id": user.user_id, "name": user.name, "info": user.info, "token": None, }
def password_forgotten_view(request): """ forgotten password view and submit. includes return_url """ from helios_auth.view_utils import render_template from helios_auth.models import User if request.method == "GET": return render_template(request, "password/forgot", {"return_url": request.GET.get("return_url", "")}) else: username = request.POST["username"] return_url = request.POST["return_url"] try: user = User.get_by_type_and_id("password", username) except User.DoesNotExist: return render_template( request, "password/forgot", {"return_url": request.GET.get("return_url", ""), "error": "no such username"}, ) body = """ This is a password reminder: Your username: %s Your password: %s -- %s """ % ( user.user_id, user.info["password"], settings.SITE_TITLE, ) # FIXME: make this a task send_mail( "password reminder", body, settings.SERVER_EMAIL, ["%s <%s>" % (user.info["name"], user.info["email"])], fail_silently=False, ) return HttpResponseRedirect(return_url)
def get_user(request): # push the expiration of the session back # request.session.set_expiry(settings.SESSION_COOKIE_AGE) # set up CSRF protection if needed if 'csrf_token' not in request.session or not isinstance( request.session['csrf_token'], str): request.session['csrf_token'] = str(uuid.uuid4()) if 'user' in request.session: user = request.session['user'] # find the user user_obj = User.get_by_type_and_id(user['type'], user['user_id']) return user_obj else: return None
def post(self, request): try: user = auth_user(request) election_params = json.loads(request.body) election_params['short_name'] = "%s_%s" % ( election_params['short_name'], user['username']) election_params['uuid'] = str(uuid.uuid1()) election_params['cast_url'] = reverse( 'elections-cast', args=[election_params['uuid']], request=request) election_params['openreg'] = False # registration starts closed election_params['admin'] = User.get_by_type_and_id( 'password', user['username']) election = Election.objects.create(**election_params) return response(201, {'uuid': election_params['uuid']}) except Exception as err: return get_error(err)
def get_user(request): # push the expiration of the session back # request.session.set_expiry(settings.SESSION_COOKIE_AGE) # set up CSRF protection if needed if not request.session.has_key('csrf_token') or ( type(request.session['csrf_token']) != str and type(request.session['csrf_token']) != unicode): request.session['csrf_token'] = str(uuid.uuid4()) if request.session.has_key('user'): user = request.session['user'] # find the user user_obj = User.get_by_type_and_id(user['type'], user['user_id']) return user_obj else: return None
def get_user(request): # push the expiration of the session back # request.session.set_expiry(settings.SESSION_COOKIE_AGE) # set up CSRF protection if needed if "csrf_token" not in request.session or ( type(request.session["csrf_token"]) != str and type(request.session["csrf_token"]) != str): request.session["csrf_token"] = str(uuid.uuid4()) if "user" in request.session: user = request.session["user"] # find the user user_obj = User.get_by_type_and_id(user["type"], user["user_id"]) return user_obj else: return None
def load_eligible_voters(self): """ try to load voters by eligibility constraints """ if self.eligibility == None: return if self.openreg == False: return total_load = True for eligibility_case in self.eligibility: print eligibility_case auth_system = eligibility_case['auth_system'] if not eligibility_case.has_key('constraint'): total_load = False else: if hasattr(AUTH_SYSTEMS[auth_system], 'can_list_category_members'): for constraint in eligibility_case['constraint']: category_id = AUTH_SYSTEMS[ auth_system].eligibility_category_id(constraint) user_list = AUTH_SYSTEMS[ auth_system].list_category_members(category_id) if self.use_voter_aliases: random.shuffle(user_list) for u in user_list: user = User.update_or_create(user_type=u['type'], user_id=u['id'], name=u['name'], info=u['info'], token=u['token']) Voter.register_user_in_election(user, self) else: total_load = False if total_load: self.openreg = False
def process(self): logger.error('--------------------- processing voterfile') self.processing_started_at = datetime.datetime.utcnow() self.save() election = self.election last_alias_num = election.last_alias_num num_voters = 0 new_voters = [] for voter in self.itervoters(): num_voters += 1 # does voter for this user already exist existing_voter = Voter.get_by_election_and_voter_id(election, voter['voter_id']) if existing_voter: logger.error(existing_voter.voter_login_id) # create the voter if not existing_voter: voter_uuid = str(uuid.uuid4()) user = User.get_by_type_and_id('dnie', voter['voter_id']) existing_voter = Voter(uuid= voter_uuid, user = user, voter_login_id = voter['voter_id'], voter_name = voter['name'], voter_email = voter['email'], election = election) existing_voter.generate_password() new_voters.append(existing_voter) existing_voter.save() if election.use_voter_aliases: voter_alias_integers = range(last_alias_num+1, last_alias_num+1+num_voters) random.shuffle(voter_alias_integers) for i, voter in enumerate(new_voters): voter.alias = 'V%s' % voter_alias_integers[i] voter.save() self.num_voters = num_voters self.processing_finished_at = datetime.datetime.utcnow() self.save() return num_voters
def after(request): # which auth system were we using? if not request.session.has_key('auth_system_name'): do_local_logout(request) return HttpResponseRedirect("/") system = AUTH_SYSTEMS[request.session['auth_system_name']] # get the user info user = system.get_user_info_after_auth(request) if user: # get the user and store any new data about him user_obj = User.update_or_create(user['type'], user['user_id'], user['name'], user['info'], user['token']) request.session['user'] = user else: return HttpResponseRedirect( "%s?%s" % (reverse(perms_why), urllib.parse.urlencode( {'system_name': request.session['auth_system_name']}))) # does the auth system want to present an additional view? # this is, for example, to prompt the user to follow @heliosvoting # so they can hear about election results if hasattr(system, 'user_needs_intervention'): intervention_response = system.user_needs_intervention( user['user_id'], user['info'], user['token']) if intervention_response: return intervention_response # go to the after intervention page. This is for modularity return HttpResponseRedirect(reverse(after_intervention))
def get_user(self): # stub the user so code is not full of IF statements return self.user or User(user_type='password', user_id=self.voter_email, name=self.voter_name)
class Voter(HeliosModel): election = models.ForeignKey(Election) # let's link directly to the user now # FIXME: delete this as soon as migrations are set up #name = models.CharField(max_length = 200, null=True) #voter_type = models.CharField(max_length = 100) #voter_id = models.CharField(max_length = 100) uuid = models.CharField(max_length = 50) # for users of type password, no user object is created # but a dynamic user object is created automatically user = models.ForeignKey('helios_auth.User', null=True) # if user is null, then you need a voter login ID and password voter_login_id = models.CharField(max_length = 100, null=True) voter_password = models.CharField(max_length = 100, null=True) voter_name = models.CharField(max_length = 200, null=True) voter_email = models.CharField(max_length = 250, null=True) voter_group = models.ForeignKey(VoterGroup, null=True) # if election uses aliases alias = models.CharField(max_length = 100, null=True) # we keep a copy here for easy tallying vote = LDObjectField(type_hint = 'legacy/EncryptedVote', null=True) vote_hash = models.CharField(max_length = 100, null=True) cast_at = models.DateTimeField(auto_now_add=False, null=True) class Meta: unique_together = (('election', 'voter_login_id')) def __init__(self, *args, **kwargs): super(Voter, self).__init__(*args, **kwargs) # stub the user so code is not full of IF statements if not self.user: self.user = User(user_type='password', user_id=self.voter_email, name=self.voter_name) @classmethod @transaction.commit_on_success def register_user_in_election(cls, user, election): voter_uuid = str(uuid.uuid4()) voter = Voter(uuid= voter_uuid, user = user, election = election) # do we need to generate an alias? if election.use_voter_aliases: heliosutils.lock_row(Election, election.id) alias_num = election.last_alias_num + 1 voter.alias = "V%s" % alias_num voter.save() return voter @classmethod def get_by_election(cls, election, cast=None, order_by='voter_login_id', after=None, limit=None): """ FIXME: review this for non-GAE? """ query = cls.objects.filter(election = election) # the boolean check is not stupid, this is ternary logic # none means don't care if it's cast or not if cast == True: query = query.exclude(cast_at = None) elif cast == False: query = query.filter(cast_at = None) # little trick to get around GAE limitation # order by uuid only when no inequality has been added if cast == None or order_by == 'cast_at' or order_by =='-cast_at': query = query.order_by(order_by) # if we want the list after a certain UUID, add the inequality here if after: if order_by[0] == '-': field_name = "%s__gt" % order_by[1:] else: field_name = "%s__gt" % order_by conditions = {field_name : after} query = query.filter (**conditions) if limit: query = query[:limit] return query @classmethod def get_all_by_election_in_chunks(cls, election, cast=None, chunk=100): return cls.get_by_election(election) @classmethod def get_by_election_and_voter_id(cls, election, voter_id): try: return cls.objects.get(election = election, voter_login_id = voter_id) except cls.DoesNotExist: return None @classmethod def get_by_election_and_user(cls, election, user): try: return cls.objects.get(election = election, user = user) except cls.DoesNotExist: return None @classmethod def get_by_election_and_uuid(cls, election, uuid): query = cls.objects.filter(election = election, uuid = uuid) try: return query[0] except: return None @classmethod def get_by_user(cls, user): return cls.objects.select_related().filter(user = user).order_by('-cast_at') @property def datatype(self): return self.election.datatype.replace('Election', 'Voter') @property def vote_tinyhash(self): """ get the tinyhash of the latest castvote """ if not self.vote_hash: return None return CastVote.objects.get(vote_hash = self.vote_hash).vote_tinyhash @property def election_uuid(self): return self.election.uuid @property def name(self): return self.user.name @property def voter_id(self): return self.user.user_id @property def voter_id_hash(self): if self.voter_login_id: # for backwards compatibility with v3.0, and since it doesn't matter # too much if we hash the email or the unique login ID here. value_to_hash = self.voter_login_id else: value_to_hash = self.voter_id try: return utils.hash_b64(value_to_hash) except: try: return utils.hash_b64(value_to_hash.encode('latin-1')) except: return utils.hash_b64(value_to_hash.encode('utf-8')) @property def voter_type(self): return self.user.user_type @property def display_html_big(self): return self.user.display_html_big def send_message(self, subject, body): self.user.send_message(subject, body) def generate_password(self, length=10): if self.voter_password: raise Exception("password already exists") self.voter_password = heliosutils.random_string(length) def store_vote(self, cast_vote): # only store the vote if it's cast later than the current one if self.cast_at and cast_vote.cast_at < self.cast_at: return self.vote = cast_vote.vote self.vote_hash = cast_vote.vote_hash self.cast_at = cast_vote.cast_at self.save() def last_cast_vote(self): return CastVote(vote = self.vote, vote_hash = self.vote_hash, cast_at = self.cast_at, voter=self)
class Voter(HeliosModel): election = models.ForeignKey(Election) # let's link directly to the user now # FIXME: delete this as soon as migrations are set up #name = models.CharField(max_length = 200, null=True) #voter_type = models.CharField(max_length = 100) #voter_id = models.CharField(max_length = 100) uuid = models.CharField(max_length = 50) # for users of type password, no user object is created # but a dynamic user object is created automatically user = models.ForeignKey('helios_auth.User', null=True) # if user is null, then you need a voter login ID and password voter_login_id = models.CharField(max_length = 100, null=True) voter_password = models.CharField(max_length = 100, null=True) voter_name = models.CharField(max_length = 200, null=True) voter_email = models.CharField(max_length = 250, null=True) # if election uses aliases alias = models.CharField(max_length = 100, null=True) # we keep a copy here for easy tallying vote = LDObjectField(type_hint = 'legacy/EncryptedVote', null=True) vote_hash = models.CharField(max_length = 100, null=True) cast_at = models.DateTimeField(auto_now_add=False, null=True) class Meta: unique_together = (('election', 'voter_login_id')) def __init__(self, *args, **kwargs): super(Voter, self).__init__(*args, **kwargs) # stub the user so code is not full of IF statements if not self.user: self.user = User(user_type='password', user_id=self.voter_email, name=self.voter_name) def __unicode__(self): return self.user.name # DENIS - ultimo upload sobrescreve demais. Registros em helios_voter devem ser apagados de forma a constar somente os usuarios indicados no CSV carregado por # ultimo. Atualiza helios_electionlog. # TODO - na view acrescentar informacao: apagado(s) X eleitor(es), antes de informar novo processamento de CSV. @classmethod @transaction.commit_on_success def unregister_voters_in_election(cls, election): amount_voters = 0 if not election: raise Exception("Eleicao nula, nao posso apagar eleitores do(s) arquivo(s) CSV previo(s) se existir(em)!") else: amount_voters = cls.objects.filter(election_id = election.id).count() voters_to_del = cls.objects.filter(election_id = election.id) voters_to_del.delete() election.append_log(ElectionLog.PREVIOUS_VOTERS_REMOVED) return amount_voters @classmethod @transaction.commit_on_success def register_user_in_election(cls, user, election): voter_uuid = str(uuid.uuid4()) voter = Voter(uuid= voter_uuid, user = user, election = election) # do we need to generate an alias? if election.use_voter_aliases: heliosutils.lock_row(Election, election.id) alias_num = election.last_alias_num + 1 voter.alias = "V%s" % alias_num voter.save() return voter @classmethod def get_by_election(cls, election, cast=None, order_by='voter_login_id', after=None, limit=None): """ FIXME: review this for non-GAE? """ query = cls.objects.filter(election = election) # the boolean check is not stupid, this is ternary logic # none means don't care if it's cast or not if cast == True: query = query.exclude(cast_at = None) elif cast == False: query = query.filter(cast_at = None) # little trick to get around GAE limitation # order by uuid only when no inequality has been added if cast == None or order_by == 'cast_at' or order_by =='-cast_at': query = query.order_by(order_by) # if we want the list after a certain UUID, add the inequality here if after: if order_by[0] == '-': field_name = "%s__gt" % order_by[1:] else: field_name = "%s__gt" % order_by conditions = {field_name : after} query = query.filter (**conditions) if limit: query = query[:limit] return query @classmethod def get_all_by_election_in_chunks(cls, election, cast=None, chunk=100): return cls.get_by_election(election) @classmethod def get_by_election_and_voter_id(cls, election, voter_id): try: return cls.objects.get(election = election, voter_login_id = voter_id.strip()) except cls.DoesNotExist: return None @classmethod def get_by_election_and_user(cls, election, user): try: return cls.objects.get(election = election, user = user) except cls.DoesNotExist: return None @classmethod def get_by_election_and_uuid(cls, election, uuid): query = cls.objects.filter(election = election, uuid = uuid) try: return query[0] except: return None @classmethod def get_by_user(cls, user): return cls.objects.select_related().filter(user = user).order_by('-cast_at') @property def datatype(self): return self.election.datatype.replace('Election', 'Voter') @property def vote_tinyhash(self): """ get the tinyhash of the latest castvote """ if not self.vote_hash: return None return CastVote.objects.get(vote_hash = self.vote_hash).vote_tinyhash @property def election_uuid(self): return self.election.uuid @property def name(self): return self.user.name @property def voter_id(self): return self.user.user_id @property def voter_id_hash(self): if self.voter_login_id: # for backwards compatibility with v3.0, and since it doesn't matter # too much if we hash the email or the unique login ID here. value_to_hash = self.voter_login_id.strip() else: value_to_hash = self.voter_id.strip() try: return utils.hash_b64(value_to_hash) except: try: return utils.hash_b64(value_to_hash.encode('latin-1')) except: return utils.hash_b64(value_to_hash.encode('utf-8')) @property def voter_type(self): return self.user.user_type @property def display_html_big(self): return self.user.display_html_big def send_message(self, subject, body): self.user.send_message(subject, body) def generate_password(self, length=10): if self.voter_password: raise Exception(_('password already exists')) # CSV_VOTERS_PASSWORD_SIMPLIFIED means password generated with 6 letters and just in lowercase. if settings.CSV_VOTERS_PASSWORD_SIMPLIFIED: length = 06 self.voter_password = heliosutils.random_string(length, alphabet='abcdefghijkmnopqrstuvwxyz').strip() else: self.voter_password = heliosutils.random_string(length, alphabet='abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789').strip() # metadata for the election @property def metadata(self): return { 'voter_email': self.voter_email, 'uuid': self.uuid, 'voter_name': self.voter_name, 'vote_hash': self.vote_hash, 'cast_at': self.cast_at, 'alias': self.alias, 'user_id': self.user.user_id, 'election id': self.election.id, 'election name': self.election.name, 'election url': self.election.url } def store_vote(self, cast_vote): # only store the vote if it's cast later than the current one if self.cast_at and cast_vote.cast_at < self.cast_at: return self.vote = cast_vote.vote self.vote_hash = cast_vote.vote_hash self.cast_at = cast_vote.cast_at self.save() def last_cast_vote(self): return CastVote(vote = self.vote, vote_hash = self.vote_hash, cast_at = self.cast_at, voter=self)
def get_user_session(username): user = User.get_by_type_and_id('password', username) if (user): return user raise_exception(404, 'User not found.')
def get_user(pk): user = User.get_by_type_and_id('password', pk) if (user): return user else: raise_exception(404,'User not found.')
class Voter(HeliosModel): election = models.ForeignKey(Election) # let's link directly to the user now # FIXME: delete this as soon as migrations are set up #name = models.CharField(max_length = 200, null=True) #voter_type = models.CharField(max_length = 100) #voter_id = models.CharField(max_length = 100) uuid = models.CharField(max_length=50) # for users of type password, no user object is created # but a dynamic user object is created automatically user = models.ForeignKey('helios_auth.User', null=True) # if user is null, then you need a voter login ID and password voter_login_id = models.CharField(max_length=100, null=True) voter_password = models.CharField(max_length=100, null=True) voter_name = models.CharField(max_length=200, null=True) voter_email = models.CharField(max_length=250, null=True) # if election uses aliases alias = models.CharField(max_length=100, null=True) # we keep a copy here for easy tallying vote = LDObjectField(type_hint='legacy/EncryptedVote', null=True) vote_hash = models.CharField(max_length=100, null=True) cast_at = models.DateTimeField(auto_now_add=False, null=True) class Meta: unique_together = (('election', 'voter_login_id')) def __init__(self, *args, **kwargs): super(Voter, self).__init__(*args, **kwargs) # stub the user so code is not full of IF statements if not self.user: self.user = User(user_type='password', user_id=self.voter_email, name=self.voter_name) @classmethod @transaction.atomic def register_user_in_election(cls, user, election): voter_uuid = str(uuid.uuid4()) voter = Voter(uuid=voter_uuid, user=user, election=election) # do we need to generate an alias? if election.use_voter_aliases: heliosutils.lock_row(Election, election.id) alias_num = election.last_alias_num + 1 voter.alias = "V%s" % alias_num voter.save() return voter @classmethod def get_by_election(cls, election, cast=None, order_by='voter_login_id', after=None, limit=None): """ FIXME: review this for non-GAE? """ query = cls.objects.filter(election=election) # the boolean check is not stupid, this is ternary logic # none means don't care if it's cast or not if cast == True: query = query.exclude(cast_at=None) elif cast == False: query = query.filter(cast_at=None) # little trick to get around GAE limitation # order by uuid only when no inequality has been added if cast == None or order_by == 'cast_at' or order_by == '-cast_at': query = query.order_by(order_by) # if we want the list after a certain UUID, add the inequality here if after: if order_by[0] == '-': field_name = "%s__gt" % order_by[1:] else: field_name = "%s__gt" % order_by conditions = {field_name: after} query = query.filter(**conditions) if limit: query = query[:limit] return query @classmethod def get_all_by_election_in_chunks(cls, election, cast=None, chunk=100): return cls.get_by_election(election) @classmethod def get_by_election_and_voter_id(cls, election, voter_id): try: return cls.objects.get(election=election, voter_login_id=voter_id) except cls.DoesNotExist: return None @classmethod def get_by_election_and_user(cls, election, user): try: return cls.objects.get(election=election, user=user) except cls.DoesNotExist: return None @classmethod def get_by_election_and_uuid(cls, election, uuid): query = cls.objects.filter(election=election, uuid=uuid) try: return query[0] except: return None @classmethod def get_by_user(cls, user): return cls.objects.select_related().filter( user=user).order_by('-cast_at') @property def datatype(self): return self.election.datatype.replace('Election', 'Voter') @property def vote_tinyhash(self): """ get the tinyhash of the latest castvote """ if not self.vote_hash: return None return CastVote.objects.get(vote_hash=self.vote_hash).vote_tinyhash @property def election_uuid(self): return self.election.uuid @property def name(self): return self.user.name @property def voter_id(self): return self.user.user_id @property def voter_id_hash(self): if self.voter_login_id: # for backwards compatibility with v3.0, and since it doesn't matter # too much if we hash the email or the unique login ID here. value_to_hash = self.voter_login_id else: value_to_hash = self.voter_id try: return utils.hash_b64(value_to_hash) except: try: return utils.hash_b64(value_to_hash.encode('latin-1')) except: return utils.hash_b64(value_to_hash.encode('utf-8')) @property def voter_type(self): return self.user.user_type @property def display_html_big(self): return self.user.display_html_big def send_message(self, subject, body): self.user.send_message(subject, body) def generate_password(self, length=10): if self.voter_password: raise Exception("password already exists") self.voter_password = heliosutils.random_string( length, alphabet='abcdefghjkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789' ) def store_vote(self, cast_vote): # only store the vote if it's cast later than the current one if self.cast_at and cast_vote.cast_at < self.cast_at: return self.vote = cast_vote.vote self.vote_hash = cast_vote.vote_hash self.cast_at = cast_vote.cast_at self.save() def last_cast_vote(self): return CastVote(vote=self.vote, vote_hash=self.vote_hash, cast_at=self.cast_at, voter=self)
def get_user_info_after_auth(request): from helios_auth.models import User user = User.get_by_type_and_id('password', request.session['password_user_id']) del request.session['password_user_id'] return {'type': 'password', 'user_id' : user.user_id, 'name': user.name, 'info': user.info, 'token': None}