def submit_vote(requester: Member, session: Session): election_id = request.json['election_id'] election = session.query(Election).get(election_id) if election.status == 'final' or election.status == 'polls closed': return BadRequest('You may not submit a vote after the polls have closed') eligible = session.query(EligibleVoter). \ filter_by(member_id=requester.id, election_id=election_id).with_for_update().one_or_none() if not eligible: return BadRequest('You are not eligible for this election.') if eligible.voted: return BadRequest('You have either already voted or received a paper ballot for this ' 'election.') eligible.voted = True vote, rolled_back = create_vote(session, election_id, 6) if rolled_back: # If we lost the lock we have to recheck eligible = session.query(EligibleVoter). \ filter_by(member_id=requester.id, election_id=election_id).with_for_update().one_or_none() if eligible.voted: return BadRequest('You have either already voted or received a paper ballot for this ' 'election.') eligible.voted = True for rank, candidate_id in enumerate(request.json['rankings']): ranking = Ranking(rank=rank, candidate_id=candidate_id) vote.ranking.append(ranking) session.add(vote) session.commit() return jsonify({'ballot_id': vote.vote_key})
def add_voter(requester: Member, session: Session): election_id = request.json['election_id'] member_id = request.json.get('member_id', requester.id) eligible_voter = EligibleVoter(member_id=member_id, election_id=election_id) session.add(eligible_voter) session.commit() return jsonify({'status': 'success'})
def add_member(requester: Member, session: Session): member = Member(**request.json) verify_url = create_auth0_user(member.email_address) send_welcome_email(member.email_address, member.first_name, verify_url) session.add(member) session.commit() return jsonify({'status': 'success'})
def submit_paper_vote(requester: Member, session: Session): election_id = request.json['election_id'] election = session.query(Election).get(election_id) if election.status == 'final': return BadRequest('You may not submit more votes after an election has been marked final') vote_key = request.json['ballot_key'] vote = session.query(Vote).filter_by( election_id=election_id, vote_key=vote_key).with_for_update().one_or_none() if not vote: return Response('Ballot #{} for election_id={} not claimed'.format(vote_key, election_id), 404) if vote.ranking and not request.json.get('override', False): if len(vote.ranking) != len(request.json['rankings']): return jsonify({'status': 'mismatch'}) for rank, candidate_id in enumerate(request.json['rankings']): if candidate_id != vote.ranking[rank].candidate_id: return jsonify({'status': 'mismatch'}) return jsonify({'status': 'match'}) if request.json.get('override', False): for rank in vote.ranking: session.delete(rank) for rank, candidate_id in enumerate(request.json['rankings']): ranking = Ranking(rank=rank, candidate_id=candidate_id) vote.ranking.append(ranking) session.add(vote) session.commit() return jsonify({'status': 'new'})
def add_meeting(requester: Member, session: Session): member_id = request.json.get('member_id', requester.id) attend = Attendee(member_id=member_id, meeting_id=request.json['meeting_id']) session.add(attend) session.commit() return jsonify({'status': 'success'})
def make_admin(requester: Member, session: Session): member = session.query(Member).filter_by( email_address=request.json['email_address']).one() committee_id = request.json[ 'committee'] if request.json['committee'] != '0' else None role = Role(member_id=member.id, role='admin', committee_id=committee_id) session.add(role) session.commit() return jsonify({'status': 'success'})
def add_role(requester: Member, session: Session): member_id = request.json.get('member_id', requester.id) committee_id = request.json[ 'committee_id'] if request.json['committee_id'] != '0' else None role = Role(member_id=member_id, role=request.json['role'], committee_id=committee_id) session.add(role) session.commit() return jsonify({'status': 'success'})
def add_election(requester: Member, session: Session): election = Election(name=request.json['name']) session.add(election) candidates = request.json['candidate_list'].split(',') members = session.query(Member).filter(Member.email_address.in_(candidates)).all() for member in members: candidate = Candidate() candidate.election = election candidate.member = member session.add(candidate) session.commit() return jsonify({'status': 'success'})
def add_committee(requester: Member, session: Session): committee = Committee(name=request.json['name']) session.add(committee) admins = request.json['admin_list'].split(',') members = session.query(Member).filter( Member.email_address.in_(admins)).all() for member in members: role = Role(role='admin') role.committee = committee role.member = member session.add(role) session.commit() return jsonify({'status': 'success'})
def test_election(self): num_votes = 500 session = Session() a = Member(first_name='A', last_name='B') session.add(a) c = Member(first_name='C', last_name='D') session.add(c) e = Member(first_name='E', last_name='F') candidates = [] for member in [a, c, e]: cand = Candidate() cand.member = member candidates.append(cand) session.add(e) election = Election(name='Test', number_winners=2) election.candidates.extend(candidates) session.add(election) for i in range(0, num_votes): shuffle(candidates) vote = Vote() election.votes.append(vote) for j, cand in enumerate(candidates): rank = Ranking(rank=i) rank.candidate = cand vote.ranking.append(rank) session.commit() session.close() session = Session() election = session.query(Election).filter_by(name='Test').one() results = hold_election(election) assert len(results.winners) == 2 assert len(results.votes) == num_votes
def attend_meeting(requester: Member, session: Session): short_id = request.json['meeting_short_id'] meeting = session.query(Meeting).filter_by(short_id=short_id).one_or_none() if not meeting: return BadRequest('Invalid meeting id') if len( session.query(Attendee).filter_by( meeting_id=meeting.id, member_id=requester.id).all()) > 0: return BadRequest('You have already logged into this meeting') a = Attendee() a.meeting = meeting a.member = requester session.add(a) session.commit() return jsonify({'status': 'success'})
def test_election_prob(self, data): # Set up the SQLAlchemy session metadata.drop_all(engine) metadata.create_all(engine) session = Session() # Randomly generate parameters num_votes = data.draw(st.integers(min_value=0, max_value=500)) num_candidates = data.draw(st.integers(min_value=1, max_value=10)) num_winners = data.draw( st.integers(min_value=1, max_value=num_candidates)) # Create candidates as members and add them to the DB candidate_members = [ Member(first_name=str(i), last_name=str(i)) for i in range(num_candidates) ] session.add_all(candidate_members) # Create candidates as candidates and add them to the DB candidates = [Candidate(member=member) for member in candidate_members] session.add_all(candidates) # Create the election and add to DB election = Election(name='Test2', number_winners=num_winners) election.candidates.extend(candidates) session.add(election) # Generate votes for the candidates for i in range(num_votes): shuffle(candidates) vote = Vote() election.votes.append(vote) for j, cand in enumerate(candidates): rank = Ranking(rank=i) rank.candidate = cand vote.ranking.append(rank) # Commit everything to DB session.commit() session.close() # Get the election back from the DB, hold the election new_session = Session() election = new_session.query(Election).filter_by(name='Test2').one() results = hold_election(election) # Check the results assert len(results.winners) == num_winners assert len(results.votes) == num_votes
def create_vote(session: Session, election_id: int, digits: int): i = 0 rolled_back = False while i < 5: try: a = random.randint(10 ** (digits - 1), 10 ** digits - 1) v = Vote(vote_key=a, election_id=election_id) session.add(v) session.commit() return v, rolled_back except IntegrityError: print('Had to retry') i += 1 session.rollback() rolled_back = True raise Exception('Failing to find a random key in five tries. Think something is wrong.')