def add_voters(cls, voters_list): """ This method adds specified voters to the database. It also sends the voting token to every voter using the provided e-mail address. """ database = DynamoDBManager() email_client = boto3.client("ses", region_name="eu-west-1") sender_email = database.get_parameter("sender_email") for voter in voters_list: response = database.add_voter(voter["student_id"], voter["student_email"]) message = """ Congratulations! You have been successfully registered for the upcoming election! Your personal voter code is: {token}""".format(token=response["token"]) email_client.send_email( Source=sender_email, Destination={"ToAddresses": [ voter["student_email"], ]}, Message={ "Subject": { "Data": "Your personal voter code" }, "Body": { "Text": { "Data": message } } }) response = respond( "Voter {voter} successfully added to the database!".format( voter=voter["student_id"]), 200) return response
def add_candidates(cls, candidates_list): """ This method adds specified candidates to the database. """ for candidate in candidates_list: database = DynamoDBManager() response = database.add_candidate(candidate["candidate_full_name"], candidate["candidate_email"], candidate["candidate_page_link"]) return response
def test_mark_voter(self, mock_boto3_resource): manager = DynamoDBManager() id = "some id" status = "true" manager.mark_voter(id, status) manager.voters_table.update_item.assert_called_with( Key={"student_id": id}, UpdateExpression="SET #voted = :voted_flag", ExpressionAttributeValues={":voted_flag": "true"}, ExpressionAttributeNames={"#voted": "voted"})
def test_set_parameter(self, mock_boto3_resource): manager = DynamoDBManager() parameter = "some parameter" value = "some value" manager.set_parameter(parameter, value) manager.parameters_table.put_item.assert_called_with( Item={ "parameter": str(parameter), "value": str(value) })
def test_add_voter(self, mock_boto3_resource, mock_randint): manager = DynamoDBManager() mock_randint.return_value = "random" id = "some id" email = "some email" manager.add_voter(id, email) manager.voters_table.put_item.assert_called_with(Item={ "student_id": id, "email": email, "token": "random", "voted": "false" })
def test_add_candidate(self, mock_boto3_resource): manager = DynamoDBManager() candidate_full_name = "Person Personson" candidate_email = "some email" candidate_link = "some link" manager.add_candidate(candidate_full_name, candidate_email, candidate_link) manager.candidates_table.put_item.assert_called_with( Item={ "full_name": candidate_full_name, "candidate_email": candidate_email, "candidate_page_link": candidate_link })
def __init__(self, request_id="NONE"): self.request_id = request_id # self.api_root = os.environ.get("api_root") self.events_list = [ "ADD_VOTERS", "ADD_CANDIDATES", "GET_CANDIDATES", "LOCK", "START", "CAST_VOTE" ] self.handlers = { "ADD_VOTERS": self.command_add_voters, "ADD_CANDIDATES": self.command_add_candidates, "GET_CANDIDATES": self.command_get_candidates, "LOCK": self.command_lock, "START": self.command_start, "CAST_VOTE": self.command_cast_vote } self.db_manager = DynamoDBManager() self.admin_token = self.db_manager.get_parameter("admin_token") self.locked = self.db_manager.get_parameter("locked") self.started = self.db_manager.get_parameter("started")
def test_add_vote(self, mock_boto3_resource, mock_boto3_client): manager = DynamoDBManager() voter_id = "1337" event_id = "1111" candidate = "Person Personson" # Case 1: everything is normal --------------------------------------------------------------------------------- response = manager.add_vote(voter_id, event_id, candidate) assert response == respond( 'Congratulations! You have successfully cast your vote for the candidate {candidate}!' .format(candidate=candidate), 200) # -------------------------------------------------------------------------------------------------------------- # Case 2: no such candidate ------------------------------------------------------------------------------------ manager.get_candidate = (lambda candidate_name: None) response = manager.add_vote(voter_id, event_id, candidate) assert response == respond( "NO SUCH CANDIDATE, PLEASE ENTER THE CORRECT FULL NAME", 404)
class EventProcessor: def __init__(self, request_id="NONE"): self.request_id = request_id # self.api_root = os.environ.get("api_root") self.events_list = [ "ADD_VOTERS", "ADD_CANDIDATES", "GET_CANDIDATES", "LOCK", "START", "CAST_VOTE" ] self.handlers = { "ADD_VOTERS": self.command_add_voters, "ADD_CANDIDATES": self.command_add_candidates, "GET_CANDIDATES": self.command_get_candidates, "LOCK": self.command_lock, "START": self.command_start, "CAST_VOTE": self.command_cast_vote } self.db_manager = DynamoDBManager() self.admin_token = self.db_manager.get_parameter("admin_token") self.locked = self.db_manager.get_parameter("locked") self.started = self.db_manager.get_parameter("started") # EVENT PROCESSING --------------------------------------------------------- def process_event(self, payload): event_type = self._determine_event(payload) if event_type != "UNKNOWN EVENT TYPE": return self._delegate_event(event_type, payload) else: return respond("EVENT VALIDATION FAILED", 400) def _determine_event(self, payload): # Determines type of the event, checks validity of the payload according to schema # At this stage, validity of the token is not checked, we just determine the type of the event determined_type = "UNKNOWN EVENT TYPE" for event_type in self.events_list: try: result = validate(instance=payload, schema=schema_dict[event_type + "_SCHEMA"]) determined_type = event_type except ValidationError as e: continue return determined_type def _delegate_event(self, event_type, payload): # Delegates the event to the handler response = self.handlers[event_type](payload) return response # COMMAND HANDLERS --------------------------------------------------------- def command_add_voters(self, payload): if self.started == "true": return respond("VOTING ALREADY STARTED", 403) if payload["administrator_token"] == self.admin_token: response = VotersManager.add_voters(payload["voters_to_add"]) return response else: return respond("WRONG TOKEN, COMMAND REJECTED", 403) def command_add_candidates(self, payload): if self.started == "true": return respond("VOTING ALREADY STARTED", 403) if payload["administrator_token"] == self.admin_token: response = CandidatesManager.add_candidates( payload["candidates_to_add"]) return response else: return respond("WRONG TOKEN, COMMAND REJECTED", 403) def command_get_candidates(self, payload): # Note that no token is required for this command if self.started == "false": return respond("VOTING NOT STARTED YET", 403) return respond(str(self.db_manager.get_candidates()), 200) def command_lock(self, payload): if self.locked == "true": return respond("SYSTEM ALREADY LOCKED", 403) if payload["administrator_token"] == self.admin_token: self.db_manager.set_parameter(parameter="locked", value="true") return respond("SYSTEM LOCKED", 200) else: return respond("WRONG TOKEN, COMMAND REJECTED", 403) def command_start(self, payload): if self.locked == "false": return respond("LOCK THE SYSTEM FIRST", 403) if self.started == "true": return respond("VOTING ALREADY STARTED", 403) if payload["administrator_token"] == self.admin_token: self.db_manager.set_parameter(parameter="started", value="true") return respond("VOTING STARTED", 200) else: return respond("WRONG TOKEN, COMMAND REJECTED", 403) def command_cast_vote(self, payload): if self.started != "true": return respond("VOTING NOT STARTED YET", 403) voter = self.db_manager.get_voter(id=payload["voter_id"]) if voter["token"] == payload["voter_token"] and voter[ "voted"] == "false": response = self.db_manager.add_vote( voter_id=payload["voter_id"], event_id=self.request_id, candidate=payload["candidate_full_name"]) return response else: return respond("WRONG TOKEN OR ALREADY VOTED, COMMAND REJECTED", 403)
def test_get_parameter(self, mock_boto3_resource): manager = DynamoDBManager() parameter = "some parameter" manager.get_parameter(parameter) manager.parameters_table.get_item.assert_called_with( Key={"parameter": parameter})
def test_get_candidates(self, mock_boto3_resource): manager = DynamoDBManager() manager.get_candidates() manager.candidates_table.scan.assert_called()
def test_get_candidate(self, mock_boto3_resource): manager = DynamoDBManager() candidate_full_name = "Person Personson" manager.get_candidate(candidate_full_name) manager.candidates_table.get_item.assert_called_with( Key={"full_name": candidate_full_name})
def test_get_voter(self, mock_boto3_resource): manager = DynamoDBManager() id = "some id" manager.get_voter(id) manager.voters_table.get_item.assert_called_with( Key={"student_id": id})