def test_start_election(client, blank_user): blank_user.set_board(FELLOW_BOARD, True) tests.utils.web_login(client, blank_user) assert maintenance.get_election() is None result = tests.utils.web_dike_begin_election(client) assert result.status_code in (200, 302) assert maintenance.get_election() is not None
def register(): election = maintenance.get_election() if election is None: flash(f'Wybory nie są aktywne.') return redirect(url_for('base.index')) elif not election.check_flag(ELECTION_REGISTER): flash(f'Rejestracja nie jest aktywna') return redirect(url_for('base.index')) form = RegisterForm() if form.validate_on_submit(): if current_user.check_password(form.password.data): kmsid = form.kmsid.data log.debug(f'Trying to register candidate by kms id: {kmsid}') fellow = Fellow.query.filter_by(id=kmsid).first() log.info(f'Trying to register candidate: {fellow}') if not fellow.check_board(FELLOW_ACTIVE): log.warning(f'Candidate is not an active fellow: {fellow}.') flash(f'Kandydat nie jest aktywnym członkiem.') return redirect(url_for('base.index')) for position in election.positions.all(): if position.is_registered(fellow): log.warning(f'Candidate is already registered: {fellow}') flash('Kandydat został już zarejestrowany.') return redirect(url_for('base.index')) register_candidate(form, election) log.info(f'New candidate registered: {fellow}') flash('Kandydat zarejestrowany poprawnie.') return redirect(url_for('base.index')) else: flash('Podane hasło jest niepoprawne.') return render_template('dike/register.html', form=form)
def seedvote(): log.info("Seeding votes") electoral = maintenance.get_electoral(maintenance.get_election()) class DynamicBallotForm(BallotForm): pass for position in electoral: for candidate in electoral[position]: setattr(DynamicBallotForm, f'{position.id}+{candidate.id}', HiddenField(default="n")) for i in range(144): form = DynamicBallotForm() for position in electoral: j = 1 rnd.shuffle(electoral[position]) for candidate in electoral[position]: if rnd.random() < 0.3: k = 'x' elif rnd.random() < 0.3: k = 'n' else: k = j j += 1 setattr(getattr(form, f'{position.id}+{candidate.id}'), 'data', k) store_votes(form, electoral) return redirect(url_for('dike.panel'))
def seedregister(): log.info("Seeding registration") election = maintenance.get_election() for fellow in Fellow.query.all(): form = RegisterForm() form.kmsid.data = fellow.studentid form.boss.data, form.vice.data, form.treasure.data, form.library.data, form.secret.data, form.free.data, form.covision.data = rnd.choices( [False, True], weights=[5, 2], k=7) register_candidate(form, election) flash('Register Seeded') return redirect(url_for('dike.panel'))
def test_register_inactive_candidate(client, blank_user, users): blank_user.set_board(FELLOW_BOARD, True) tests.utils.web_login(client, blank_user) maintenance.begin_election() users[0].set_board(FELLOW_ACTIVE, False) tests.utils.web_dike_register(client, users[0], [POSITION_COVISION]) election = maintenance.get_election() assert set( election.positions.filter_by( name=POSITION_COVISION).first().candidates.all()) == set()
def test_register_candidates_without_free(client, blank_user, users): blank_user.set_board(FELLOW_BOARD, True) tests.utils.web_login(client, blank_user) maintenance.begin_election() tests.utils.web_dike_register( client, users[0], [POSITION_BOSS, POSITION_VICE, POSITION_FREE]) tests.utils.web_dike_register(client, users[1], [POSITION_BOSS, POSITION_VICE]) election = maintenance.get_election() assert set( election.positions.filter_by( name=POSITION_BOSS).first().candidates.all()) == {users[0]}
def test_register_candidates_board_covision_conflict_allowed( client, blank_user, users, feature_flags): feature_flags.disable( FEATURE_DIKE_CANDIDATE_BOARD_COVISION_CONFLICT_FORBIDDEN) blank_user.set_board(FELLOW_BOARD, True) tests.utils.web_login(client, blank_user) maintenance.begin_election() tests.utils.web_dike_register(client, users[0], ["boss", "free"]) tests.utils.web_dike_register(client, users[1], ["boss", "free", "covision"]) election = maintenance.get_election() assert set( election.positions.filter_by( name="boss").first().candidates.all()) == {users[0], users[1]}
def test_register_candidates_board_covision_conflict_forbidden( client, blank_user, users, feature_flags): feature_flags.enable( FEATURE_DIKE_CANDIDATE_BOARD_COVISION_CONFLICT_FORBIDDEN) blank_user.set_board(FELLOW_BOARD, True) tests.utils.web_login(client, blank_user) maintenance.begin_election() tests.utils.web_dike_register(client, users[0], [POSITION_BOSS, POSITION_FREE]) tests.utils.web_dike_register( client, users[1], [POSITION_BOSS, POSITION_FREE, POSITION_COVISION]) election = maintenance.get_election() assert set( election.positions.filter_by( name=POSITION_BOSS).first().candidates.all()) == {users[0]}
def test_register_candidates(client, blank_user, users): blank_user.set_board(FELLOW_BOARD, True) tests.utils.web_login(client, blank_user) maintenance.begin_election() tests.utils.web_dike_register( client, users[0], [POSITION_BOSS, POSITION_VICE, POSITION_FREE]) tests.utils.web_dike_register( client, users[1], [POSITION_BOSS, POSITION_TREASURE, POSITION_LIBRARY, POSITION_FREE]) tests.utils.web_dike_register(client, users[2], [POSITION_COVISION]) election = maintenance.get_election() assert set( election.positions.filter_by( name=POSITION_BOSS).first().candidates.all()) == { users[0], users[1] } assert set( election.positions.filter_by( name=POSITION_VICE).first().candidates.all()) == {users[0]} assert set( election.positions.filter_by( name=POSITION_TREASURE).first().candidates.all()) == {users[1]} assert set( election.positions.filter_by( name=POSITION_SECRET).first().candidates.all()) == set() assert set( election.positions.filter_by( name=POSITION_LIBRARY).first().candidates.all()) == {users[1]} assert set( election.positions.filter_by( name=POSITION_FREE).first().candidates.all()) == { users[0], users[1] } assert set( election.positions.filter_by( name=POSITION_COVISION).first().candidates.all()) == {users[2]}
def web_dike_ballot(client, preferences, kmsid=None, password=None): kmsid = kmsid or flask_login.current_user.id password = password or get_default_password(flask_login.current_user.email) data = { "kmsid": kmsid, "password": password, } election = get_election() for preference in preferences: positions = election.positions.filter_by( name=preference["position"]).all() assert len(positions) == 1 position = positions[0] fellow = preference["fellow"] rank = preference["rank"] data[f"{position.id}+{fellow.id}"] = rank log.debug(f"ballot data = {data}") client.post("/dike/ballot", data=data)
def test_election_reckoning_bystage(client, blank_user, users): blank_user.set_board(FELLOW_BOARD, True) tests.utils.web_login(client, blank_user) tests.utils.web_dike_begin_election(client) tests.utils.web_dike_register(client, users[0], [POSITION_BOSS]) tests.utils.web_dike_register(client, users[1], [POSITION_VICE]) # stage boss tests.utils.web_dike_begin_voting(client) tests.utils.web_dike_end_voting(client) # reckoning client.get("/dike/reckoning") election = maintenance.get_election() positions = election.positions.all() for position in positions: if position.name == POSITION_BOSS: assert position.is_reckoned else: assert not position.is_reckoned
def __call__(self, form, field): if field.data is None: return match = re.match(r"^\d+(\+\d+)*$", field.data) if not match: logged_validation_error("Invalid request format") fellows = [int(k) for k in field.data.split("+")] if self.maximum is not None and len(fellows) > self.maximum: logged_validation_error( f"Maximal number of candidates for {self.position} exceeded: {self.maximum}" ) election = maintenance.get_election() position = election.positions.filter_by(name=self.position).first() for fellow_id in fellows: if position.elected.filter_by(id=fellow_id).scalar() is None: fellow = lada.models.Fellow.query.filter_by( id=fellow_id).first() logged_validation_error( f"Fellow {str(fellow)} is not elected for position {self.position}" )
def endscreen(): election = maintenance.get_election() if not (not (election is None) and not election.check_flag(ELECTION_REGISTER)): flash(f'Głosowanie nie jest aktywne.') elif election.check_flag(ELECTION_VOTING): flash(f'Głosowanie nie zostało zakończone.') if not verify_voters(election): flash('Illegal voter detected') board = get_board() _, entitled = maintenance.reckon_election(election) checksum = compute_fellows_checksum(entitled) form = EndscreenForm() if form.validate_on_submit(): maintenance.end_election(election) return redirect(url_for('base.board')) return render_template('dike/endscreen.html', form=form, board=board, checksum=checksum)
def ballot(): election = maintenance.get_election() if election is None: flash(f'Wybory nie są aktywne.') return redirect(url_for('base.index')) elif not election.check_flag(ELECTION_VOTING): flash(f'Głosowanie nie jest aktywne.') return redirect(url_for('base.index')) if not election.is_entitled_to_vote(current_user): flash(f'Nie masz prawa wyborczego w tych wyborach.') return redirect(url_for('base.index')) if election.did_vote(current_user): flash(f'Oddano już głos w tych wyborach.') return redirect(url_for('base.index')) electoral = maintenance.get_electoral(election) class DynamicBallotForm(BallotForm): pass for position in electoral: for candidate in electoral[position]: setattr(DynamicBallotForm, f'{position.id}+{candidate.id}', HiddenField(default="n")) form = DynamicBallotForm() if form.validate_on_submit(): store_votes(form, electoral) election.add_voter(current_user) db.session.commit() log.info('New ballot received') flash('Głos oddany poprawnie.') return redirect(url_for('dike.afterballot')) return render_template('dike/ballot.html', form=form, electoral=electoral)
def reckon(): election = maintenance.get_election() maintenance.reckon_election(election) flash('reckoned') return redirect(url_for('dike.panel'))
def reckoning(): election = maintenance.get_election() if not (not (election is None) and not election.check_flag(ELECTION_REGISTER)): flash(f'Głosowanie nie jest aktywne.') elif election.check_flag(ELECTION_VOTING): flash(f'Głosowanie nie zostało zakończone.') if not verify_voters(election): flash('Illegal voter detected') try: results, entitled = maintenance.reckon_election(election) except ArbitraryDiscardDecisionNeededError as e: form = ArbitraryDiscardDecisionForm() form.position.data = e.position.id return render_template('dike/arbitrary_discard_decision.html', form=form, election=e.election, position=e.position, candidates=e.candidates) checksum = compute_fellows_checksum(entitled) if election.is_stage(STAGE_BOSS): form = ReckoningFormBoss() if form.validate_on_submit(): boss = results[0]['elected'][0] election.positions.filter_by( name=POSITION_BOSS).first().choose(boss) for position in election.positions.filter( Position.name != POSITION_BOSS).all(): position.unregister(boss) maintenance.begin_registration(election) return redirect(url_for('dike.panel')) return render_template('dike/reckoning.html', form=form, results=results, checksum=checksum, stage=election.stage) elif election.is_stage(STAGE_BOARD): form = ReckoningFormBoard() if form.validate_on_submit(): maintenance.store_chosen(election, form) maintenance.begin_registration(election) return redirect(url_for('dike.panel')) return render_template('dike/reckoning.html', form=form, results=results, checksum=checksum, stage=election.stage) elif election.is_stage(STAGE_COVISION): form = ReckoningFormCovision() if form.validate_on_submit(): for covision in results[0]['elected']: election.positions.filter_by( name=POSITION_COVISION).first().choose(covision) maintenance.set_board(election) return redirect(url_for('dike.endscreen')) return render_template('dike/reckoning.html', form=form, results=results, checksum=checksum, stage=election.stage)
def test_election_reckoning_tie_breaking(client, blank_user, users): blank_user.set_board(FELLOW_BOARD, True) tests.utils.web_login(client, blank_user) tests.utils.web_dike_begin_election(client) tests.utils.web_dike_register(client, users[0], [POSITION_BOSS, POSITION_FREE]) tests.utils.web_dike_register(client, users[1], [POSITION_BOSS, POSITION_FREE]) tests.utils.web_dike_register(client, users[2], [POSITION_BOSS, POSITION_FREE]) tests.utils.web_dike_register(client, users[3], [POSITION_BOSS, POSITION_FREE]) # stage boss tests.utils.web_dike_begin_voting(client) tests.utils.web_login(client, users[0]) tests.utils.web_dike_ballot(client, [ { "fellow": users[3], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[0], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[1]) tests.utils.web_dike_ballot(client, [ { "fellow": users[0], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[2]) tests.utils.web_dike_ballot(client, [ { "fellow": users[0], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[3]) tests.utils.web_dike_ballot(client, [ { "fellow": users[0], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[4]) tests.utils.web_dike_ballot(client, [ { "fellow": users[0], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[5]) tests.utils.web_dike_ballot(client, [ { "fellow": users[0], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[6]) tests.utils.web_dike_ballot(client, [ { "fellow": users[1], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[0], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[7]) tests.utils.web_dike_ballot(client, [ { "fellow": users[1], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[0], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[8]) tests.utils.web_dike_ballot(client, [ { "fellow": users[1], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[0], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[9]) tests.utils.web_dike_ballot(client, [ { "fellow": users[1], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[2], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[0], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[10]) tests.utils.web_dike_ballot(client, [ { "fellow": users[2], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[0], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[11]) tests.utils.web_dike_ballot(client, [ { "fellow": users[2], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[0], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[12]) tests.utils.web_dike_ballot(client, [ { "fellow": users[2], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[0], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, users[13]) tests.utils.web_dike_ballot(client, [ { "fellow": users[2], "position": POSITION_BOSS, "rank": 1 }, { "fellow": users[1], "position": POSITION_BOSS, "rank": 2 }, { "fellow": users[0], "position": POSITION_BOSS, "rank": 3 }, { "fellow": users[3], "position": POSITION_BOSS, "rank": 4 }, ]) tests.utils.web_login(client, blank_user) tests.utils.web_dike_end_voting(client) tests.utils.web_dike_reckon_boss(client) election = maintenance.get_election() positions = election.positions.all() for position in positions: log.debug(f'{position.name}') if position.name == POSITION_BOSS: assert position.is_reckoned assert position.is_chosen(users[2])
def test_election_reckoning(client, blank_user, users): blank_user.set_board(FELLOW_BOARD, True) tests.utils.web_login(client, blank_user) tests.utils.web_dike_begin_election(client) tests.utils.web_dike_register(client, users[0], [POSITION_BOSS, POSITION_FREE]) tests.utils.web_dike_register(client, users[1], [POSITION_VICE, POSITION_FREE]) tests.utils.web_dike_register(client, users[2], [POSITION_TREASURE, POSITION_FREE]) tests.utils.web_dike_register(client, users[3], [POSITION_SECRET, POSITION_FREE]) tests.utils.web_dike_register(client, users[4], [POSITION_LIBRARY, POSITION_FREE]) tests.utils.web_dike_register(client, users[5], [POSITION_FREE]) tests.utils.web_dike_register(client, users[6], [POSITION_FREE]) tests.utils.web_dike_register(client, users[7], [POSITION_FREE]) tests.utils.web_dike_register(client, users[8], [POSITION_COVISION]) tests.utils.web_dike_register(client, users[9], [POSITION_COVISION]) tests.utils.web_dike_register(client, users[10], [POSITION_COVISION]) tests.utils.web_dike_register(client, users[11], [POSITION_VICE, POSITION_FREE]) tests.utils.web_dike_register(client, users[12], [POSITION_TREASURE, POSITION_FREE]) # stage boss tests.utils.web_dike_begin_voting(client) tests.utils.web_login(client, users[0]) tests.utils.web_dike_ballot(client, [ { "fellow": users[0], "position": POSITION_BOSS, "rank": 1 }, ]) tests.utils.web_login(client, blank_user) tests.utils.web_dike_end_voting(client) tests.utils.web_dike_reckon_boss(client) # stage board tests.utils.web_dike_begin_voting_board(client) tests.utils.web_login(client, users[0]) tests.utils.web_dike_ballot(client, [ { "fellow": users[1], "position": POSITION_VICE, "rank": 1 }, { "fellow": users[2], "position": POSITION_TREASURE, "rank": 1 }, { "fellow": users[3], "position": POSITION_SECRET, "rank": 1 }, { "fellow": users[4], "position": POSITION_LIBRARY, "rank": 1 }, { "fellow": users[5], "position": POSITION_FREE, "rank": 1 }, { "fellow": users[6], "position": POSITION_FREE, "rank": 2 }, { "fellow": users[7], "position": POSITION_FREE, "rank": 3 }, ]) tests.utils.web_login(client, users[1]) tests.utils.web_dike_ballot(client, [ { "fellow": users[11], "position": POSITION_VICE, "rank": 1 }, { "fellow": users[12], "position": POSITION_TREASURE, "rank": 1 }, ]) tests.utils.web_login(client, blank_user) tests.utils.web_dike_end_voting(client) tests.utils.web_dike_reckon_board(client, [ { "position": POSITION_VICE, "fellows": [users[11]] }, { "position": POSITION_TREASURE, "fellows": [users[2]] }, { "position": POSITION_SECRET, "fellows": [users[3]] }, { "position": POSITION_LIBRARY, "fellows": [users[4]] }, { "position": POSITION_FREE, "fellows": [users[1], users[6], users[7]] }, ]) # stage covision tests.utils.web_dike_begin_voting_covision(client) tests.utils.web_login(client, users[0]) tests.utils.web_dike_ballot(client, [ { "fellow": users[8], "position": POSITION_COVISION, "rank": 1 }, { "fellow": users[9], "position": POSITION_COVISION, "rank": 2 }, { "fellow": users[10], "position": POSITION_COVISION, "rank": 3 }, ]) tests.utils.web_login(client, blank_user) tests.utils.web_dike_end_voting(client) tests.utils.web_dike_reckon_covision(client) election = maintenance.get_election() positions = election.positions.all() for position in positions: assert position.is_reckoned assert users[0].check_board(POSITION_BOSS) assert users[0].check_board(FELLOW_BOARD) assert users[11].check_board(POSITION_VICE) assert users[2].check_board(POSITION_TREASURE) assert users[3].check_board(POSITION_SECRET) assert users[4].check_board(POSITION_LIBRARY) assert users[1].check_board(POSITION_FREE) assert users[6].check_board(POSITION_FREE) assert users[7].check_board(POSITION_FREE) assert users[8].check_board(POSITION_COVISION) assert users[9].check_board(POSITION_COVISION) assert users[10].check_board(POSITION_COVISION) assert not users[12].check_board(POSITION_TREASURE) assert not users[12].check_board(FELLOW_BOARD)
def panel(): election = maintenance.get_election() form = PanelForm() log.debug('Dike panel opened') if election is None: if form.validate_on_submit(): maintenance.begin_election() flash(f'Rozpoczęto wybory.') return redirect(url_for('dike.panel')) return render_template('dike/panel.html', form=form, mode='inactive') elif election.check_flag(ELECTION_REGISTER): class DynamicPanelForm(PanelForm): pass electoral = maintenance.get_electoral(election, full=True) for position in electoral: for candidate in electoral[position]: setattr(DynamicPanelForm, f'{position.id}+{candidate.id}', HiddenField(default="n")) form = DynamicPanelForm() if form.validate_on_submit(): if form.unregister_candidates.data: unregister_candidates(form, election) return redirect(url_for('dike.panel')) if form.begin_voting_boss.data: election.set_stage(STAGE_BOSS) elif form.begin_voting_board.data: election.set_stage(STAGE_BOARD) elif form.begin_voting_covision.data: election.set_stage(STAGE_COVISION) maintenance.begin_voting(election) flash(f'Rozpoczęto głosowanie.') return redirect(url_for('dike.panel')) return render_template('dike/panel.html', form=form, mode='register', electoral=electoral) elif election.check_flag(ELECTION_VOTING): if form.validate_on_submit(): maintenance.end_voting(election) flash('Zakończono głosowanie.') return redirect(url_for('dike.reckoning')) if not verify_voters(election): flash('Illegal voter detected') log.debug(f"election.voters_boss.all() = {election.voters_boss.all()}") log.debug( f"election.voters_board.all() = {election.voters_board.all()}") log.debug( f"election.voters_covision.all() = {election.voters_covision.all()}" ) log.debug( f"election.did_vote({current_user}) = {election.did_vote(current_user)}" ) entitled = reckon_entitled_to_vote(election) entitled_checksum = compute_fellows_checksum(entitled) return render_template('dike/panel.html', form=form, mode='voting', count=election.count_votes(), entitled_checksum=entitled_checksum) else: return redirect(url_for('dike.reckoning'))