Exemple #1
0
    def test_login__form_submission__invalid_password(self):
        from nuvavaalit.models import Voter
        from nuvavaalit.views.login import login

        session = DBSession()
        session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers'))
        session.flush()
        self.assertEquals(
            session.query(Voter).filter_by(username=u'buck.rogers').first().fullname(),
            u'Bück Rögers')

        request = testing.DummyRequest(statsd=False)
        token = request.session.new_csrf_token()
        request.POST = {
            'form.submitted': u'1',
            'username': u'buck.rogers',
            'password': u'thisiswrong',
            'csrf_token': token,
        }

        options = login(request)
        self.assertEquals(options, {
            'action_url': 'http://example.com/tunnistaudu',
            'csrf_token': token,
            'error': u'Tunnistautuminen epäonnistui. Kokeile tunnistautua uudelleen!'})
Exemple #2
0
    def test_login__form_submission__success(self, remember):
        from nuvavaalit.models import Voter
        from nuvavaalit.views.login import login

        session = DBSession()
        session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers'))
        session.flush()
        self.assertEquals(
            session.query(Voter).filter_by(username=u'buck.rogers').first().fullname(),
            u'Bück Rögers')

        remember.return_value = [('X-Login', 'buck.rogers')]
        request = testing.DummyRequest(statsd=False)
        token = request.session.new_csrf_token()
        request.POST = {
            'form.submitted': u'1',
            'username': u'buck.rogers',
            'password': u'secret',
            'csrf_token': token,
        }

        response = login(request)
        self.assertEquals(dict(response.headers), {
            'Content-Length': '0',
            'Content-Type': 'text/html; charset=UTF-8',
            'Location': 'http://example.com/valitse',
            'X-Login': '******'})
Exemple #3
0
    def run(self):
        session = DBSession()
        session.bind.echo = False

        # Join the repoze.filesafe manager in the transaction so that files will
        # be written only when a transaction commits successfully.
        filesafe = FileSafeDataManager()
        transaction.get().join(filesafe)

        # Query the currently existing usernames to avoid UNIQUE violations.
        self.usernames.update(username for cols in session.query(Voter.username).all() for username in cols)

        fh_itella = filesafe.createFile(self.output, 'w')

        # Excel worksheet for Itella
        wb_itella = xlwt.Workbook(encoding='utf-8')
        ws_itella = wb_itella.add_sheet('Hexagon IT')
        text_formatting = xlwt.easyxf(num_format_str='@')
        for col, header in enumerate([u'Tunnus', u'Salasana', u'Nimi', u'Osoite', u'Postinumero', u'Postitoimipaikka']):
            ws_itella.write(0, col, header, text_formatting)
        rows_itella = count(1)
        voter_count = 0

        self.header('Starting to process {}'.format(self.source_file))
        src_sheet = xlrd.open_workbook(self.source_file).sheet_by_index(0)
        pbar = progressbar.ProgressBar(widgets=[progressbar.Percentage(), progressbar.Bar()], maxval=src_sheet.nrows).start()

        for row in xrange(1, src_sheet.nrows):
            token, lastname, names, address, zipcode, city = [c.value for c in src_sheet.row_slice(row, 0, 6)]
            names = names.split()
            firstname = names[0]

            username = self.genusername(names, lastname)
            password = self.genpasswd()

            # Create the voter instance.
            session.add(Voter(username, password, firstname, lastname, token))

            # Write the Itella information
            row = rows_itella.next()

            for col, item in enumerate([username, password, u'{} {}'.format(u' '.join(names), lastname), address, zipcode, city]):
                ws_itella.write(row, col, item, text_formatting)

            voter_count += 1
            pbar.update(voter_count)

        wb_itella.save(fh_itella)
        fh_itella.close()

        session.flush()
        transaction.commit()
        pbar.finish()

        self.header('Finished processing')
        print 'Processed', voter_count, 'voters.'
    def test_voting_forbidden_authorized_after_election_period(self):
        from nuvavaalit.models import Voter

        session = DBSession()
        session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers'))
        session.flush()

        self.authenticate(u'buck.rogers')
        response = self.testapp.get('/aanesta/abcdefg', expect_errors=True)
        self.assertEquals(response.status, '403 Forbidden')
Exemple #5
0
    def test_authenticated_user__authenticated(self):
        from nuvavaalit.models import Voter
        from nuvavaalit.views.login import authenticated_user

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

        user = Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers')
        session.add(user)

        self.assertEquals(user, authenticated_user(testing.DummyRequest(statsd=False)))
Exemple #6
0
    def test_no_votes(self):
        from nuvavaalit.models import Candidate
        from nuvavaalit.models import Voter
        from nuvavaalit.views.results import results

        session = DBSession()
        session.add(Voter(u"buck.rogers", u"secret", u"Bück", u"Rögers"))
        session.add(Candidate(2, u"Steven", u"Seagal", u"No pain, no game", u""))
        session.add(Candidate(7, u"Jet", u"Li", u"Yin, yang", u""))
        session.add(Candidate(11, u"Jean-Claude", u"van Damme", u"No engrish", u""))
        session.flush()

        self.assertEquals(
            results(testing.DummyRequest(statsd=False)),
            {
                "others": [],
                "selected": [
                    {"name": u"Li, Jet", "number": 7, "percentage": "0.0", "votes": 0},
                    {"name": u"Seagal, Steven", "number": 2, "percentage": "0.0", "votes": 0},
                    {"name": u"van Damme, Jean-Claude", "number": 11, "percentage": "0.0", "votes": 0},
                ],
                "threshold": 8,
                "total_votes": 0,
                "show_leftovers": False,
                "voting_percentage": "0.0",
            },
        )
    def test_encrypted_link_matches_selection(self):
        from nuvavaalit.models import Candidate
        from nuvavaalit.models import Voter

        session = DBSession()
        session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers'))
        session.add(Candidate(2, u'Steven', u'Seagal', u'No pain, no game', u''))
        session.add(Candidate(7, u'Jet', u'Li', u'Yin, yang', u''))
        session.add(Candidate(11, u'Jean-Claude', u'van Damme', u'No engrish', u''))
        session.flush()

        response = self.testapp.get('/tunnistaudu')
        response.form['username'] = u'buck.rogers'
        response.form['password'] = u'secret'
        response = response.form.submit()

        self.assertEquals(response.status, '302 Found')
        self.assertEquals(response.location, 'http://localhost/valitse')
        response = response.follow()

        self.assertEquals(response.request.url, 'http://localhost/valitse')
        voting_links = response.html.findAll('a', attrs={'href': re.compile('^http://localhost/aanesta/')})
        self.assertEquals(voting_links[1]['href'], voting_links[2]['href'])
        self.assertEquals(voting_links[2].text, u'Seagal, Steven, 2')
        # Click the voting link
        response = self.testapp.get(voting_links[2]['href'])
        # Assert that we get a matching candidate selection
        self.assertEquals(response.html.find('p', attrs={'class': 'candidate-name'}).text, u'2 Seagal, Steven')
Exemple #8
0
def populate_test_users():
    """Populates the database with test users."""
    parser = argparse.ArgumentParser(description='Generates test users in the database.')
    parser.add_argument('config', help='Path to a Paste configuration file, e.g. development.ini.')
    parser.add_argument('quantity', nargs='?', default=10, type=int, help='Number of test users to generate.')
    args = parser.parse_args()

    env = bootstrap(relpath(args.config))
    session = DBSession()
    session.bind.echo = False

    for i in xrange(1, args.quantity + 1):
        session.add(Voter(u'user{}'.format(i), u'testi', u'User #{}'.format(i), u'Fööbär'))

    session.flush()
    transaction.commit()

    print "Created {} test users".format(args.quantity)
    env['closer']()
    def test_already_voted_user_is_logged_out(self):
        from nuvavaalit.models import Voter
        from nuvavaalit.models import VotingLog

        session = DBSession()
        voter = Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers')
        session.add(voter)
        session.flush()
        session.add(VotingLog(voter))
        session.flush()

        self.assertTrue(voter.has_voted())
        self.authenticate(u'buck.rogers')
        response = self.testapp.get('/valitse')

        # An already voted user is redirected to the thank you page.
        self.assertEquals(response.status, '302 Found')
        self.assertEquals(response.location, 'http://localhost/kiitos')

        # Assert that we get cookies that log out the user.
        self.assertLogoutCookies(response)
Exemple #10
0
    def test_candidates(self):
        from nuvavaalit.models import Candidate
        from nuvavaalit.views.public import browse_candidates

        session = DBSession()
        session.add(Candidate(2, u'Steven', u'Seagal', u'No pain, no game', u''))
        session.add(Candidate(7, u'Jet', u'Li', u'Yin, yang', u''))
        session.add(Candidate(11, u'Jean-Claude', u'van Damme', u'No engrish', u''))
        session.flush()

        options = browse_candidates(testing.DummyRequest(statsd=False))
        positions = options.pop('positions')
        self.assertEquals('0 1:3 2:3 0 1:3 2:3'.split(), [positions.next() for i in xrange(6)])
        self.assertEquals(list(options.pop('candidates')), [
            [{'image_url': 'http://example.com/static/images/candidates/2.jpg',
              'name': u'Seagal, Steven',
              'number': 2,
              'slogan': u'No pain, no game'},
             {'image_url': 'http://example.com/static/images/candidates/7.jpg',
              'name': u'Li, Jet',
              'number': 7,
              'slogan': u'Yin, yang'},
             {'image_url': 'http://example.com/static/images/candidates/11.jpg',
              'name': u'van Damme, Jean-Claude',
              'number': 11,
              'slogan': u'No engrish'}]])
        self.assertEquals(options, {
            'columns': 3,
            'page_name': 'browse'})
Exemple #11
0
def populate_candidates():
    """Populates the database with candidate information."""
    parser = argparse.ArgumentParser(description='Generates candidates in the database.')
    parser.add_argument('config', help='Path to a Paste configuration file, e.g. development.ini.')
    parser.add_argument('candidates', nargs='?', help='Path to a CSV file containing the candidate information.')
    args = parser.parse_args()

    env = bootstrap(relpath(args.config))

    session = DBSession()
    session.bind.echo = False
    # Create the candidate for empty votes.
    session.add(Candidate(Candidate.EMPTY_CANDIDATE, u'Tyhjä', u'', u'', u''))

    csv_file = relpath(args.candidates)
    reader = csv.reader(open(csv_file))

    print 'Reading candidates from', csv_file

    cnt = 0
    reader.next()

    for row in reader:
        number, firstname, lastname, slogan = row[:4]
        try:
            number = int(number.strip())
        except (TypeError, ValueError):
            print 'Invalid data: {}'.format(str(row))
            continue

        session.add(Candidate(number, univalue(firstname), univalue(lastname), univalue(slogan), u''))
        print 'Added {} {}, {}'.format(firstname, lastname, number)
        cnt += 1

    session.flush()
    transaction.commit()

    print "Created {} candidates.".format(cnt)
    env['closer']()
Exemple #12
0
    def test_different_sessions_get_different_vote_links(self):
        from nuvavaalit.models import Candidate
        from nuvavaalit.models import Voter

        session = DBSession()
        session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers'))
        session.add(Candidate(2, u'Steven', u'Seagal', u'No pain, no game', u''))
        session.add(Candidate(7, u'Jet', u'Li', u'Yin, yang', u''))
        session.add(Candidate(11, u'Jean-Claude', u'van Damme', u'No engrish', u''))
        session.flush()

        response = self.testapp.get('/tunnistaudu')
        response.form['username'] = u'buck.rogers'
        response.form['password'] = u'secret'
        response = response.form.submit()

        self.assertEquals(response.status, '302 Found')
        self.assertEquals(response.location, 'http://localhost/valitse')
        response = response.follow()

        self.assertEquals(response.request.url, 'http://localhost/valitse')
        # Get a list of voting links
        voting_links = [str(tag) for tag in response.html.findAll('a', attrs={'href': re.compile('^http://localhost/aanesta/')})]

        # Login again to the application, creating a new session
        response = self.testapp.get('/tunnistaudu')
        response.form['username'] = u'buck.rogers'
        response.form['password'] = u'secret'
        response = response.form.submit()

        self.assertEquals(response.status, '302 Found')
        self.assertEquals(response.location, 'http://localhost/valitse')
        response = response.follow()

        self.assertEquals(response.request.url, 'http://localhost/valitse')
        new_voting_links = [str(tag) for tag in response.html.findAll('a', attrs={'href': re.compile('^http://localhost/aanesta/')})]

        self.assertEquals(len(voting_links), len(new_voting_links))
        self.assertNotEqual(voting_links, new_voting_links)
Exemple #13
0
    def test_stable_sorting_of_equals(self):
        """Test that in case of a tie we get a stable but random sorting of candidates."""
        from nuvavaalit.models import Candidate
        from nuvavaalit.models import Vote
        from nuvavaalit.models import Voter
        from nuvavaalit.views.results import results

        session = DBSession()
        session.add(Voter(u"buck.rogers", u"secret", u"Bück", u"Rögers"))
        session.add(Candidate(2, u"Steven", u"Seagal", u"No pain, no game", u""))
        session.add(Candidate(7, u"Jet", u"Li", u"Yin, yang", u""))
        session.add(Candidate(11, u"Jean-Claude", u"van Damme", u"No engrish", u""))
        session.flush()

        candidate_two = session.query(Candidate).filter_by(number=2).first()
        candidate_seven = session.query(Candidate).filter_by(number=7).first()

        session.add(Vote(candidate_two))
        session.add(Vote(candidate_seven))
        session.flush()

        self.assertEquals(
            results(testing.DummyRequest(statsd=False)),
            {
                "others": [],
                "selected": [
                    {"name": u"Li, Jet", "number": 7, "percentage": "50.0", "votes": 1},
                    {"name": u"Seagal, Steven", "number": 2, "percentage": "50.0", "votes": 1},
                    {"name": u"van Damme, Jean-Claude", "number": 11, "percentage": "0.0", "votes": 0},
                ],
                "threshold": 8,
                "total_votes": 2,
                "show_leftovers": False,
                "voting_percentage": "200.0",
            },
        )

        # Rendering the results again will result in the same relative ordering
        # of the equal votes.
        self.assertEquals(
            results(testing.DummyRequest(statsd=False)),
            {
                "others": [],
                "selected": [
                    {"name": u"Li, Jet", "number": 7, "percentage": "50.0", "votes": 1},
                    {"name": u"Seagal, Steven", "number": 2, "percentage": "50.0", "votes": 1},
                    {"name": u"van Damme, Jean-Claude", "number": 11, "percentage": "0.0", "votes": 0},
                ],
                "threshold": 8,
                "total_votes": 2,
                "show_leftovers": False,
                "voting_percentage": "200.0",
            },
        )
Exemple #14
0
    def test_empty_votes_removed_from_results_listing(self):
        """Test that in case of a tie we get a stable but random sorting of candidates."""
        from nuvavaalit.models import Candidate
        from nuvavaalit.models import Vote
        from nuvavaalit.models import Voter
        from nuvavaalit.views.results import results

        session = DBSession()
        session.add(Voter(u"buck.rogers", u"secret", u"Bück", u"Rögers"))
        session.add(Candidate(Candidate.EMPTY_CANDIDATE, u"empty", u"empty", u"empty", u"empty"))
        session.add(Candidate(2, u"Steven", u"Seagal", u"No pain, no game", u""))
        session.add(Candidate(7, u"Jet", u"Li", u"Yin, yang", u""))
        session.add(Candidate(11, u"Jean-Claude", u"van Damme", u"No engrish", u""))
        session.flush()

        candidate_two = session.query(Candidate).filter_by(number=2).first()
        candidate_seven = session.query(Candidate).filter_by(number=7).first()
        candidate_empty = session.query(Candidate).filter_by(number=Candidate.EMPTY_CANDIDATE).first()

        session.add(Vote(candidate_two))
        session.add(Vote(candidate_seven))
        session.add(Vote(candidate_empty))
        session.add(Vote(candidate_empty))
        session.flush()

        # The empty votes do not show up in the results listing but do
        # affect the number of votes, percentages, etc.
        self.assertEquals(
            results(testing.DummyRequest(statsd=False)),
            {
                "others": [],
                "selected": [
                    {"name": u"Li, Jet", "number": 7, "percentage": "25.0", "votes": 1},
                    {"name": u"Seagal, Steven", "number": 2, "percentage": "25.0", "votes": 1},
                    {"name": u"van Damme, Jean-Claude", "number": 11, "percentage": "0.0", "votes": 0},
                ],
                "threshold": 8,
                "total_votes": 4,
                "show_leftovers": False,
                "voting_percentage": "400.0",
            },
        )
Exemple #15
0
def vote(request):
    """Renders the voting form for the selected candidate and processes the
    vote.

    A valid vote must meet all of the following criteria:

        * The voter must be authenticated.

        * The voter must not have voted previously.

        * The candidate must be the one chosen in the previous step (See
          :py:func:`select`).

        * The CSRF token included in the form must be valid.

    :param request: The currently active request.
    :type request: :py:class:`pyramid.request.Request`

    :rtype: dict
    """
    error = False
    session = DBSession()
    voter = authenticated_user(request)
    log = logging.getLogger('nuvavaalit')
    request.add_response_callback(disable_caching)
    localizer = get_localizer(request)

    # The user must be authenticated at this time
    if voter is None:
        log.warn('Unauthenticated attempt to vote.')
        raise HTTPForbidden()

    # The user may vote only once
    if voter.has_voted():
        log.warn('User "{}" attempted to vote a second time.'.format(voter.username))
        return exit_voting(request)

    # Find the selected candidate
    try:
        number = int(decrypt(request.matchdict['id'], request.session['encryption_key']))
    except (ValueError, TypeError):
        log.warn('Candidate number decryption failed')
        raise HTTPNotFound

    candidate = session.query(Candidate)\
            .filter(Candidate.number == number)\
            .first()

    if candidate is None:
        log.warn('User "{}" attempted to vote for a non-existing candidate "{}".'.format(
            voter.username, number))
        raise HTTPNotFound

    # Handle voting
    if 'vote' in request.POST:

        if request.session.get_csrf_token() != request.POST.get('csrf_token'):
            log.warn('CSRF attempt at: {0}.'.format(request.url))
            error = True
        elif request.POST['vote'].strip() == str(number):

            session.add(Vote(candidate))
            session.add(VotingLog(voter))

            log.info('Stored vote cast by "{}".'.format(voter.username))
            if request.statsd:
                statsd.increment('vote.success')
            return exit_voting(request)
        else:
            error = True

    if request.statsd and error:
        statsd.increment('vote.error')

    options = {
        'action_url': request.path_url,
        'select_url': route_url('select', request),
        'candidate': {
            'number': candidate.number,
            'name': candidate.fullname() if not candidate.is_empty() else _(u'Tyhjä'),
            },
        'voter': {
            'fullname': voter.fullname(),
        },
        'error': error,
        'csrf_token': request.session.get_csrf_token(),
        'unload_confirmation': localizer.translate(
            _(u'Et ole vielä äänestänyt. Oletko varma, että haluat poistua sivulta?')),
    }

    return options
Exemple #16
0
    def test_successful_voting_process(self):
        from nuvavaalit.models import Candidate
        from nuvavaalit.models import Vote
        from nuvavaalit.models import Voter
        from nuvavaalit.models import VotingLog

        # Create a user we will authenticate as.
        session = DBSession()
        session.add(Voter(u'buck.rogers', u'secret', u'Bück', u'Rögers'))
        session.add(Candidate(2, u'Steven', u'Seägäl', u'No pain, no game', u''))
        session.add(Candidate(7, u'Jët', u'Li', u'Yin, yang', u''))
        session.add(Candidate(11, u'Jeän-Claüde', u'van Damme', u'No engrish', u''))
        session.flush()

        self.assertEquals(0, session.query(Vote).count())
        self.assertEquals(0, session.query(VotingLog).count())

        self.authenticate(u'buck.rogers')

        # Accessing the system front page will redirect us to the login page
        # during the elections.
        response = self.testapp.get('/')
        self.assertEquals(response.status, '302 Found')
        self.assertEquals(response.location, 'http://localhost/tunnistaudu')
        response = response.follow()

        # Logging in the system successfully will bring us to the candidate
        # selection page.
        response.form['username'] = u'buck.rogers'
        response.form['password'] = u'secret'
        response = response.form.submit()
        self.assertEquals(response.status, '302 Found')
        self.assertEquals(response.location, 'http://localhost/valitse')
        response = response.follow()

        # Selecting a candidate brings us to the voting page.
        self.assertEquals(response.request.url, 'http://localhost/valitse')
        voting_links = response.html.findAll('a', attrs={'href': re.compile('^http://localhost/aanesta/')})
        # Assert we have two links to the candidate.
        self.assertEquals(voting_links[1]['href'], voting_links[2]['href'])
        self.assertEquals(voting_links[2].text, u'Seägäl, Steven, 2')
        # Click the voting link
        response = self.testapp.get(voting_links[2]['href'])
        self.assertTrue(response.request.url.startswith('http://localhost/aanesta/'))
        # Assert that we get a matching candidate selection
        self.assertEquals(response.html.find('p', attrs={'class': 'candidate-name'}).text, u'2 Seägäl, Steven')

        # Attempting to vote a non-selected candidate gives us an error message.
        response.form['vote'] = u'69'
        response = response.form.submit()
        self.assertTrue(response.html.find('div', attrs={'class': 'error'}).text.startswith(u'Antamasi ehdokasnumero ei vastaa valintaasi'))
        self.assertTrue(response.request.url.startswith('http://localhost/aanesta/'))

        # Voting for the selected candidate stores the vote and logs out the user.
        response.form['vote'] = u'2'
        response = response.form.submit()
        self.assertEquals(response.status, '302 Found')
        self.assertEquals(response.location, 'http://localhost/kiitos')
        # Assert that we get cookies that log out the user.
        self.assertLogoutCookies(response)

        # Assert that the vote was recorded correctly.
        self.assertEquals(2, session.query(Vote).one().candidate.number)
        self.assertEquals(u'buck.rogers', session.query(VotingLog).one().voter.username)

        # Assert that subsequent attempts to login results in automatic logout.
        response = self.testapp.get('/tunnistaudu')
        response.form['username'] = u'buck.rogers'
        response.form['password'] = u'secret'
        response = response.form.submit()

        self.assertEquals(response.status, '302 Found')
        self.assertEquals(response.location, 'http://localhost/kiitos')
        # Assert that we get cookies that log out the user.
        self.assertLogoutCookies(response)