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 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 election_count(requester: Member, session: Session): election_id = request.args['id'] election = session.query(Election).get(election_id) stv = hold_election(election) winners = [session.query(Candidate).get(cid).member.name for cid in stv.winners] round_information = {} for round_number, round in enumerate(stv.previous_rounds): candidate_information = {} for cid, vote_info in round.items(): candidate_name = session.query(Candidate).get(cid).member.name candidate_information[candidate_name] = vote_info round_information[round_number + 1] = candidate_information return custom_jsonify(data={'winners': winners, 'round_information': round_information}, encoder=CustomEncoder)
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(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 decorated(*args, **kwargs): if USE_AUTH: auth = request.headers.get('authorization') if not auth: return deny('Authorization not found.') token = auth.split()[1] try: token = jwt.decode(token, JWT_SECRET, audience=JWT_CLIENT_ID) except Exception as e: return deny(str(e)) email = token.get('email') else: email = NO_AUTH_EMAIL session = Session() try: member = session.query(Member).filter_by(email_address=email).one() authenticated = False if admin: for role in member.roles: if role.committee_id is None and role.role == 'admin': authenticated = True else: authenticated = True if authenticated: kwargs['requester'] = member kwargs['session'] = session return f(*args, **kwargs) return deny('not enough access') finally: session.close()
def get_election_by_id(requester: Member, session: Session): election = session.query(Election).get(request.args.get('id')) result = {'name': election.name, 'number_winners': election.number_winners, 'candidates': [{'id': candidate.id, 'name': candidate.member.name} for candidate in election.candidates], 'status': election.status} return jsonify(result)
def get_eligible(requester: Member, session: Session): election_id = request.args['election_id'] eligibles = session.query(EligibleVoter)\ .filter_by(election_id=election_id).options(joinedload(EligibleVoter.member)).all() results = {} for eligible in eligibles: results[eligible.member_id] = {'name': eligible.member.name, 'email_address': eligible.member.email_address} return jsonify(results)
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 get_members(requester: Member, session: Session): results = [] members = session.query(Member).all() for member in members: results.append({ 'id': member.id, 'name': member.name, 'email': member.email_address }) return jsonify(results)
def get_vote(requester: Member, session: Session, election_id: int, ballot_key: int): vote = session.query(Vote).filter(Vote.election_id == election_id, Vote.vote_key == ballot_key).one_or_none() if not vote: return Response('Ballot #{} has not been cast for election_id={}'.format(ballot_key, election_id), 404) else: rankings = [ranking.candidate_id for ranking in vote.ranking] return jsonify({ 'election_id': election_id, 'ballot_key': ballot_key, 'rankings': rankings })
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 issue_ballot(requester: Member, session: Session): election_id = request.json['election_id'] member_id = request.json['member_id'] eligible = session.query(EligibleVoter). \ filter_by(member_id=member_id, election_id=election_id).with_for_update().one_or_none() if not eligible: return BadRequest('Voter is not eligible for this election.') if eligible.voted: return BadRequest('Voter has either already voted or received a paper ballot for this ' 'election.') eligible.voted = True 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_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 get_elections(requester: Member, session: Session): elections = session.query(Election).all() result = {e.id: e.name for e in elections} return jsonify(result)
def get_member_info(requester: Member, session: Session): other_member = session.query(Member).get(request.args['member_id']) return jsonify(get_member_details_helper(other_member))
def get_committees(requester: Member, session: Session): committees = session.query(Committee).all() result = {c.id: c.name for c in committees} return jsonify(result)
def get_meeting(requester: Member, session: Session): meetings = session.query(Meeting).all() result = {m.id: m.name for m in meetings} return jsonify(result)