예제 #1
0
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'})
예제 #2
0
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})
예제 #3
0
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)
예제 #4
0
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'})
예제 #5
0
    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
예제 #6
0
 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()
예제 #7
0
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)
예제 #8
0
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)
예제 #9
0
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'})
예제 #10
0
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)
예제 #11
0
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
        })
예제 #12
0
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'})
예제 #13
0
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'})
예제 #14
0
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'})
예제 #15
0
    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
예제 #16
0
def get_elections(requester: Member, session: Session):
    elections = session.query(Election).all()
    result = {e.id: e.name for e in elections}
    return jsonify(result)
예제 #17
0
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))
예제 #18
0
def get_committees(requester: Member, session: Session):
    committees = session.query(Committee).all()
    result = {c.id: c.name for c in committees}
    return jsonify(result)
예제 #19
0
def get_meeting(requester: Member, session: Session):
    meetings = session.query(Meeting).all()
    result = {m.id: m.name for m in meetings}
    return jsonify(result)