def test_election_public(self): """ Test the election_public property of Elections. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 1) self.assertEqual(election.election_public, True) election = nuancierlib.get_election(self.session, 2) self.assertEqual(election.election_public, False) election = nuancierlib.get_election(self.session, 3) self.assertEqual(election.election_public, False)
def admin_cache(election_id): ''' Regenerate the cache for this election. ''' election = nuancierlib.get_election(SESSION, election_id) next_url = None if 'next' in flask.request.args: next_url = flask.request.args['next'] if not next_url or next_url == flask.url_for( '.admin_cache', election_id=election_id): next_url = flask.url_for('.admin_index') if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') try: nuancierlib.generate_cache( session=SESSION, election=election, picture_folder=APP.config['PICTURE_FOLDER'], cache_folder=APP.config['CACHE_FOLDER'], size=APP.config['THUMB_SIZE']) flask.flash('Cache regenerated for election %s' % election.election_name) except nuancierlib.NuancierException as err: SESSION.rollback() LOG.debug('User: "******" could not generate cache for "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash(err.message, 'error') return flask.redirect(next_url)
def test_toggle_public(self): """ Test the toggle_public function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 1) self.assertEqual(True, election.election_public) nuancierlib.toggle_public(self.session, 1) election = nuancierlib.get_election(self.session, 1) self.assertEqual(False, election.election_public) nuancierlib.toggle_public(self.session, 1) election = nuancierlib.get_election(self.session, 1) self.assertEqual(True, election.election_public)
def admin_review(election_id): ''' Review a new election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if election.election_open: flask.flash( 'This election is already open to public votes and can no ' 'longer be changed', 'error') return flask.redirect(flask.url_for('admin_index')) if election.election_public: flask.flash( 'The results of this election are already public, this election' ' can no longer be changed', 'error') return flask.redirect(flask.url_for('admin_index')) candidates = nuancierlib.get_candidates(SESSION, election_id) return flask.render_template( 'admin_review.html', election=election, form=nuancier.forms.ConfirmationForm(), candidates=candidates, picture_folder=os.path.join( APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join( APP.config['CACHE_FOLDER'], election.election_folder))
def test_edit_election(self): """ Test the edit_election function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 2) new_election = nuancierlib.edit_election( self.session, election=election, election_name='elec name', election_folder='Test', election_year=2048, election_date_start=TODAY, election_date_end=TODAY + timedelta(days=2), submission_date_start=TODAY - timedelta(days=2), election_n_choice=42, election_badge_link='http://badges.fp.o/1234', user='******', ) self.assertEqual(new_election.election_name, 'elec name') self.assertEqual(new_election.election_folder, 'Test') self.assertEqual(new_election.election_year, 2048) self.assertEqual(new_election.election_date_start, TODAY) self.assertEqual( new_election.election_date_end, TODAY + timedelta(days=2)) self.assertEqual( new_election.submission_date_start, TODAY - timedelta(days=2)) self.assertEqual(new_election.election_n_choice, 42) self.assertEqual( new_election.election_badge_link, 'http://badges.fp.o/1234')
def admin_review_status(election_id, status): ''' Review a new election depending on the status of the candidates. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if election.election_open: flask.flash( 'This election is already open to public votes and can no ' 'longer be changed', 'error') if election.election_public: flask.flash( 'The results of this election are already public, this election' ' can no longer be changed', 'error') status = flask.request.args.get('status', status) if status == 'all': _status = None elif status in ['pending', 'denied']: _status = False else: _status = True candidates = nuancierlib.get_candidates(SESSION, election_id, approved=_status) if status == 'pending': candidates = [ candidate for candidate in candidates if candidate.approved_motif in [None, ''] ] elif status == 'denied': candidates = [ candidate for candidate in candidates if candidate.approved_motif not in [None, ''] ] template = 'admin_review.html' if election.election_public or election.election_open \ or not nuancier.is_nuancier_admin(flask.g.fas_user): template = 'admin_review_ro.html' return flask.render_template( template, election=election, form=nuancier.forms.ConfirmationForm(), candidates=candidates, picture_folder=os.path.join(APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join(APP.config['CACHE_FOLDER'], election.election_folder), status=status, )
def admin_review_status(election_id, status): ''' Review a new election depending on the status of the candidates. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if election.election_open: flask.flash( 'This election is already open to public votes and can no ' 'longer be changed', 'error') if election.election_public: flask.flash( 'The results of this election are already public, this election' ' can no longer be changed', 'error') status = flask.request.args.get('status', status) if status == 'all': _status = None elif status in ['pending', 'denied']: _status = False else: _status = True candidates = nuancierlib.get_candidates( SESSION, election_id, approved=_status ) if status == 'pending': candidates = [ candidate for candidate in candidates if candidate.approved_motif in [None, ''] ] elif status == 'denied': candidates = [ candidate for candidate in candidates if candidate.approved_motif not in [None, ''] ] template = 'admin_review.html' if election.election_public or election.election_open \ or not nuancier.is_nuancier_admin(flask.g.fas_user): template = 'admin_review_ro.html' return flask.render_template( template, election=election, form=nuancier.forms.ConfirmationForm(), candidates=candidates, picture_folder=os.path.join( APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join( APP.config['CACHE_FOLDER'], election.election_folder), status=status, )
def test_elections_repr(self): """ Test the __repr__ function of Elections. """ create_elections(self.session) create_candidates(self.session) election = nuancierlib.get_election(self.session, 1) self.assertEqual( election.__repr__(), "Elections(id:1, name:u'Wallpaper F19', year:2013)" )
def test_elections_api_repr(self): """ Test the api_repr function of Elections. """ create_elections(self.session) create_candidates(self.session) election = nuancierlib.get_election(self.session, 1) self.assertEqual( election.api_repr(1), {'name': 'Wallpaper F19', 'year': 2013} )
def admin_edit(election_id): ''' Edit an election. ''' if not nuancier.is_nuancier_admin(flask.g.fas_user): flask.flash('You are not an administrator of nuancier', 'error') return flask.redirect(flask.url_for('msg')) election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') form = nuancier.forms.AddElectionForm() if flask.request.method == 'GET': form = nuancier.forms.AddElectionForm(election=election) if form.validate_on_submit(): try: election = nuancierlib.edit_election( SESSION, election=election, election_name=form.election_name.data, election_folder=form.election_folder.data, election_year=form.election_year.data, election_date_start=form.election_date_start.data, election_date_end=form.election_date_end.data, submission_date_start=form.submission_date_start.data, submission_date_end=form.submission_date_end.data, election_n_choice=form.election_n_choice.data, user_n_candidates=form.user_n_candidates.data, election_badge_link=form.election_badge_link.data, user=flask.g.fas_user.username, ) SESSION.commit() flask.flash('Election updated') except SQLAlchemyError as err: SESSION.rollback() LOG.debug("User: %s could not edit election: %s ", flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash('Could not edit this election, is this name or ' 'folder already used?', 'error') return flask.render_template( 'admin_edit.html', election=election, form=form) return flask.redirect(flask.url_for('admin_index')) return flask.render_template( 'admin_edit.html', election=election, form=form)
def test_generate_cache_no_picture_folder(self): """ Test the generate_cache function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 2) self.assertRaises(nuancierlib.NuancierException, nuancierlib.generate_cache, session=self.session, election=election, picture_folder='none', cache_folder=CACHE_FOLDER, size=(128, 128))
def admin_edit(election_id): ''' Edit an election. ''' if not nuancier.is_nuancier_admin(flask.g.fas_user): flask.flash('You are not an administrator of nuancier', 'error') return flask.redirect(flask.url_for('msg')) election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') form = nuancier.forms.AddElectionForm() if flask.request.method == 'GET': form = nuancier.forms.AddElectionForm(election=election) if form.validate_on_submit(): try: election = nuancierlib.edit_election( SESSION, election=election, election_name=form.election_name.data, election_folder=form.election_folder.data, election_year=form.election_year.data, election_date_start=form.election_date_start.data, election_date_end=form.election_date_end.data, submission_date_start=form.submission_date_start.data, submission_date_end=form.submission_date_end.data, election_n_choice=form.election_n_choice.data, user_n_candidates=form.user_n_candidates.data, election_badge_link=form.election_badge_link.data, user=flask.g.fas_user.username, ) SESSION.commit() flask.flash('Election updated') except SQLAlchemyError as err: SESSION.rollback() LOG.debug("User: %s could not edit election: %s ", flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash( 'Could not edit this election, is this name or ' 'folder already used?', 'error') return flask.render_template('admin_edit.html', election=election, form=form) return flask.redirect(flask.url_for('admin_index')) return flask.render_template('admin_edit.html', election=election, form=form)
def test_edit_election(self): """ Test the edit_election function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 2) self.assertRaises( nuancierlib.NuancierException, nuancierlib.edit_election, session=self.session, election=election, election_name='elec name', election_folder='Test', election_year=2048, election_date_start=TODAY, election_date_end=TODAY + timedelta(days=2), submission_date_start=TODAY - timedelta(days=2), submission_date_end=TODAY - timedelta(days=1), election_n_choice=42, user_n_candidates=5, election_badge_link='http://badges.fp.o/1234', ) new_election = nuancierlib.edit_election( self.session, election=election, election_name='elec name', election_folder='Test', election_year=2048, election_date_start=TODAY, election_date_end=TODAY + timedelta(days=2), submission_date_start=TODAY - timedelta(days=2), submission_date_end=TODAY - timedelta(days=1), election_n_choice=42, user_n_candidates=5, election_badge_link='http://badges.fp.o/1234', user='******', ) self.assertEqual(new_election.election_name, 'elec name') self.assertEqual(new_election.election_folder, 'Test') self.assertEqual(new_election.election_year, 2048) self.assertEqual(new_election.election_date_start, TODAY) self.assertEqual(new_election.election_date_end, TODAY + timedelta(days=2)) self.assertEqual(new_election.submission_date_start, TODAY - timedelta(days=2)) self.assertEqual(new_election.submission_date_end, TODAY - timedelta(days=1)) self.assertEqual(new_election.election_n_choice, 42) self.assertEqual(new_election.election_badge_link, 'http://badges.fp.o/1234')
def test_elections_repr(self): """ Test the __repr__ function of Elections. """ create_elections(self.session) create_candidates(self.session) election = nuancierlib.get_election(self.session, 1) if six.PY2: self.assertEqual( election.__repr__(), "Elections(id:1, name:u'Wallpaper F19', year:2013)") else: self.assertEqual( election.__repr__(), "Elections(id:1, name:'Wallpaper F19', year:2013)")
def vote(election_id): ''' Give the possibility to the user to vote for an election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') candidates = nuancierlib.get_candidates(SESSION, election_id, approved=True) if not election.election_open: flask.flash('This election is not open', 'error') return flask.redirect(flask.url_for('index')) if flask.g.fas_user: username = flask.g.fas_user.username if not isinstance(username, six.binary_type): username = username.encode('utf-8') random.seed(int(hashlib.sha1(username).hexdigest(), 16) % 100000) random.shuffle(candidates) # How many votes the user made: votes = nuancierlib.get_votes_user(SESSION, election_id, flask.g.fas_user.username) if len(votes) >= election.election_n_choice: flask.flash( 'You have cast the maximal number of votes ' 'allowed for this election.', 'error') return flask.redirect( flask.url_for('election', election_id=election_id)) if len(votes) > 0: candidate_done = [cdt.candidate_id for cdt in votes] candidates = [ candidate for candidate in candidates if candidate.id not in candidate_done ] return flask.render_template( 'vote.html', election=election, form=nuancier.forms.ConfirmationForm(), candidates=candidates, n_votes_done=len(votes), picture_folder=os.path.join(APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join(APP.config['CACHE_FOLDER'], election.election_folder))
def test_generate_cache_no_picture_folder(self): """ Test the generate_cache function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 2) self.assertRaises( nuancierlib.NuancierException, nuancierlib.generate_cache, session=self.session, election=election, picture_folder='none', cache_folder=CACHE_FOLDER, size=(128, 128) )
def test_elections_api_repr(self): """ Test the api_repr function of Elections. """ create_elections(self.session) create_candidates(self.session) election = nuancierlib.get_election(self.session, 1) self.assertEqual( election.api_repr(1), { 'date_end': TODAY - timedelta(days=8), 'date_start': TODAY - timedelta(days=10), 'id': 1, 'name': u'Wallpaper F19', 'submission_date_start': TODAY - timedelta(days=15), 'submission_date_end': TODAY - timedelta(days=13), 'year': 2013 })
def test_generate_cache(self): """ Test the generate_cache function. """ create_elections(self.session) create_candidates(self.session) election = nuancierlib.get_election(self.session, 2) self.assertFalse(os.path.exists(CACHE_FOLDER)) nuancierlib.generate_cache(session=self.session, election=election, picture_folder=PICTURE_FOLDER, cache_folder=CACHE_FOLDER, size=(128, 128)) self.assertTrue(os.path.exists(CACHE_FOLDER))
def vote(election_id): ''' Give the possibility to the user to vote for an election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') candidates = nuancierlib.get_candidates( SESSION, election_id, approved=True) if not election.election_open: flask.flash('This election is not open', 'error') return flask.redirect(flask.url_for('index')) if flask.g.fas_user: random.seed( int( hashlib.sha1(flask.g.fas_user.username).hexdigest(), 16 ) % 100000) random.shuffle(candidates) # How many votes the user made: votes = nuancierlib.get_votes_user(SESSION, election_id, flask.g.fas_user.username) if len(votes) >= election.election_n_choice: flask.flash('You have cast the maximal number of votes ' 'allowed for this election.', 'error') return flask.redirect( flask.url_for('election', election_id=election_id)) if len(votes) > 0: candidate_done = [cdt.candidate_id for cdt in votes] candidates = [candidate for candidate in candidates if candidate.id not in candidate_done] return flask.render_template( 'vote.html', election=election, form=nuancier.forms.ConfirmationForm(), candidates=candidates, n_votes_done=len(votes), picture_folder=os.path.join( APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join( APP.config['CACHE_FOLDER'], election.election_folder) )
def stats(election_id): ''' Return some stats about this election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if not election.election_public: flask.flash('The results this election are not public yet', 'error') return flask.redirect(flask.url_for('results_list')) statsinfo = nuancierlib.get_stats(SESSION, election_id) return flask.render_template('stats.html', stats=statsinfo, election=election)
def test_elections_api_repr(self): """ Test the api_repr function of Elections. """ create_elections(self.session) create_candidates(self.session) election = nuancierlib.get_election(self.session, 1) self.assertEqual( election.api_repr(1), { 'date_end': TODAY - timedelta(days=8), 'date_start': TODAY - timedelta(days=10), 'id': 1, 'name': u'Wallpaper F19', 'submission_date_start': TODAY - timedelta(days=15), 'year': 2013 } )
def test_generate_cache_cache_folder_is_file(self): """ Test the generate_cache function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 2) stream = open(CACHE_FOLDER, 'w') stream.write('test') stream.close() self.assertRaises(nuancierlib.NuancierException, nuancierlib.generate_cache, session=self.session, election=election, picture_folder=PICTURE_FOLDER, cache_folder=CACHE_FOLDER, size=(128, 128))
def election(election_id): ''' Display the index page of the election will all the candidates submitted. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') # How many votes the user made: votes = [] can_vote = True if hasattr(flask.g, 'fas_user') and flask.g.fas_user: votes = nuancierlib.get_votes_user(SESSION, election_id, flask.g.fas_user.username) if election.election_open and len(votes) < election.election_n_choice: if len(votes) > 0: flask.flash('You have already voted, but you can still vote ' 'on more candidates.') return flask.redirect(flask.url_for('vote', election_id=election_id)) elif election.election_open and len(votes) >= election.election_n_choice: can_vote = False elif not election.election_public: flask.flash('This election is not open', 'error') return flask.redirect(flask.url_for('elections_list')) candidates = nuancierlib.get_candidates( SESSION, election_id, approved=True) if hasattr(flask.g, 'fas_user') and flask.g.fas_user: random.seed( int( hashlib.sha1(flask.g.fas_user.username).hexdigest(), 16 ) % 100000) random.shuffle(candidates) return flask.render_template( 'election.html', candidates=candidates, election=election, can_vote=can_vote, picture_folder=os.path.join( APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join( APP.config['CACHE_FOLDER'], election.election_folder) )
def election(election_id): ''' Display the index page of the election will all the candidates submitted. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') # How many votes the user made: votes = [] can_vote = True if hasattr(flask.g, 'fas_user') and flask.g.fas_user: votes = nuancierlib.get_votes_user(SESSION, election_id, flask.g.fas_user.username) if election.election_open and len(votes) < election.election_n_choice: if len(votes) > 0: flask.flash('You have already voted, but you can still vote ' 'on more candidates.') return flask.redirect(flask.url_for('vote', election_id=election_id)) elif election.election_open and len(votes) >= election.election_n_choice: can_vote = False elif not election.election_public: flask.flash('This election is not open', 'error') return flask.redirect(flask.url_for('elections_list')) candidates = nuancierlib.get_candidates(SESSION, election_id, approved=True) if hasattr(flask.g, 'fas_user') and flask.g.fas_user: username = flask.g.fas_user.username if not isinstance(username, six.binary_type): username = username.encode('utf-8') random.seed(int(hashlib.sha1(username).hexdigest(), 16) % 100000) random.shuffle(candidates) return flask.render_template( 'election.html', candidates=candidates, election=election, can_vote=can_vote, picture_folder=os.path.join(APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join(APP.config['CACHE_FOLDER'], election.election_folder))
def test_generate_cache(self): """ Test the generate_cache function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 2) self.assertFalse(os.path.exists(CACHE_FOLDER)) nuancierlib.generate_cache( session=self.session, election=election, picture_folder=PICTURE_FOLDER, cache_folder=CACHE_FOLDER, size=(128, 128) ) self.assertTrue(os.path.exists(CACHE_FOLDER))
def stats(election_id): ''' Return some stats about this election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if not election.election_public: flask.flash('The results this election are not public yet', 'error') return flask.redirect(flask.url_for('results_list')) statsinfo = nuancierlib.get_stats(SESSION, election_id) return flask.render_template( 'stats.html', stats=statsinfo, election=election)
def test_election_public_today(self): """ Test the election_public property for today. """ today = datetime.utcnow().date() election = model.Elections( election_name='Wallpaper F19', election_folder='F19', election_year='2013', election_n_choice=2, submission_date_start=today - timedelta(days=4), election_date_start=today - timedelta(days=2), election_date_end=today, ) self.session.add(election) self.session.commit() election = nuancierlib.get_election(self.session, 1) self.assertEqual(election.submission_open, False) self.assertEqual(election.election_open, False) self.assertEqual(election.election_public, True)
def test_generate_cache_cache_folder_is_file(self): """ Test the generate_cache function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 2) stream = open(CACHE_FOLDER, 'w') stream.write('test') stream.close() self.assertRaises( nuancierlib.NuancierException, nuancierlib.generate_cache, session=self.session, election=election, picture_folder=PICTURE_FOLDER, cache_folder=CACHE_FOLDER, size=(128, 128) )
def test_election_public_today(self): """ Test the election_public property for today. """ today = datetime.utcnow().date() election = model.Elections( election_name='Wallpaper F19', election_folder='F19', election_year='2013', election_n_choice=2, submission_date_start=today - timedelta(days=4), submission_date_end=today - timedelta(days=3), election_date_start=today - timedelta(days=2), election_date_end=today, ) self.session.add(election) self.session.commit() election = nuancierlib.get_election(self.session, 1) self.assertEqual(election.submission_open, False) self.assertEqual(election.election_open, False) self.assertEqual(election.election_public, True)
def admin_review(election_id): ''' Review a new election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if election.election_open: flask.flash( 'This election is already open to public votes and can no ' 'longer be changed', 'error') if election.election_public: flask.flash( 'The results of this election are already public, this election' ' can no longer be changed', 'error') status = flask.request.args.get('status', 'all') if status == 'all': status = None candidates = nuancierlib.get_candidates( SESSION, election_id, approved=status ) template = 'admin_review.html' if election.election_public or election.election_open \ or not nuancier.is_nuancier_admin(flask.g.fas_user): template = 'admin_review_ro.html' return flask.render_template( template, election=election, form=nuancier.forms.ConfirmationForm(), candidates=candidates, picture_folder=os.path.join( APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join( APP.config['CACHE_FOLDER'], election.election_folder))
def admin_cache(election_id): ''' Regenerate the cache for this election. ''' election = nuancierlib.get_election(SESSION, election_id) next_url = None if 'next' in flask.request.args: next_url = flask.request.args['next'] if not next_url or next_url == flask.url_for('.admin_cache', election_id=election_id): next_url = flask.url_for('.admin_index') if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') try: nuancierlib.generate_cache(session=SESSION, election=election, picture_folder=APP.config['PICTURE_FOLDER'], cache_folder=APP.config['CACHE_FOLDER'], size=APP.config['THUMB_SIZE']) flask.flash('Cache regenerated for election %s' % election.election_name) except nuancierlib.NuancierMultiExceptions as multierr: # pragma: no cover SESSION.rollback() LOG.debug('User: "******" could not generate cache for "%s"', flask.g.fas_user.username, election_id) LOG.exception(multierr.messages) for msg in multierr.messages: flask.flash(msg, 'error') except nuancierlib.NuancierException as err: SESSION.rollback() LOG.debug('User: "******" could not generate cache for "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash(str(err), 'error') return flask.redirect(next_url)
def admin_review(election_id, status='all'): ''' Review a new election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if election.election_open: flask.flash( 'This election is already open to public votes and can no ' 'longer be changed', 'error') if election.election_public: flask.flash( 'The results of this election are already public, this election' ' can no longer be changed', 'error') status = flask.request.args.get('status', status) return flask.redirect(flask.url_for( 'admin_review_status', election_id=election_id, status=status))
def results(election_id): ''' Displays the results of an election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if not election.election_public: flask.flash('The results this election are not public yet', 'error') return flask.redirect(flask.url_for('results_list')) election_results = nuancierlib.get_results(SESSION, election_id) return flask.render_template( 'results.html', election=election, results=election_results, picture_folder=os.path.join(APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join(APP.config['CACHE_FOLDER'], election.election_folder))
def results(election_id): ''' Displays the results of an election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if not election.election_public: flask.flash('The results this election are not public yet', 'error') return flask.redirect(flask.url_for('results_list')) election_results = nuancierlib.get_results(SESSION, election_id) return flask.render_template( 'results.html', election=election, results=election_results, picture_folder=os.path.join( APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join( APP.config['CACHE_FOLDER'], election.election_folder))
def test_generate_cache_wrong_info_file(self): """ Test the generate_cache function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 3) info_file = os.path.join(PICTURE_FOLDER, election.election_folder, 'infos.txt') stream = open(info_file, 'w') stream.write('test') stream.close() self.assertRaises( nuancierlib.NuancierException, nuancierlib.generate_cache, session=self.session, election=election, picture_folder=PICTURE_FOLDER, cache_folder=CACHE_FOLDER, size=(128, 128) ) os.unlink(info_file)
def admin_review(election_id, status='all'): ''' Review a new election. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if election.election_open: flask.flash( 'This election is already open to public votes and can no ' 'longer be changed', 'error') if election.election_public: flask.flash( 'The results of this election are already public, this election' ' can no longer be changed', 'error') status = flask.request.args.get('status', status) return flask.redirect( flask.url_for('admin_review_status', election_id=election_id, status=status))
def process_vote(election_id): ''' Actually register the vote, after checking if the user is actually allowed to vote. ''' form = nuancier.forms.ConfirmationForm() if not form.validate_on_submit(): flask.flash('Wrong input submitted', 'error') return flask.render_template('msg.html') election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if not election.election_open: flask.flash('This election is not open', 'error') return flask.render_template('msg.html') candidates = nuancierlib.get_candidates(SESSION, election_id, approved=True) candidate_ids = set([candidate.id for candidate in candidates]) entries = set( [int(entry) for entry in flask.request.form.getlist('selection')]) # If not enough candidates selected if not entries: flask.flash('You did not select any candidate to vote for.', 'error') return flask.redirect(flask.url_for('vote', election_id=election_id)) # If vote on candidates from other elections if not set(entries).issubset(candidate_ids): flask.flash( 'The selection you have made contains element which are ' 'not part of this election, please be careful.', 'error') return flask.redirect(flask.url_for('vote', election_id=election_id)) # How many votes the user made: votes = nuancierlib.get_votes_user(SESSION, election_id, flask.g.fas_user.username) # Too many votes -> redirect if len(votes) >= election.election_n_choice: flask.flash( 'You have cast the maximal number of votes ' 'allowed for this election.', 'error') return flask.redirect( flask.url_for('election', election_id=election_id)) # Selected more candidates than allowed -> redirect if len(votes) + len(entries) > election.election_n_choice: flask.flash( 'You selected %s wallpapers while you are only allowed ' 'to select %s' % (len(entries), (election.election_n_choice - len(votes))), 'error') return flask.render_template( 'vote.html', form=nuancier.forms.ConfirmationForm(), election=election, candidates=[ nuancierlib.get_candidate(SESSION, candidate_id) for candidate_id in entries ], n_votes_done=len(votes), picture_folder=os.path.join(APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join(APP.config['CACHE_FOLDER'], election.election_folder)) # Allowed to vote, selection sufficient, choice confirmed: process for selection in entries: value = 1 if nuancier.has_weigthed_vote(flask.g.fas_user): value = 2 nuancierlib.add_vote(SESSION, selection, flask.g.fas_user.username, value=value) try: SESSION.commit() except SQLAlchemyError as err: # pragma: no cover SESSION.rollback() LOG.debug( 'ERROR: could not process the vote - user: "******" ' 'election: "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash( 'An error occured while processing your votes, please ' 'report this to your lovely admin or see logs for ' 'more details', 'error') flask.flash('Your vote has been recorded, thank you for voting on ' '%s %s' % (election.election_name, election.election_year)) if election.election_badge_link: flask.flash('Do not forget to <a href="%s" target="_blank">claim your ' 'badge!</a>' % election.election_badge_link) return flask.redirect(flask.url_for('elections_list'))
def admin_process_review(election_id): ''' Process the reviewing of a new election. ''' if not nuancier.is_nuancier_admin(flask.g.fas_user): flask.flash('You are not an administrator of nuancier', 'error') return flask.redirect(flask.url_for('msg')) status = flask.request.args.get('status', None) endpoint = 'admin_review' if status: endpoint = 'admin_review_status' election = nuancierlib.get_election(SESSION, election_id) form = nuancier.forms.ConfirmationForm() if not form.validate_on_submit(): flask.flash('Wrong input submitted', 'error') return flask.render_template('msg.html') if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if election.election_open: flask.flash( 'This election is already open to public votes and can no ' 'longer be changed', 'error') return flask.redirect(flask.url_for('results_list')) if election.election_public: flask.flash( 'The results of this election are already public, this election' ' can no longer be changed', 'error') return flask.redirect(flask.url_for('results_list')) candidates = nuancierlib.get_candidates(SESSION, election_id) candidates_id = [str(candidate.id) for candidate in candidates] candidates_selected = flask.request.form.getlist('candidates_id') motifs = flask.request.form.getlist('motifs') action = flask.request.form.get('action') if action: action = action.strip() if action not in ['Approved', 'Denied']: flask.flash('Only the actions "Approved" or "Denied" are accepted', 'error') return flask.redirect( flask.url_for(endpoint, election_id=election_id, status=status)) selections = [] for cand in candidates_id: if cand not in candidates_selected: selections.append(None) else: selections.append(cand) if action == 'Denied': req_motif = False if not motifs: req_motif = True for cnt in range(len(motifs)): motif = motifs[cnt] if selections[cnt] and not motif.strip(): req_motif = True break if req_motif: flask.flash('You must provide a reason to deny a candidate', 'error') return flask.redirect( flask.url_for(endpoint, election_id=election_id, status=status)) cnt = 0 for candidate in candidates_selected: if candidate not in candidates_id: flask.flash( 'One of the candidate submitted was not candidate in this ' 'election', 'error') return flask.redirect( flask.url_for(endpoint, election_id=election_id, status=status)) msgs = [] for candidate in selections: if candidate: candidate = nuancierlib.get_candidate(SESSION, candidate) motif = None if len(motifs) > cnt: motif = motifs[cnt].strip() if action == 'Approved': candidate.approved = True candidate.approved_motif = motif else: candidate.approved = False candidate.approved_motif = motif if APP.config.get('NUANCIER_EMAIL_NOTIFICATIONS', False): # pragma: no cover nuancierlib.notifications.email_publish( to_email=candidate.submitter_email, img_title=candidate.candidate_name, motif=motif) else: LOG.warning( 'Should have sent an email to "%s" about "%s" that has' ' been rejected because of "%s"', candidate.submitter_email, candidate.candidate_name, motif) SESSION.add(candidate) msgs.append({ 'topic': 'candidate.%s' % (action.lower()), 'msg': dict( agent=flask.g.fas_user.username, election=election.api_repr(version=1), candidate=candidate.api_repr(version=1), ) }) cnt += 1 try: SESSION.commit() except SQLAlchemyError as err: # pragma: no cover SESSION.rollback() LOG.debug( 'User: "******" could not approve/deny candidate(s) for ' 'election "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash('Could not approve/deny candidate', 'error') flask.flash('Candidate(s) updated') for msg in msgs: nuancierlib.notifications.publish( topic=msg['topic'], msg=msg['msg'], ) return flask.redirect( flask.url_for(endpoint, election_id=election_id, status=status))
def contribute(election_id): ''' Display the index page for interested contributor. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') elif not election.submission_open: flask.flash('This election is not open for submission', 'error') return flask.redirect(flask.url_for('elections_list')) candidates = nuancier.lib.model.Candidates.get_by_submitter( SESSION, flask.g.fas_user.username, election_id) if election.user_n_candidates and \ len(candidates) >= election.user_n_candidates: flask.flash( 'You have uploaded the maximum number of candidates (%s) you ' 'can upload for this election' % election.user_n_candidates, 'error') return flask.redirect(flask.url_for('elections_list')) form = nuancier.forms.AddCandidateForm() if form.validate_on_submit(): candidate_file = flask.request.files['candidate_file'] try: validate_input_file(candidate_file) except nuancierlib.NuancierException as err: LOG.debug('ERROR: Uploaded file is invalid - user: "******" ' 'election: "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash(err.message, 'error') return flask.render_template( 'contribute.html', election=election, form=form) filename = secure_filename('%s-%s' % (flask.g.fas_user.username, candidate_file.filename)) # Only save the file once everything has been safely saved in the DB upload_folder = os.path.join( APP.config['PICTURE_FOLDER'], election.election_folder) if not os.path.exists(upload_folder): # pragma: no cover try: os.mkdir(upload_folder) except OSError, err: LOG.debug('ERROR: cannot add candidate file') LOG.exception(err) flask.flash( 'An error occured while writing the file, please ' 'contact an administrator', 'error') return flask.render_template( 'contribute.html', election=election, form=form) # Save candidate to the database try: nuancierlib.add_candidate( SESSION, candidate_file=filename, candidate_name=form.candidate_name.data, candidate_author=form.candidate_author.data, candidate_original_url=form.candidate_original_url.data, candidate_license=form.candidate_license.data, candidate_submitter=flask.g.fas_user.username, submitter_email=flask.g.fas_user.email, election_id=election.id, user=flask.g.fas_user.username, ) except nuancierlib.NuancierException as err: flask.flash(err.message, 'error') return flask.render_template( 'contribute.html', election=election, form=form) # The PIL module has already read the stream so we need to back up candidate_file.seek(0) candidate_file.save( os.path.join(upload_folder, filename)) try: SESSION.commit() except SQLAlchemyError as err: # pragma: no cover SESSION.rollback() # Remove file from the system if the db commit failed os.unlink(os.path.join(upload_folder, filename)) LOG.debug('ERROR: cannot add candidate - user: "******" ' 'election: "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash( 'Someone has already upload a file with the same file name' ' for this election', 'error') return flask.render_template( 'contribute.html', election=election, form=form) flask.flash('Thanks for your submission') return flask.redirect(flask.url_for('index'))
def test_get_election(self): """ Test the get_election function. """ create_elections(self.session) election = nuancierlib.get_election(self.session, 3) self.assertEqual('Wallpaper F21', election.election_name)
def process_vote(election_id): ''' Actually register the vote, after checking if the user is actually allowed to vote. ''' form = nuancier.forms.ConfirmationForm() if not form.validate_on_submit(): flask.flash('Wrong input submitted', 'error') return flask.render_template('msg.html') election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if not election.election_open: flask.flash('This election is not open', 'error') return flask.render_template('msg.html') candidates = nuancierlib.get_candidates( SESSION, election_id, approved=True) candidate_ids = set([candidate.id for candidate in candidates]) entries = set([int(entry) for entry in flask.request.form.getlist('selection')]) # If not enough candidates selected if not entries: flask.flash('You did not select any candidate to vote for.', 'error') return flask.redirect(flask.url_for('vote', election_id=election_id)) # If vote on candidates from other elections if not set(entries).issubset(candidate_ids): flask.flash('The selection you have made contains element which are ' 'not part of this election, please be careful.', 'error') return flask.redirect(flask.url_for('vote', election_id=election_id)) # How many votes the user made: votes = nuancierlib.get_votes_user(SESSION, election_id, flask.g.fas_user.username) # Too many votes -> redirect if len(votes) >= election.election_n_choice: flask.flash('You have cast the maximal number of votes ' 'allowed for this election.', 'error') return flask.redirect( flask.url_for('election', election_id=election_id)) # Selected more candidates than allowed -> redirect if len(votes) + len(entries) > election.election_n_choice: flask.flash('You selected %s wallpapers while you are only allowed ' 'to select %s' % ( len(entries), (election.election_n_choice - len(votes))), 'error') return flask.render_template( 'vote.html', form=nuancier.forms.ConfirmationForm(), election=election, candidates=[nuancierlib.get_candidate(SESSION, candidate_id) for candidate_id in entries], n_votes_done=len(votes), picture_folder=os.path.join( APP.config['PICTURE_FOLDER'], election.election_folder), cache_folder=os.path.join( APP.config['CACHE_FOLDER'], election.election_folder) ) # Allowed to vote, selection sufficient, choice confirmed: process for selection in entries: value = 1 if nuancier.has_weigthed_vote(flask.g.fas_user): value = 2 nuancierlib.add_vote( SESSION, selection, flask.g.fas_user.username, value=value) try: SESSION.commit() except SQLAlchemyError as err: # pragma: no cover SESSION.rollback() LOG.debug('ERROR: could not process the vote - user: "******" ' 'election: "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash('An error occured while processing your votes, please ' 'report this to your lovely admin or see logs for ' 'more details', 'error') flask.flash('Your vote has been recorded, thank you for voting on ' '%s %s' % (election.election_name, election.election_year)) if election.election_badge_link: flask.flash('Do not forget to <a href="%s" target="_blank">claim your ' 'badge!</a>' % election.election_badge_link) return flask.redirect(flask.url_for('elections_list'))
def admin_process_review(election_id): ''' Process the reviewing of a new election. ''' if not nuancier.is_nuancier_admin(flask.g.fas_user): flask.flash('You are not an administrator of nuancier', 'error') return flask.redirect(flask.url_for('msg')) status = flask.request.args.get('status', None) endpoint = 'admin_review' if status: endpoint = 'admin_review_status' election = nuancierlib.get_election(SESSION, election_id) form = nuancier.forms.ConfirmationForm() if not form.validate_on_submit(): flask.flash('Wrong input submitted', 'error') return flask.render_template('msg.html') if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') if election.election_open: flask.flash( 'This election is already open to public votes and can no ' 'longer be changed', 'error') return flask.redirect(flask.url_for('results_list')) if election.election_public: flask.flash( 'The results of this election are already public, this election' ' can no longer be changed', 'error') return flask.redirect(flask.url_for('results_list')) candidates = nuancierlib.get_candidates(SESSION, election_id) candidates_id = [str(candidate.id) for candidate in candidates] candidates_selected = flask.request.form.getlist('candidates_id') motifs = flask.request.form.getlist('motifs') action = flask.request.form.get('action') if action: action = action.strip() if action not in ['Approved', 'Denied']: flask.flash( 'Only the actions "Approved" or "Denied" are accepted', 'error') return flask.redirect(flask.url_for( endpoint, election_id=election_id, status=status)) selections = [] for cand in candidates_id: if cand not in candidates_selected: selections.append(None) else: selections.append(cand) if action == 'Denied': req_motif = False if not motifs: req_motif = True for cnt in range(len(motifs)): motif = motifs[cnt] if selections[cnt] and not motif.strip(): req_motif = True break if req_motif: flask.flash( 'You must provide a motif to deny a candidate', 'error') return flask.redirect(flask.url_for( endpoint, election_id=election_id, status=status)) cnt = 0 for candidate in candidates_selected: if candidate not in candidates_id: flask.flash( 'One of the candidate submitted was not candidate in this ' 'election', 'error') return flask.redirect(flask.url_for( endpoint, election_id=election_id, status=status)) msgs = [] for candidate in selections: if candidate: candidate = nuancierlib.get_candidate(SESSION, candidate) motif = None if len(motifs) > cnt: motif = motifs[cnt].strip() if action == 'Approved': candidate.approved = True candidate.approved_motif = motif else: candidate.approved = False candidate.approved_motif = motif if APP.config.get( 'NUANCIER_EMAIL_NOTIFICATIONS', False): # pragma: no cover nuancierlib.notifications.email_publish( to_email=candidate.submitter_email, img_title=candidate.candidate_name, motif=motif) else: LOG.warning( 'Should have sent an email to "%s" about "%s" that has' ' been rejected because of "%s"', candidate.submitter_email, candidate.candidate_name, motif) SESSION.add(candidate) msgs.append({ 'topic': 'candidate.%s' % (action.lower()), 'msg': dict( agent=flask.g.fas_user.username, election=election.api_repr(version=1), candidate=candidate.api_repr(version=1), ) }) cnt += 1 try: SESSION.commit() except SQLAlchemyError as err: # pragma: no cover SESSION.rollback() LOG.debug('User: "******" could not approve/deny candidate(s) for ' 'election "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash('Could not approve/deny candidate', 'error') flask.flash('Candidate(s) updated') for msg in msgs: nuancierlib.notifications.publish( topic=msg['topic'], msg=msg['msg'], ) return flask.redirect(flask.url_for( endpoint, election_id=election_id, status=status))
def contribute(election_id): ''' Display the index page for interested contributor. ''' election = nuancierlib.get_election(SESSION, election_id) if not election: flask.flash('No election found', 'error') return flask.render_template('msg.html') elif not election.submission_open: flask.flash('This election is not open for submission', 'error') return flask.redirect(flask.url_for('elections_list')) candidates = nuancier.lib.model.Candidates.get_by_submitter( SESSION, flask.g.fas_user.username, election_id) if election.user_n_candidates and \ len(candidates) >= election.user_n_candidates: flask.flash( 'You have uploaded the maximum number of candidates (%s) you ' 'can upload for this election' % election.user_n_candidates, 'error') return flask.redirect(flask.url_for('elections_list')) form = nuancier.forms.AddCandidateForm() if form.validate_on_submit(): candidate_file = flask.request.files['candidate_file'] try: validate_input_file(candidate_file) except nuancierlib.NuancierException as err: LOG.debug( 'ERROR: Uploaded file is invalid - user: "******" ' 'election: "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash('%s' % err, 'error') return flask.render_template('contribute.html', election=election, form=form) filename = secure_filename( '%s-%s' % (flask.g.fas_user.username, candidate_file.filename)) # Only save the file once everything has been safely saved in the DB upload_folder = os.path.join(APP.config['PICTURE_FOLDER'], election.election_folder) if not os.path.exists(upload_folder): # pragma: no cover try: os.mkdir(upload_folder) except OSError as err: LOG.debug('ERROR: cannot add candidate file') LOG.exception(err) flask.flash( 'An error occured while writing the file, please ' 'contact an administrator', 'error') return flask.render_template('contribute.html', election=election, form=form) # Save candidate to the database try: nuancierlib.add_candidate( SESSION, candidate_file=filename, candidate_name=form.candidate_name.data, candidate_author=form.candidate_author.data, candidate_original_url=form.candidate_original_url.data, candidate_license=form.candidate_license.data, candidate_submitter=flask.g.fas_user.username, submitter_email=flask.g.fas_user.email, election_id=election.id, user=flask.g.fas_user.username, ) except nuancierlib.NuancierException as err: flask.flash('%s' % err, 'error') return flask.render_template('contribute.html', election=election, form=form) # The PIL module has already read the stream so we need to back up candidate_file.seek(0) candidate_file.save(os.path.join(upload_folder, filename)) try: SESSION.commit() except SQLAlchemyError as err: # pragma: no cover SESSION.rollback() # Remove file from the system if the db commit failed os.unlink(os.path.join(upload_folder, filename)) LOG.debug( 'ERROR: cannot add candidate - user: "******" ' 'election: "%s"', flask.g.fas_user.username, election_id) LOG.exception(err) flask.flash( 'Someone has already upload a file with the same file name' ' for this election', 'error') return flask.render_template('contribute.html', election=election, form=form) flask.flash('Thanks for your submission') return flask.redirect(flask.url_for('index')) elif flask.request.method == 'GET': form.candidate_author.data = flask.g.fas_user.username return flask.render_template('contribute.html', election=election, form=form)
# -*- coding: utf-8 -*- __requires__ = ['SQLAlchemy >= 0.7', 'jinja2 >= 2.4'] import pkg_resources import os os.environ['NUANCIER_CONFIG'] = '/etc/nuancier/nuancier.cfg' from nuancier import APP, SESSION, lib election = lib.get_election(SESSION, 1) lib.generate_cache( SESSION, election, APP.config['PICTURE_FOLDER'], APP.config['CACHE_FOLDER'], APP.config['THUMB_SIZE'], )