Commit 6789af2e authored by Swergas's avatar Swergas

implement first steps of test scenario 3 (trustees with threshold)

parent 7eaf4d5d
......@@ -64,6 +64,8 @@ build_and_run_automated_test_scenarios_with_preinstalled_image:
- source venv/bin/activate
# Install pip packages
- pip install -r requirements.txt
# Run the automated test scenario 3
- python3 ./tests/test_scenario_3.py
# Run the automated test scenario 2
- python3 ./tests/test_scenario_2.py
# Run the automated test scenario 1
......
Scenario 3: Vote with vote codes in manual mode and manual trustees, using a threshold for trustees
=================================
## Introduction and parameters
Protagonists to emulate: election administrator, credential authority, `T` trustees, `K` electors, an auditor.
Administrator and trustees uses only thier browser. Credential authority uses her browser and sends emails.
Electors use their browser and read emails sent by the server and by the credential authority.
`L` electors re-vote (with `L <= K`)
`M` electors ask administrator to re-generate their password, and vote with their re-generated password (with `M <= K`).
A threshold of `U` trustees are needed (among all `T` trustees) to validate the vote.
The auditor makes web requests, has a persistent state, and runs the commandline version of the Belenios tool.
Auditor makes web requests, has a persistent state, and runs the commandline version of the Belenios tool.
Authentication of administrator and electors are done using a login / password combination.
Examples of parameters sizes: `N` and `K` would be between 6 (quick test) and 1000 (load test)
## Note about verification
Verifications all along the process is done using command line tools `belenios-tool verify` and `belenios-tool verify-diff`:
- `belenios-tool verify` does a static verification (it verifies that vote data at current time is coherent)
- `belenios-tool verify-diff` does a dynamic verification (it verifies that current state of vote data is a possible/legitimate evolution of a vote data snapshot that has been saved during a previous step of the process)
## Detailed steps of the Test Scenario 1 process
- Starting setup of the election (action of the administrator)
- Creation of the draft election
- Alice has been given administrator rights on an online voting app called Belenios. She goes to check out its homepage and logs in.
- She clicks on the "Prepare a new election" link
- She picks the Credential management method: manual
- (She keeps default value for Authentication method: it is Password, not CAS)
- She clicks on the "Proceed" button (this redirects to the "Preparation of election" page)
- In the "Name and description of the election" section, she changes values of fields name and description of the election
- She clicks on the "Save changes button" (the one that is next to the election description field)
- In the "Contact" section, the changes values of field "Contact:", and clicks on the "Save changes button" of this section
- She remembers the URL of the draft election administration page
- Edition of election's questions
- She clicks on the "Edit questions" link, to write her own questions
- She arrives on the Questions page. She checks that the page title is correct
- She removes answer 3
- She clicks on the "Save changes" button (this redirects to the "Preparation of election" page)
- Setting election's voters
- She clicks on the "Edit voters" link, to then type the list of voters
- She types `N` e-mail addresses (the list of invited voters)
- She clicks on the "Add" button to submit changes
- She clicks on "Return to draft page" link
- In "Authentication" section, she clicks on the "Generate and mail missing passwords" button
- She checks that the page contains expected confirmation text, instead of an error
- She clicks on the "Proceed" link
- In "Credentials" section, she clicks on "Credential management" link
- She remembers the link displayed
- She sends the remembered link to the credential authority by email
- She logs out and closes the browser
- Credential authority sends credentials to electors
- Cecily, the Credential Authority, receives the email sent by Alice, and opens the link in it
- She remembers what the link to the election will be, so that she will be able to send it to voters by email with their private credential
- She clicks on the "Generate" button
- She clicks on the "private credentials" and "public credentials" links and downloads these files. (Files are by default downloaded using filenames `creds.txt` and `public_creds.txt` respectively)
- She clicks on the "Submit public credentials" button
- She checks that redirected page shows correct confirmation sentence
- She closes the window
- She reads the private credentials file (`creds.txt`) and sends credential emails to voters
- Continuing setup of the election: Administrator invites trustees and sets threshold
- Administrator logs in and goes to the election draft page
- In the "Trustees" section, she clicks on the "here" link
- She clicks on the "threshold mode" link
- In the field next to "Threshold:", she types `U`, and clicks on the "Set" button
- She adds `T` trustees (their email address), and remembers the link she will send to each trustee
- She sends to each trustee an email containing their own link
- She logs out and closes the window
- Trustees initialization step 1/3: Trustees generate election private keys. Each of the `T` trustees will do the following process:
- Trustee opens link that has been sent to him by election administrator
- He checks that the page content shows the same election URL as the one the administrator saw
- He clicks on the "Generate private key" button
- He clicks on the "private key" link, to download the private key (file is saved by default as `private_key.txt`)
- He clicks on the "Submit" button
- He checks that the next page shows the expected confirmation sentence ("Waiting for the other trustees... Reload the page to check progress.")
- He closes the window
- (Administrator logs in, selects the election by clicking on its link, and in the "Trustees" section clicks on "here". She checks that in the table on the current trustee row, the "STATE" column is now "1b" instead of "1a")
- If trustee was the last one in the list, he checks that page contains text "Now, all the certificates of the trustees have been generated. Proceed to generate your share of the decryption key."
- (Administrator logs in, selects the election by clicking on its link, and in the "Trustees" section clicks on "here". She checks that in the table on every row, the "STATE" column is now "2a")
- Trustees initialization step 2/3: Trustees generate their share of the decryption key. Each of the `T` trustees will do the following process:
- Trustee opens link that has been sent to him by election administrator
- He checks that the page content shows the same election URL as the one the administrator saw
- He checks the presence of text "Now, all the certificates of the trustees have been generated. Proceed to generate your share of the decryption key."
- In field next to "Enter your private key:", he types the content of the `private_key.txt` file he downloaded
- He clicks on the "Proceed" button
- He waits until the text field next to "Data:" contains text, and clicks on the "Submit" button
- If he is not the last trustee in the list, he checks that the next page contains text "Waiting for the other trustees... Reload the page to check progress.". Else, he checks that the next page contains text "Now, all the trustees have generated their secret shares. Proceed to the final checks so that the election can be validated."
- (Administrator logs in, selects the election by clicking on its link, and in the "Trustees" section clicks on "here". She checks that in the table on the current trustee row, the "STATE" column is now "2b" instead of "2a")
- Trustees initialization step 3/3: Trustees do the final checks so that the election can be validated. Each of the `T` trustees will do the following process:
- Trustee opens link that has been sent to him by election administrator
- He checks that the page content shows the same election URL as the one the administrator saw
- He checks the presence of text "Step 3/3"
- He checks the presence of text "Now, all the certificates of the trustees have been generated. Proceed to generate your share of the decryption key."
- In field next to "Enter your private key:", he types the content of the `private_key.txt` file he downloaded
- He clicks on the "Proceed" button
- He waits until the text field next to "Data:" contains text, and clicks on the "Submit" button
- He checks that the next page contains text "Your job in the key establishment protocol is done!"
- He clicks on the "public key" link and downloads the file (file is saved by default as `public_key.json`)
- (Administrator logs in, selects the election by clicking on its link, and in the "Trustees" section clicks on "here". She checks that in the table on the current trustee row, the "STATE" column is now "3b" instead of "3a")
- Administrator completes setup of the election
- Alice, as an administrator of an election, wants to finalize her draft election creation, to start the vote. She opens a browser and logs in as administrator
- She goes to the draft election administration page
- In the "Trustees" section clicks on "here". She checks that in the table on all rows, the "STATE" column is now "done"
- She clicks on the "Go back to election draft" link
- In "Validate creation" section, she clicks on the "Create election" link
- (She arrives on the "Checklist" page, that lists all main parameters of the election for review, and that flags incoherent or misconfigured parameters. For example, in this test scenario, it displays 2 warnings: "Warning: No trustees were set. This means that the server will manage the election key by itself.", and "Warning: No contact was set!")
- She checks the presence of text "election ready"
- In the "Validate creation" section, she clicks on the "Create election" button
- (She arrives back on the "My test election for Scenario 1 — Administration" page. Its contents have changed. There is now a text saying "The election is open. Voters can vote.", and there are now buttons "Close election", "Archive election", "Delete election")
- She remembers the URL of the voting page, that is where the "Election home" link points to
- She checks that a "Close election" button is present (but she does not click on it)
- She logs out and closes the window
- Verify election consistency (using command line tool `belenios_tool verify`)
- All voting electors cast their vote (`K` electors vote). We check vote data consistency for every batch of `X` votes (using `belenios_tool verify-diff` and a snapshot of election data copied in previous batch). For each batch of `X` voters:
- Create election data snapshot
- Current batch of electors vote. For each voter of this batch:
- Bob checks that he has received 2 emails containing an invitation to vote and all necessary credentials (election page URL, username, password). He goes to the election page URL.
- He clicks on the "Start" button
- A loading screen appears, then another screen appears. He clicks on the "Here" button
- A modal opens (it is an HTML modal created using Window.prompt()), with an input field. He types his credential.
- He fills his votes to each answer of the question (for each displayed checkbox, he decides to mark it or leave it empty)
- He clicks on the "Next" button
- He remembers the smart ballot tracker that is displayed
- He clicks on the "Continue" button
- He types his voter username and password, and submits the form
- He checks that the smart ballot tracker value that appears on screen is the same as the one he noted
- He clicks on the "I cast my vote" button
- He clicks on the "ballot box" link
- He checks that his smart ballot tracker appears in the list
- He closes the window (there is no log-out link, because user is not logged in: credentials are not remembered)
- He checks his mailbox to find a new email with confirmation of his vote, and verifies the value of the smart ballot tracker written in this email is the same as the one he noted.
- Verify election consistency (using `belenios_tool verify-diff`)
- Delete election data snapshot
- Verify election consistency (using command line tool `belenios_tool verify`)
- Create election data snapshot
- All electors who want to change their vote re-vote (`L` electors re-vote)
- We re-apply the same procedure as listed in previous step, except we use the set of `L` re-voters instead of the set of `K` voters
- Verify election consistency (using `belenios_tool verify-diff` and the snapshot created right before re-votes)
- Delete election data snapshot
- Verify election consistency (using command line tool `belenios_tool verify`)
- Administrator starts tallying of the election
- Alice goes to the election page
- She clicks on the "Administer this election" link
- She logs in as administrator
- She clicks on the "Close election" button
- She clicks on the "Proceed to vote counting" button
- She remembers the encrypted tally hash
- She remembers the link to send to each trustee, so they can tally the election
- She sends to each trustee an email containing their own link
- She logs out and closes the window
- Trustees do tallying (partial decryption). Each trustee (Tom and Taylor) will do the following process:
- He opens the link that Alice (the election administrator) has sent to him
- We verify that the encrypted election hash is the same as the one that has been displayed to election administrator
- He verifies that the "private key" input field is empty (at the beginning)
- He clicks on the "Browse..." button and selects his private key file (initially downloaded as `private_key.json` by default)
- He waits until the "private key" input field (that has id "#private_key") becomes not empty anymore. This is because once the user has selected the file to upload, the Javascript code in the page detects that a file has been selected, reads it, and fills "private key" input field with file's contents. The computation triggered by click on the "Compute decryption factors" button will use the value of this field, not directly the uploaded file contents.
- He clicks on the "Compute decryption factors" button
- He checks that the text field below (used as visual feedback) now contains text
- He clicks on the "Submit" button
- He checks that next screen contains a confirmation sentence
- He closes the window
- Administrator finished tallying of the election
- Alice goes to the election page
- She clicks on the "Administer this election" link
- She logs in as administrator
- She checks that encrypted tally hash is still the same as the first time it has been displayed to her
- She checks that the "DONE?" column of each trustee is to "Yes"
- She clicks on the "Compute the result" button
- She checks consistency of the election result
- She checks that the number of accepted ballots is the same as the number of voters who voted
- For each available answer in the question, she checks that the total number of votes in favor of Answer X displayed in result page is the same as the sum of votes for Answer X in all votes of voters who voted that have been randomly generated in advance
- She checks that each ballot content corresponds to content that of this vote that has been randomly generated in advance
- Verify election consistency (using command line tool `belenios_tool verify`)
......@@ -20,6 +20,7 @@ ELECTION_TITLE = "My test election for Scenario 1"
ELECTION_DESCRIPTION = "This is the description of my test election for Scenario 1"
ADMINISTRATOR_USERNAME = "user1" # This value comes from file `demo/password_db.csv`, first row, first column
ADMINISTRATOR_PASSWORD = "phiexoey" # This value comes from file `demo/password_db.csv`, first row, 4th column
INITIATOR_CONTACT = "Election initiator <election.initiator@mytestelection.com>"
GIT_REPOSITORY_ABSOLUTE_PATH = dirname(dirname(abspath(__file__)))
......@@ -28,4 +29,6 @@ GIT_REPOSITORY_ABSOLUTE_PATH = dirname(dirname(abspath(__file__)))
BROWSER_DOWNLOAD_FOLDER = "/tmp"
ADMINISTRATOR_EMAIL_ADDRESS = "alice_aka_election_administrator@mailinator.com"
CREDENTIAL_AUTHORITY_EMAIL_ADDRESS = "cecily_aka_election_credential_authority@mailinator.com"
TRUSTEES_EMAIL_ADDRESSES = ["tom_aka_trustee_1@mailinator.com", "taylor_aka_trustee_2@mailinator.com"]
\ No newline at end of file
NUMBER_OF_TRUSTEES = 5
TRUSTEES_EMAIL_ADDRESSES = ["tom_aka_trustee_1@mailinator.com", "taylor_aka_trustee_2@mailinator.com", "tania_aka_trustee_3@mailinator.com", "tiffany_aka_trustee_4@mailinator.com", "theresa_aka_trustee_5@mailinator.com"]
TRUSTEES_THRESHOLD_VALUE = 3
......@@ -20,7 +20,7 @@ def initialize_browser_for_scenario_2():
return initialize_browser(for_scenario_2=True)
class BeleniosTestElectionScenario2(BeleniosElectionTestBase):
class BeleniosTestElectionScenario2Base(BeleniosElectionTestBase):
"""
Properties:
- server
......@@ -102,8 +102,10 @@ class BeleniosTestElectionScenario2(BeleniosElectionTestBase):
# - She picks the Credential management method: manual
# (- She keeps default value for Authentication method: it is Password, not CAS)
# - She clicks on the "Proceed" button (this redirects to the "Preparation of election" page)
# - She changes values of fields name and description of the election
# - In the "Name and description of the election" section, she changes values of fields name and description of the election
# - She clicks on the "Save changes button" (the one that is next to the election description field)
# - In "Contact" section, she changes the value of "contact" field
# - She clicks on the "Save changes" button (the one that is in the "Contact" section)
administrator_starts_creation_of_election(browser, True)
# She remembers the URL of the draft election administration page
......@@ -609,7 +611,10 @@ The election administrator.\
self.administrator_verifies_vote_results()
class BeleniosTestElectionScenario2(BeleniosTestElectionScenario2Base):
def test_scenario_2_manual_vote(self):
console_log("### Running test method BeleniosTestElectionScenario2::test_scenario_2_manual_vote()")
console_log("### Starting step: administrator_starts_creation_of_manual_election")
self.administrator_starts_creation_of_manual_election()
console_log("### Step complete: administrator_starts_creation_of_manual_election")
......@@ -699,6 +704,7 @@ if __name__ == "__main__":
settings.ADMINISTRATOR_PASSWORD = os.getenv('ADMINISTRATOR_PASSWORD', settings.ADMINISTRATOR_PASSWORD)
settings.ELECTION_TITLE = os.getenv('ELECTION_TITLE', settings.ELECTION_TITLE)
settings.ELECTION_DESCRIPTION = os.getenv('ELECTION_DESCRIPTION', settings.ELECTION_DESCRIPTION)
settings.INITIATOR_CONTACT = os.getenv('INITIATOR_CONTACT', settings.INITIATOR_CONTACT)
settings.BROWSER_DOWNLOAD_FOLDER = os.getenv('BROWSER_DOWNLOAD_FOLDER', settings.BROWSER_DOWNLOAD_FOLDER)
settings.ADMINISTRATOR_EMAIL_ADDRESS = os.getenv('ADMINISTRATOR_EMAIL_ADDRESS', settings.ADMINISTRATOR_EMAIL_ADDRESS)
settings.CREDENTIAL_AUTHORITY_EMAIL_ADDRESS = os.getenv('CREDENTIAL_AUTHORITY_EMAIL_ADDRESS', settings.CREDENTIAL_AUTHORITY_EMAIL_ADDRESS)
......@@ -714,6 +720,7 @@ if __name__ == "__main__":
console_log("NUMBER_OF_REGENERATED_PASSWORD_VOTERS:", settings.NUMBER_OF_REGENERATED_PASSWORD_VOTERS)
console_log("ELECTION_TITLE:", settings.ELECTION_TITLE)
console_log("ELECTION_DESCRIPTION:", settings.ELECTION_DESCRIPTION)
console_log("INITIATOR_CONTACT:", settings.INITIATOR_CONTACT)
console_log("BROWSER_DOWNLOAD_FOLDER:", settings.BROWSER_DOWNLOAD_FOLDER)
console_log("ADMINISTRATOR_EMAIL_ADDRESS:", settings.ADMINISTRATOR_EMAIL_ADDRESS)
console_log("CREDENTIAL_AUTHORITY_EMAIL_ADDRESS:", settings.CREDENTIAL_AUTHORITY_EMAIL_ADDRESS)
......
#!/usr/bin/python
# coding: utf-8
import unittest
import random
import os
import subprocess
import re
import sys
from uuid import uuid4
from distutils.util import strtobool
from selenium.common.exceptions import UnexpectedAlertPresentException
from util.fake_sent_emails_manager import FakeSentEmailsManager
from util.selenium_tools import wait_for_element_exists, wait_for_elements_exist, wait_for_element_exists_and_contains_expected_text, wait_for_element_exists_and_has_non_empty_content, wait_for_an_element_with_partial_link_text_exists, set_element_attribute, wait_for_element_exists_and_has_non_empty_attribute
from util.election_testing import console_log, random_email_addresses_generator, remove_database_folder, wait_a_bit, build_css_selector_to_find_buttons_in_page_content_by_value, initialize_server, initialize_browser, election_page_url_to_election_id, verify_election_consistency, create_election_data_snapshot, delete_election_data_snapshot, log_in_as_administrator, log_out, administrator_starts_creation_of_election, administrator_edits_election_questions, administrator_sets_election_voters, administrator_validates_creation_of_election
from util.election_test_base import BeleniosElectionTestBase
from test_scenario_2 import BeleniosTestElectionScenario2Base, initialize_browser_for_scenario_2
import settings
class BeleniosTestElectionScenario3(BeleniosTestElectionScenario2Base):
"""
Properties:
- server
- browser
- fake_sent_emails_manager: An instance of FakeSentEmailsManager
- voters_email_addresses: A list of email addresses (strings). This is all users who are invited to vote
- voters_email_addresses_who_have_lost_their_password: A list of email addresses (strings). This is all users who have asked for a new password.
- voters_email_addresses_who_have_voted: A dictionary, indexed by email address (string), where each element value is True
- voters_data: A dictionary, indexed by email address (string), where each element is a dictionary of fields for the voter who is identified by this email address. This is data about all users who have voted.
- election_page_url: The election page URL (string). Example: "http://localhost:8001/elections/H5ecRG3wHZ21cp/"
- election_id: The election ID (string). Example: "H5ecRG3wHZ21cp"
- draft_election_administration_page_url: URL of the draft election administration page
- credential_authority_link
- credential_authority_file_paths
- links_for_trustees
- downloaded_files_paths_per_trustee
- temporary_files_to_remove_after_test
- encrypted_tally_hash
- closed_election_tally_links_for_trustees
"""
__test__ = True
def __init__(self, *args, **kw):
super().__init__(*args, **kw)
self.draft_election_administration_page_url = None
self.credential_authority_link = None
self.credential_authority_file_paths = dict() # A dict where key is a label describing the file and value is the absolute path to file
self.links_for_trustees = []
self.downloaded_files_paths_per_trustee = dict() # A dict where key is trustee email address, and value is a dict where key is file label (for example "private key" or "public key"), and value is the absolute path to the file
self.temporary_files_to_remove_after_test = []
self.encrypted_tally_hash = None
self.closed_election_tally_links_for_trustees = []
def administrator_invites_trustees_and_sets_threshold(self):
self.browser = initialize_browser_for_scenario_2()
browser = self.browser
log_in_as_administrator(browser)
browser.get(self.draft_election_administration_page_url)
wait_a_bit()
# In the trustees section, she clicks on the "here" link
setup_election_key_link_label = "here"
setup_election_key_link_element = wait_for_an_element_with_partial_link_text_exists(browser, setup_election_key_link_label)
setup_election_key_link_element.click()
wait_a_bit()
# She clicks on the "threshold mode" link
threshold_mode_link_label = "threshold mode"
threshold_mode_link_element = wait_for_an_element_with_partial_link_text_exists(browser, threshold_mode_link_label)
threshold_mode_link_element.click()
wait_a_bit()
# She adds `NUMBER_OF_TRUSTEES` trustees (their email address), and remembers the link she will send to each trustee
# (The threshold field appears only after user has added the first trustee)
self.links_for_trustees = []
email_address_field_css_selector = "#main form input[name=__co_eliom_id]" # TODO: Maybe we should edit Belenios' HTML template to rename `__co_eliom_id` to something more explicit, like `__co_eliom_new_trustee_email_address`
submit_button_css_selector = "#main form input[type=submit][value=Add]"
for idx, email_address in enumerate(settings.TRUSTEES_EMAIL_ADDRESSES):
email_address_field_element = wait_for_element_exists(browser, email_address_field_css_selector)
email_address_field_element.clear()
email_address_field_element.send_keys(email_address)
submit_button_element = wait_for_element_exists(browser, submit_button_css_selector)
submit_button_element.click()
trustee_link_css_selector = "#main table tbody tr:nth-of-type(" + str(idx + 2) + ") td:nth-of-type(3) a"
trustee_link_element = wait_for_element_exists_and_has_non_empty_content(browser, trustee_link_css_selector)
self.links_for_trustees.append(trustee_link_element.get_attribute('href'))
wait_a_bit()
# In the field next to "Threshold:", she types the value of `U` (aka `TRUSTEES_THRESHOLD_VALUE`)
threshold_value_field_css_selector = "#main form input[name=__co_eliom_threshold]"
threshold_value_field_element = wait_for_element_exists(browser, threshold_value_field_css_selector, settings.EXPLICIT_WAIT_TIMEOUT)
threshold_value_field_value = settings.TRUSTEES_THRESHOLD_VALUE
threshold_value_field_element.clear()
threshold_value_field_element.send_keys(threshold_value_field_value)
wait_a_bit()
# She clicks on the "Set" button
submit_button_css_selector = "#main form input[type=submit][value=Set]"
submit_button_element = wait_for_element_exists(browser, submit_button_css_selector)
submit_button_element.click()
wait_a_bit()
# She sends to each trustee an email containing their own link
subject = "Link to generate the decryption key"
content_format = """\
Dear trustee,
You will find below the link to generate your private decryption key, used to tally the election.
{link_for_trustee}
Here's the instructions:
1. click on the link
2. click on "generate a new key pair"
3. your private key will appear in another window or tab. Make sure
you SAVE IT properly otherwise it will not possible to tally and the
election will be canceled.
4. in the first window, click on "submit" to send the public part of
your key, used encrypt the votes. For verification purposes, you
should save this part (that starts with "pok" "challenge"), for
example sending yourself an email.
Regarding your private key, it is crucial you save it (otherwise the
election will be canceled) and store it securely (if your private key
is known together with the private keys of the other trustees, then
vote privacy is no longer guaranteed). We suggest two options:
1. you may store the key on a USB stick and store it in a safe.
2. Or you may simply print it and store it in a safe.
Of course, more cryptographic solutions are welcome as well.
Thank you for your help,
--
The election administrator.\
"""
for idx, trustee_email_address in enumerate(settings.TRUSTEES_EMAIL_ADDRESSES):
custom_content = content_format.format(link_for_trustee=self.links_for_trustees[idx])
self.fake_sent_emails_manager.send_email(settings.ADMINISTRATOR_EMAIL_ADDRESS, trustee_email_address, subject, custom_content)
# Optionnaly, she logs out
# log_out(browser)
# She closes the window
browser.quit()
def test_scenario_3_manual_vote_with_threshold(self):
console_log("### Running test method BeleniosTestElectionScenario3::test_scenario_3_manual_vote_with_threshold()")
console_log("### Starting step: administrator_starts_creation_of_manual_election")
self.administrator_starts_creation_of_manual_election()
console_log("### Step complete: administrator_starts_creation_of_manual_election")
console_log("### Starting step: credential_authority_sends_credentials_to_voters")
self.credential_authority_sends_credentials_to_voters()
console_log("### Step complete: credential_authority_sends_credentials_to_voters")
console_log("### Starting step: administrator_invites_trustees_and_sets_threshold")
self.administrator_invites_trustees_and_sets_threshold()
console_log("### Step complete: administrator_invites_trustees_and_sets_threshold")
# TODO
# console_log("### Starting step: trustees_generate_election_private_keys")
# self.trustees_generate_election_private_keys()
# console_log("### Step complete: trustees_generate_election_private_keys")
# console_log("### Starting step: administrator_completes_creation_of_election")
# self.administrator_completes_creation_of_election()
# console_log("### Step complete: administrator_completes_creation_of_election")
# console_log("### Starting step: verify_election_consistency using `belenios_tool verify` (0)")
# verify_election_consistency(self.election_id)
# console_log("### Step complete: verify_election_consistency using `belenios_tool verify` (0)")
# console_log("### Starting step: all_voters_vote_in_sequences")
# self.all_voters_vote_in_sequences()
# console_log("### Step complete: all_voters_vote_in_sequences")
# console_log("### Starting step: verify_election_consistency using `belenios_tool verify` (1)")
# verify_election_consistency(self.election_id)
# console_log("### Step complete: verify_election_consistency using `belenios_tool verify` (1)")
# console_log("### Starting step: create_election_data_snapshot (0)")
# snapshot_folder = create_election_data_snapshot(self.election_id)
# console_log("### Step complete: create_election_data_snapshot (0)")
# try:
# console_log("### Starting step: some_voters_revote")
# self.some_voters_revote()
# console_log("### Step complete: some_voters_revote")
# console_log("### Starting step: verify_election_consistency using `belenios_tool verify-diff` (0)")
# verify_election_consistency(self.election_id, snapshot_folder)
# finally:
# delete_election_data_snapshot(snapshot_folder)
# console_log("### Step complete: verify_election_consistency using `belenios_tool verify-diff` (0)")
# console_log("### Starting step: verify_election_consistency using `belenios_tool verify` (2)")
# verify_election_consistency(self.election_id)
# console_log("### Step complete: verify_election_consistency using `belenios_tool verify` (2)")
# console_log("### Starting step: administrator_starts_tallying_of_election")
# self.administrator_starts_tallying_of_election()
# console_log("### Step complete: administrator_starts_tallying_of_election")
# console_log("### Starting step: trustees_do_partial_decryption")
# self.trustees_do_partial_decryption()
# console_log("### Step complete: trustees_do_partial_decryption")
# console_log("### Starting step: administrator_finishes_tallying_of_election")
# self.administrator_finishes_tallying_of_election()
# console_log("### Step complete: administrator_finishes_tallying_of_election")
# console_log("### Starting step: verify_election_consistency using `belenios_tool verify` (3)")
# verify_election_consistency(self.election_id)
# console_log("### Step complete: verify_election_consistency using `belenios_tool verify` (3)")
if __name__ == "__main__":
random_seed = os.getenv('RANDOM_SEED', None)
if not random_seed:
random_seed = random.randrange(sys.maxsize)
console_log("Python random seed being used:", random_seed)
random.seed(random_seed)
if os.getenv('USE_HEADLESS_BROWSER', None):
settings.USE_HEADLESS_BROWSER = bool(strtobool(os.getenv('USE_HEADLESS_BROWSER')))
settings.SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH = os.getenv('SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH', settings.SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH)
settings.WAIT_TIME_BETWEEN_EACH_STEP = float(os.getenv('WAIT_TIME_BETWEEN_EACH_STEP', settings.WAIT_TIME_BETWEEN_EACH_STEP))
settings.EXPLICIT_WAIT_TIMEOUT = int(os.getenv('EXPLICIT_WAIT_TIMEOUT', settings.EXPLICIT_WAIT_TIMEOUT))
settings.NUMBER_OF_INVITED_VOTERS = int(os.getenv('NUMBER_OF_INVITED_VOTERS', settings.NUMBER_OF_INVITED_VOTERS))
settings.NUMBER_OF_VOTING_VOTERS = int(os.getenv('NUMBER_OF_VOTING_VOTERS', settings.NUMBER_OF_VOTING_VOTERS))
settings.NUMBER_OF_REVOTING_VOTERS = int(os.getenv('NUMBER_OF_REVOTING_VOTERS', settings.NUMBER_OF_REVOTING_VOTERS))
settings.NUMBER_OF_REGENERATED_PASSWORD_VOTERS = int(os.getenv('NUMBER_OF_REGENERATED_PASSWORD_VOTERS', settings.NUMBER_OF_REGENERATED_PASSWORD_VOTERS))
settings.ADMINISTRATOR_USERNAME = os.getenv('ADMINISTRATOR_USERNAME', settings.ADMINISTRATOR_USERNAME)
settings.ADMINISTRATOR_PASSWORD = os.getenv('ADMINISTRATOR_PASSWORD', settings.ADMINISTRATOR_PASSWORD)
settings.ELECTION_TITLE = os.getenv('ELECTION_TITLE', settings.ELECTION_TITLE)
settings.ELECTION_DESCRIPTION = os.getenv('ELECTION_DESCRIPTION', settings.ELECTION_DESCRIPTION)
settings.INITIATOR_CONTACT = os.getenv('INITIATOR_CONTACT', settings.INITIATOR_CONTACT)
settings.BROWSER_DOWNLOAD_FOLDER = os.getenv('BROWSER_DOWNLOAD_FOLDER', settings.BROWSER_DOWNLOAD_FOLDER)
settings.ADMINISTRATOR_EMAIL_ADDRESS = os.getenv('ADMINISTRATOR_EMAIL_ADDRESS', settings.ADMINISTRATOR_EMAIL_ADDRESS)
settings.CREDENTIAL_AUTHORITY_EMAIL_ADDRESS = os.getenv('CREDENTIAL_AUTHORITY_EMAIL_ADDRESS', settings.CREDENTIAL_AUTHORITY_EMAIL_ADDRESS)
settings.NUMBER_OF_TRUSTEES = int(os.getenv('NUMBER_OF_TRUSTEES', settings.NUMBER_OF_TRUSTEES))
# TODO: settings.TRUSTEES_EMAIL_ADDRESSES (it cannot be manipulated the same way because it is an array)
settings.TRUSTEES_THRESHOLD_VALUE = os.getenv('TRUSTEES_THRESHOLD_VALUE', settings.TRUSTEES_THRESHOLD_VALUE)
console_log("USE_HEADLESS_BROWSER:", settings.USE_HEADLESS_BROWSER)
console_log("SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH:", settings.SENT_EMAILS_TEXT_FILE_ABSOLUTE_PATH)
console_log("WAIT_TIME_BETWEEN_EACH_STEP:", settings.WAIT_TIME_BETWEEN_EACH_STEP)
console_log("EXPLICIT_WAIT_TIMEOUT:", settings.EXPLICIT_WAIT_TIMEOUT)
console_log("NUMBER_OF_INVITED_VOTERS:", settings.NUMBER_OF_INVITED_VOTERS)
console_log("NUMBER_OF_VOTING_VOTERS:", settings.NUMBER_OF_VOTING_VOTERS)
console_log("NUMBER_OF_REVOTING_VOTERS:", settings.NUMBER_OF_REVOTING_VOTERS)
console_log("NUMBER_OF_REGENERATED_PASSWORD_VOTERS:", settings.NUMBER_OF_REGENERATED_PASSWORD_VOTERS)
console_log("ELECTION_TITLE:", settings.ELECTION_TITLE)
console_log("ELECTION_DESCRIPTION:", settings.ELECTION_DESCRIPTION)
console_log("INITIATOR_CONTACT:", settings.INITIATOR_CONTACT)
console_log("BROWSER_DOWNLOAD_FOLDER:", settings.BROWSER_DOWNLOAD_FOLDER)
console_log("ADMINISTRATOR_EMAIL_ADDRESS:", settings.ADMINISTRATOR_EMAIL_ADDRESS)
console_log("CREDENTIAL_AUTHORITY_EMAIL_ADDRESS:", settings.CREDENTIAL_AUTHORITY_EMAIL_ADDRESS)
console_log("TRUSTEES_EMAIL_ADDRESSES:", settings.TRUSTEES_EMAIL_ADDRESSES)
console_log("NUMBER_OF_TRUSTEES:", settings.NUMBER_OF_TRUSTEES)
console_log("TRUSTEES_THRESHOLD_VALUE:", settings.TRUSTEES_THRESHOLD_VALUE)
unittest.main()
......@@ -381,7 +381,7 @@ def log_out(browser):
wait_for_element_exists_and_contains_expected_text(browser, "#main button", "Start", settings.EXPLICIT_WAIT_TIMEOUT)
def administrator_starts_creation_of_election(browser, manual_credential_management=False, election_title=None, election_description=None):
def administrator_starts_creation_of_election(browser, manual_credential_management=False, election_title=None, election_description=None, initiator_contact=None):
"""
Initial browser (required) state: administrator has just logged in
Final browser state: on the "Preparation of election" page
......@@ -391,8 +391,10 @@ def administrator_starts_creation_of_election(browser, manual_credential_managem
- She picks the Credential management method she wants (function paramenter `manual_credential_management`)
(- She keeps default value for Authentication method: it is Password, not CAS)
- She clicks on the "Proceed" button (this redirects to the "Preparation of election" page)
- She changes values of fields name and description of the election
- In the "Name and description of the election" section, she changes values of fields name and description of the election
- She clicks on the "Save changes button" (the one that is next to the election description field)
- In "Contact" section, she changes the value of "contact" field
- She clicks on the "Save changes" button (the one that is in the "Contact" section)
"""
if election_title is None:
......@@ -401,6 +403,9 @@ def administrator_starts_creation_of_election(browser, manual_credential_managem
if election_description is None:
election_description = settings.ELECTION_DESCRIPTION
if initiator_contact is None:
initiator_contact = settings.INITIATOR_CONTACT
# She clicks on the "Prepare a new election" link
create_election_link_expected_content = "Prepare a new election"
links_css_selector = "#main a"
......@@ -424,7 +429,7 @@ def administrator_starts_creation_of_election(browser, manual_credential_managem
wait_a_bit()
# She changes values of fields name and description of the election
# In the "Name and description of the election" section, she changes values of fields name and description of the election
election_name_field_css_selector = "#main form input[name=__co_eliom_name]"
election_name_field_element = wait_for_element_exists(browser, election_name_field_css_selector, settings.EXPLICIT_WAIT_TIMEOUT)
election_name_field_value = election_title
......@@ -441,13 +446,29 @@ def administrator_starts_creation_of_election(browser, manual_credential_managem
wait_a_bit()
# She clicks on the "Save changes button" (the one that is next to the election description field)
save_changes_button_css_selector = "#main > div:nth-child(1) form input[type=submit]" # Warning: form:nth-child(1) selects another form
# She clicks on the "Save changes" button (the one that is next to the election description field)
save_changes_button_css_selector = "#main > div:nth-of-type(1) form input[type=submit]" # Warning: form:nth-child(1) selects another form
save_changes_button_element = browser.find_element_by_css_selector(save_changes_button_css_selector)
save_changes_button_element.click()
wait_a_bit()
# In "Contact" section, she changes the value of "contact" field
election_contact_field_css_selector = "#main form input[name=__co_eliom_contact]"
election_contact_field_element = browser.find_element_by_css_selector(election_contact_field_css_selector)
election_contact_field_value = initiator_contact
election_contact_field_element.clear()
election_contact_field_element.send_keys(election_contact_field_value)
wait_a_bit()
# She clicks on the "Save changes" button (the one that is in the "Contact" section)
contact_section_save_changes_button_css_selector = "#main > div:nth-of-type(3) form input[type=submit]" # Warning: form:nth-child(1) selects another form
contact_section_save_changes_button_element = browser.find_element_by_css_selector(contact_section_save_changes_button_css_selector)
contact_section_save_changes_button_element.click()
wait_a_bit()
def administrator_edits_election_questions(browser):
"""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment