Ejemplo n.º 1
0
def results_template_xls(request):
    """Downloads an Excel sheet template for paper ballot results submission.

    The Excel template contains the names and numbers of the candidates
    associated with the school's voting district.
    """
    rows = [
        (u'Numero', u'Nimi', u'Äänimäärä'),
    ]

    user = authenticated_user(request)
    if user is None:
        raise Forbidden

    session = DBSession()

    # Add all the candidates and their numbers into the CSV template.
    candidates = session.query(Candidate)\
                 .filter(Candidate.district == user.school.district)\
                 .order_by(Candidate.number)
    rows.extend((c.number, c.fullname(), u'') for c in candidates)

    request.add_response_callback(disable_caching_explorer)
    return xls_response(rows,
                        filename='nuorisovaalit2011-uurnatulokset.xls',
                        num_formats=('@', '@', '@'),
                        col_widths=(None, 8000, 3000))
    def test_authenticated_user__authenticated(self):
        from nuorisovaalitadmin.models import User
        from nuorisovaalitadmin.views.login import authenticated_user

        self.config.testing_securitypolicy(userid=u'dokai')
        session = DBSession()

        # We're cheating here by setting the foreign key without having a
        # corresponding object. We get away with it because SQLite doesn't
        # enforce the foreign key constraint.
        user = User(u'dokai', u'secret', u'Kai', '*****@*****.**', school_or_id=1)
        session.add(user)

        request = testing.DummyRequest()
        self.assertEquals(user, authenticated_user(request))
Ejemplo n.º 3
0
def results(request):
    """Renders a page for downloading the school specific combined results of
    the election (electronic and paper ballot).
    """
    user = authenticated_user(request)
    if user is None:
        raise Forbidden
    options = {
        'title': u'Tulokset',
        'district': user.school.district.name,
        'results_template_xls': route_url('results_template_xls', request),
        'results_xls': route_url('results_xls', request),
    }

    request.add_response_callback(disable_caching)
    return options
Ejemplo n.º 4
0
def voter_list(request):
    """Renders a page for downloading the school specific list of voters.
    """
    user = authenticated_user(request)
    if user is None:
        raise Forbidden

    options = {
        'title': u'Lista äänestäneistä',
        'school': user.school.name,
        'district': user.school.district.name,
        'voter_list_xls': route_url('voter_list_xls', request),
    }

    request.add_response_callback(disable_caching)
    return options
Ejemplo n.º 5
0
def voter_list_xls(request):
    """Downloads the school specific list of voters as an Excel sheet.

    The list contains all voters registered for the school and voters who have
    already cast their vote will have a timestamp noting the time the vote
    was cast. The timestamp (or lack thereof) can be used to either grant or
    deny access to the paper ballot.

    The Excel sheet contains the following information about each voter:

        * Last name
        * First name
        * Date of birth (dd.mm.yyyy)
        * Voting timestamp
    """
    user = authenticated_user(request)
    if user is None:
        raise Forbidden

    rows = [
        (u'Sukunimi', u'Etunimi', u'Syntymäaika', u'Äänestänyt'),
    ]
    session = DBSession()

    # Query all the voters and the voting timestamp if they have voted.
    voters = session.query(Voter.lastname, Voter.firstname, Voter.dob, VotingLog.timestamp.label('timestamp'))\
             .outerjoin(VotingLog)\
             .filter(Voter.school == user.school)\
             .order_by(Voter.lastname, Voter.firstname)

    for voter in voters:
        timestamp = ''
        if voter.timestamp is not None:
            timestamp = datetime.fromtimestamp(voter.timestamp).strftime('%d.%m.%Y %H:%M:%S')
        rows.append((voter.lastname,
                     voter.firstname,
                     unicode(voter.dob.strftime('%d.%m.%Y')),
                     unicode(timestamp)))

    request.add_response_callback(disable_caching_explorer)
    return xls_response(rows, filename='nuorisovaalit2011-aanestajalista.xls',
                        num_formats=('@', '@', '@', '@'),
                        col_widths=(7000, 7000, 3500, 7000))
Ejemplo n.º 6
0
def results_xls(request):
    """Downloads the district specific combined results as an Excel sheet.
    """
    user = authenticated_user(request)
    if user is None:
        raise Forbidden

    district = user.school.district

    title = u'{0} ({1} kansanedustajapaikka'.format(district.name, district.quota)
    title += ')' if district.quota == 1 else 'a)'
    rows = [
        (title, u'', u'', u'', u''),
        (u'', u'', u'', u'', u''),
        (u'Valitut ehdokkaat', u'', u'', u'', u''),
        (u'Numero', u'Nimi', u'Puolue', u'Äänimäärä', u'Vertailuluku'),
    ]

    for i, record in enumerate(dhont_selection(user.school.district)):

        # Add a separator between the selected and other candidates.
        if i == district.quota:
            rows.append((u'', u'', u'', u'', u''))
            rows.append((u'Valitsematta jääneet ehdokkaat', u'', u'', u'', u''))
            rows.append((u'Numero', u'Nimi', u'Puolue', u'Äänimäärä', u'Vertailuluku'))

        candidate = record['candidate']
        rows.append((candidate.number,
                     candidate.fullname(),
                     candidate.party.name,
                     record['absolute_votes'],
                     record['proportional_votes']))

    request.add_response_callback(disable_caching_explorer)
    return xls_response(rows,
                        filename='nuorisovaalit2011-tulokset.xls',
                        num_formats=(None, '@', '@', None, None),
                        col_widths=(None, 8000, 14000, 3000, 3000))
Ejemplo n.º 7
0
def renderer_globals_factory(system):
    """Returns a dictionary of mappings that are available as global
    parameters in each renderer.
    """
    request = system.get('request')
    user = authenticated_user(request)

    userid = user.username if user is not None else None
    school = user.school.name if user is not None else None

    if request.path == '/':
        section = 'frontpage'
    else:
        section = '-'.join(request.path.split('/')).strip('-')

    return {
        'flash_messages': request.session.pop_flash(),
        'main': get_renderer('templates/master.pt').implementation(),
        'top_navigation': top_navigation(request),
        'logged_user': userid,
        'logged_school': school,
        'logout_url': route_url('logout', request),
        'section': 'section-' + section,
    }
    def test_authenticated_user__authenticated_model_missing(self):
        from nuorisovaalitadmin.views.login import authenticated_user

        self.config.testing_securitypolicy(userid=u'dokai')
        request = testing.DummyRequest()
        self.failUnless(authenticated_user(request) is None)
    def test_authenticated_user__anonymous(self):
        from nuorisovaalitadmin.views.login import authenticated_user

        request = testing.DummyRequest()
        self.failUnless(authenticated_user(request) is None)
Ejemplo n.º 10
0
    def submit_results(self):
        """Handles the form submission and renders the currently persisted
        information.
        """
        user = authenticated_user(self.request)
        log = logging.getLogger('nuorisovaalitadmin')

        if user is None:
            raise Forbidden
        self.user = user

        session = DBSession()
        options = {
            'title': u'Tulostietojen lähetys',
            'errors': None,
            'errors_left': 0,
            'file_type_error': None,
        }

        if 'xlsfile' in self.request.POST and hasattr(self.request.POST['xlsfile'], 'file'):
            if self.request.POST['csrf_token'] != self.request.session.get_csrf_token():
                log.warn('CSRF attempt at: {0}.'.format(self.request.url))
                raise Forbidden

            xls = self.request.POST['xlsfile']
            errors = []

            try:
                try:
                    # Attempt to parse it as an Excel 97/XP/2000 or older first.
                    submission = self.parse_xls(xls.file)
                    log.info('Validating Excel submission from "{0}".'.format(user.username))
                except xlrd.XLRDError:
                    # Attempt to parse it as an Excel 2010 file.
                    xls.file.seek(0)
                    submission = self.parse_xlsx(xls.file)
                    log.info('Validating Excel 2010 (xlsx) submission from "{0}".'.format(user.username))

                errors = self.validate(submission)
            except:
                log.warn('User "{0}" attempted to submit a non compliant file.'.format(user.username))
                options['file_type_error'] = True

            if options['file_type_error'] is None and len(errors) == 0:
                # Clear submissions for the user's school.
                session.query(CSVSubmission)\
                    .filter_by(kind=CSVSubmission.RESULT, school_id=user.school.id)\
                    .delete()
                # Add the latest submission.
                session.add(CSVSubmission(self.normalize(submission), user.school, CSVSubmission.RESULT))
                self.request.session.flash(u'Tiedosto tallennettu onnistuneesti.')

                # Redirect to avoid form resubmission on page reload.
                return HTTPFound(location=route_url('submit_results', self.request))
            else:
                log.warn('Validation failed for results submission made by "{0}"'.format(user.username))
                self.request.session.flash(u'Lähetetyssä tiedostossa oli virheitä. '
                                           u'Korjaa virheet ja lähetä uudelleen.')
                errors_to_show = 15
                options['errors'] = errors[:errors_to_show]
                if len(errors) > errors_to_show:
                    options['errors_left'] = len(errors) - errors_to_show

        options.update({
            'csrf_token': self.request.session.get_csrf_token(),
            'submission': None,
            'template_url': route_url('results_template_xls', self.request),
            'action_url': route_url('submit_results', self.request),
        })

        submission = session.query(CSVSubmission)\
                     .filter_by(kind=CSVSubmission.RESULT, school_id=user.school.id)\
                     .first()
        if submission is not None:
            options['submission'] = {
                'timestamp': submission.timestamp.strftime('%d.%m.%Y %H:%M'),
                'data': submission.csv,
            }

        self.request.add_response_callback(disable_caching)
        return options
Ejemplo n.º 11
0
    def submit_voters(self):
        """Handles the form submission and renders the currently persisted
        information.
        """
        user = authenticated_user(self.request)
        log = logging.getLogger('nuorisovaalitadmin')
        if user is None:
            log.warn('Unauthenticated attempt to submit voters.')
            raise Forbidden

        session = DBSession()
        options = {
            'errors': None,
            'errors_left': 0,
            'file_type_error': None,
        }

        if 'csvfile' in self.request.POST and hasattr(self.request.POST['csvfile'], 'file'):
            if self.request.POST.get('csrf_token') != self.request.session.get_csrf_token():
                log.warn('CSRF attempt at: {0}.'.format(self.request.url))
                raise Forbidden

            csv = self.request.POST['csvfile']
            errors = []

            try:
                try:
                    # Attempt to parse it as an Excel file first.
                    submission = self.parse_xls(csv.file)
                    log.info('Received Excel submission from "{0}".'.format(user.username))
                except xlrd.XLRDError:
                    # Fall back to CSV format.
                    csv.file.seek(0)
                    submission = self.parse_csv(csv.file)
                    log.info('Received CSV submission from "{0}".'.format(user.username))

                errors = self.validate(submission)
            except:
                log.warn('User "{0}" attempted to submit a non compliant file.'.format(user.username))
                options['file_type_error'] = True

            if options['file_type_error'] is None and len(errors) == 0:
                # Clear submissions for the user's school.
                session.query(CSVSubmission).filter_by(kind=CSVSubmission.VOTER,
                                                       school_id=user.school.id).delete()
                # Add the latest submission.
                session.add(CSVSubmission(
                    self.normalize(submission),
                    user.school,
                    CSVSubmission.VOTER))
                self.request.session.flash(u'Tiedosto tallennettu onnistuneesti.')

                # Redirect to avoid form resubmission on page reload.
                return HTTPFound(location=route_url('submit_voters', self.request))
            else:
                log.warn('Validation failed for voter submission made by "{0}"'.format(user.username))
                self.request.session.flash(u'Lähetetyssä tiedostossa oli virheitä. '
                                           u'Korjaa virheet ja lähetä uudelleen.')
                errors_to_show = 15
                options['errors'] = errors[:errors_to_show]
                if len(errors) > errors_to_show:
                    options['errors_left'] = len(errors) - errors_to_show

                # Print out the validation errors for easier failure tracking.
                for error_msg in options['errors']:
                    log.warn(u'Validation error (L{lineno}): {msg}'.format(**error_msg))

        options.update({
            'csrf_token': self.request.session.get_csrf_token(),
            'submission': None,
            'template_url': route_url('voters_template_xls', self.request),
            'action_url': route_url('submit_voters', self.request),
            'data_length_text': u'0 henkilöä',
            })

        submission = session.query(CSVSubmission)\
                        .filter_by(kind=CSVSubmission.VOTER, school_id=user.school.id)\
                        .first()
        if submission is not None:
            data_length = len(submission.csv)
            options['data_length_text'] = u'1 henkilö' if data_length == 1 else u'{0} henkilöä'.format(data_length)
            options['submission'] = {
                'timestamp': submission.timestamp.strftime('%d.%m.%Y %H:%M'),
                'data': submission.csv,
            }

        self.request.add_response_callback(disable_caching)

        return options