Пример #1
0
    async def get_poll_registrations(self, request):
        private_key, public_key, user = await self._authorize(request)
        election_id = request.match_info.get('electionId', '')

        if election_id == '':
            raise ApiBadRequest(
                'The election ID is a required query string parameter')

        poll_book = await self._database.fetch_poll_book(
            election_id=election_id)

        if poll_book is None:
            raise ApiNotFound('No voters with the election id '
                              '{} was not found'.format(election_id))

        election = await self._database.fetch_election_resource(
            election_id=election_id)

        if election is None:
            raise ApiNotFound('Election with the election id '
                              '{} was not found'.format(election_id))

        if election.get('admin_id') != user.get('voter_id'):
            raise ApiBadRequest(
                'User is not the owner of the election with the id '
                '{} .'.format(election_id))

        return json_response(poll_book)
Пример #2
0
    async def count_poll_registrations(self, request):
        private_key, public_key, user = await self._authorize(request)
        election_id = request.match_info.get('electionId', '')

        if election_id == '':
            raise ApiBadRequest(
                'The election ID is a required query string parameter')

        count_poll_book = await self._database.count_poll_book(
            election_id=election_id)

        election = await self._database.fetch_election_resource(
            election_id=election_id)

        if election is None:
            raise ApiNotFound('Election with the election id '
                              '{} was not found'.format(election_id))

        if election.get('results_permission') != 'PUBLIC':

            poll_registration = await self._database.fetch_poll_book_registration(
                voter_id=user.get('voter_id'), election_id=election_id)

            if poll_registration is None and election.get(
                    'admin_id') != user.get('voter_id'):
                raise ApiBadRequest(
                    'Voter is not registered in the poll book of the election with the id '
                    '{} .'.format(election_id))

        return json_response(count_poll_book)
Пример #3
0
    async def update_poll_book_status(self, request):
        private_key, public_key, user = await self._authorize(request)
        voter_id = request.match_info.get('voterId', '')

        if voter_id == '':
            raise ApiBadRequest(
                'The voter ID is a required query string parameter')

        election_id = request.match_info.get('electionId', '')

        if election_id == '':
            raise ApiBadRequest(
                'The election ID is a required query string parameter')

        voter_poll_book = await self._database.fetch_poll_book_registration(
            election_id=election_id, voter_id=voter_id)

        if voter_poll_book is None:
            raise ApiNotFound('Voter with the voter id '
                              '{} was not found'.format(voter_id))

        election = await self._database.fetch_election_resource(
            election_id=election_id)

        if election is None:
            raise ApiNotFound('Election with the election id '
                              '{} was not found'.format(election_id))

        current_time = get_time()

        if election.get('start_timestamp') < current_time:
            raise ApiBadRequest('Election with the election id '
                                '{} already start.'.format(election_id))

        if election.get('admin_id') != user.get('voter_id'):
            raise ApiBadRequest(
                'User is not the owner of the election with the id '
                '{} .'.format(election_id))

        if voter_poll_book.get('status') is True:
            status = 0
        else:
            status = 1

        await self._messenger.send_update_voter_poll_book_status_transaction(
            private_key=private_key,
            voter_id=voter_id,
            name=voter_poll_book.get('name'),
            election_id=election_id,
            status=status,
            timestamp=get_time())

        return json_response(
            {'data': 'Update Poll Registration Status transaction submitted'})
Пример #4
0
    async def get_election(self, request):
        private_key, public_key, user = await self._authorize(request)

        election_id = request.match_info.get('electionId', '')

        if election_id == '':
            raise ApiBadRequest(
                'The election ID is a required query string parameter')

        if 'asAdmin' in request.rel_url.query:
            election = await self._database.fetch_election_with_can_vote_resource_admin(
                voter_id=user.get('voter_id'), election_id=election_id)
        else:
            election = await self._database.fetch_election_with_can_vote_resource(
                voter_id=user.get('voter_id'), election_id=election_id)

        if election is None:
            raise ApiNotFound('Election with the election id '
                              '{} was not found'.format(election_id))

        if election.get('results_permission') != 'PUBLIC':
            if election.get('can_vote') is False and election.get(
                    'admin_id') != user.get('voter_id'):
                raise ApiForbidden(
                    'Voter is not registered in the poll book of the election with the id '
                    '{}.'.format(election_id))

        return json_response(election)
    async def _send_and_wait_for_commit(self, batch):
        # Send transaction to validator
        submit_request = client_batch_submit_pb2.ClientBatchSubmitRequest(
            batches=[batch])
        await self._connection.send(
            validator_pb2.Message.CLIENT_BATCH_SUBMIT_REQUEST,
            submit_request.SerializeToString())

        # Send status request to validator
        batch_id = batch.header_signature
        status_request = client_batch_submit_pb2.ClientBatchStatusRequest(
            batch_ids=[batch_id], wait=True)
        validator_response = await self._connection.send(
            validator_pb2.Message.CLIENT_BATCH_STATUS_REQUEST,
            status_request.SerializeToString())

        # Parse response
        status_response = client_batch_submit_pb2.ClientBatchStatusResponse()
        status_response.ParseFromString(validator_response.content)
        status = status_response.batch_statuses[0].status
        if status == client_batch_submit_pb2.ClientBatchStatus.INVALID:
            error = status_response.batch_statuses[0].invalid_transactions[0]
            raise ApiBadRequest(error.message)
        elif status == client_batch_submit_pb2.ClientBatchStatus.PENDING:
            raise ApiInternalError('Transaction submitted but timed out')
        elif status == client_batch_submit_pb2.ClientBatchStatus.UNKNOWN:
            raise ApiInternalError('Something went wrong. Try again later')
    async def create_agent(self, request):
        body = await decode_request(request)
        required_fields = ['email', 'name', 'password']
        validate_fields(required_fields, body)

        public_key, private_key = self._messenger.get_new_key_pair()
        email = body.get('email')

        await self._messenger.send_create_agent_transaction(
            private_key=private_key,
            email=email,
            name=body.get('name'),
            timestamp=get_time())

        encrypted_private_key = encrypt_private_key(
            request.app['aes_key'], public_key, private_key)
        hashed_password = hash_password(body.get('password'))

        try:
            await self._database.create_auth_entry(email,
                                               public_key, encrypted_private_key, hashed_password)
        except IntegrityError:
            raise ApiBadRequest('The Email address has already been used!')

        token = generate_auth_token(
            request.app['secret_key'], public_key)

        return json_response({'authorization': token})
Пример #7
0
    async def get_vote_election(self, request):
        private_key, public_key, user = await self._authorize(request)
        voter_id = request.match_info.get('voterId', '')

        if voter_id == '':
            raise ApiBadRequest(
                'The voter ID is a required query string parameter')

        election_id = request.match_info.get('electionId', '')

        if election_id == '':
            raise ApiBadRequest(
                'The election ID is a required query string parameter')

        if user.get('voter_id') != voter_id:
            raise ApiForbidden('Admin must be the authenticated one')

        vote = await self._database.fetch_my_vote__election_resource(
            voter_id=voter_id, election_id=election_id)

        return json_response(vote)
Пример #8
0
    async def list_elections_current(self, request):
        private_key, public_key, user = await self._authorize(request)
        voterId = request.match_info.get('voterId', '')

        if voterId == '':
            raise ApiBadRequest(
                'The voter ID is a required query string parameter')

        if user.get('voter_id') != voterId:
            raise ApiForbidden('Admin must be the authenticated one')

        current_elections_list = await self._database.fetch_current_elections_resources(
            voterId, get_time())
        return json_response(current_elections_list)
Пример #9
0
    async def get_voting_option(self, request):
        private_key, public_key, user = await self._authorize(request)
        voting_option_id = request.match_info.get('votingOptionId', '')

        if voting_option_id == '':
            raise ApiBadRequest(
                'The voting option ID is a required query string parameter')

        voting_option = await self._database.fetch_voting_option_resource(
            voting_option_id=voting_option_id)

        if voting_option is None:
            raise ApiNotFound('No voting options with the id '
                              '{} was not found'.format(voting_option_id))

        return json_response(voting_option)
Пример #10
0
    async def update_voter_type(self, request):
        private_key, public_key, user = await self._authorize(request)
        body = await decode_request(request)
        required_fields = ['type']
        validate_fields(required_fields, body)

        voter_id = request.match_info.get('voterId', '')
        if voter_id == '':
            raise ApiBadRequest(
                'The voter ID is a required query string parameter')

        if user.get('type') != 'SUPERADMIN':
            raise ApiForbidden('Forbidden')

        voter = await self._database.fetch_voter_resource(voter_id=voter_id)

        if voter is None:
            raise ApiNotFound('No voter found')

        if body.get('type') == 'ADMIN' and (voter.get('type') == 'ADMIN' or
                                            voter.get('type') == 'SUPERADMIN'):
            raise ApiConflict(
                'Voter {} is already an admin or superadmin'.format(voter_id))
        elif body.get('type') == 'VOTER' and voter.get('type') == 'VOTER':
            raise ApiConflict('Voter {} is already a voter. '.format(voter_id))

        auth_info = await self._database.fetch_auth_resource(
            public_key=voter.get('public_key'))
        voter_private_key = decrypt_private_key(
            request.app['aes_key'], voter.get('public_key'),
            auth_info.get('encrypted_private_key'))

        await self._messenger.send_update_voter_transaction(
            private_key=voter_private_key,
            voter_id=voter_id,
            public_key=voter.get('public_key'),
            name=voter.get('name'),
            created_at=get_time(),
            type=body.get('type'))

        return json_response({
            'voter': {
                'voter_id': voter_id,
                'name': voter.get('name'),
                'type': 'ADMIN'
            }
        })
Пример #11
0
    async def list_admin_elections(self, request):
        private_key, public_key, user = await self._authorize(request)

        voter_id = request.match_info.get('voterId', '')

        if voter_id == '':
            raise ApiBadRequest(
                'The voter ID is a required query string parameter')

        if user.get('voter_id') != voter_id:
            raise ApiForbidden('Admin must be the authenticated one')

        if user.get('type') != 'ADMIN' and user.get('type') != 'SUPERADMIN':
            raise ApiForbidden('Voter must be an admin or superadmin')

        admin_elections_list = await self._database.fetch_admin_elections_resources(
            user.get('voter_id'))
        return json_response(admin_elections_list)
Пример #12
0
    async def get_vote(self, request):
        private_key, public_key, user = await self._authorize(request)
        vote_id = request.match_info.get('voteId', '')

        if vote_id == '':
            raise ApiBadRequest(
                'The vote ID is a required query string parameter')

        vote = await self._database.fetch_vote_resource(vote_id=vote_id)

        if vote is None:
            raise ApiNotFound('Vote with the vote id '
                              '{} was not found'.format(vote_id))

        election_id = vote.get('election_id')
        election = await self._database.fetch_election_resource(
            election_id=election_id)

        if election is None:
            raise ApiNotFound('Election with the election id '
                              '{} was not found'.format(election_id))

        return json_response(vote)
Пример #13
0
def validate_fields(required_fields, body):
    for field in required_fields:
        if body.get(field) is None:
            raise ApiBadRequest("'{}' parameter is required".format(field))
Пример #14
0
async def decode_request(request):
    try:
        return await request.json()
    except JSONDecodeError:
        raise ApiBadRequest('Improper JSON format')
Пример #15
0
    async def update_vote(self, request):
        private_key, public_key, user = await self._authorize(request)
        body = await decode_request(request)
        required_fields = ['voting_option_id']
        validate_fields(required_fields, body)

        vote_id = request.match_info.get('voteId', '')

        if vote_id == '':
            raise ApiBadRequest(
                'The vote ID is a required query string parameter')

        vote = await self._database.fetch_vote_resource(vote_id=vote_id)
        election_id = vote.get('election_id')

        if vote is None:
            raise ApiNotFound('Vote with the vote id '
                              '{} was not found'.format(vote_id))

        if vote.get('voting_option_id') == body.get('voting_option_id'):
            raise ApiBadRequest('Vote must be different.')

        election = await self._database.fetch_election_resource(
            election_id=election_id)

        if election is None:
            raise ApiNotFound('Election with the election id '
                              '{} was not found'.format(election_id))

        if election.get('can_change_vote') == 0:
            raise ApiInternalError(
                'Election with the election id '
                '{} was not found don\'t permit to change vote'.format(
                    election_id))

        if election.get('can_change_vote') == 0:
            raise ApiInternalError(
                'Election with the election id '
                '{} was not found don\'t permit to change vote'.format(
                    election_id))

        current_time = get_time()

        if election.get('end_timestamp') < current_time or election.get(
                'start_timestamp') > current_time:
            raise ApiBadRequest('Not in election time.'.format())

        if election.get('admin_id') == user.get('voter_id'):
            raise ApiBadRequest(
                'User is not the owner of the election with the id '
                '{} .'.format(election_id))

        new_voting_option_id = body.get('voting_option_id')
        old_voting_option_id = vote.get('voting_option_id')

        old_num_vote = await self._database.fetch_voting_option_num_vote_resource(
            voting_option_id=old_voting_option_id)
        new_num_vote = await self._database.fetch_voting_option_num_vote_resource(
            voting_option_id=new_voting_option_id)
        num_votes_remove = old_num_vote.get('num_votes') - 1
        num_votes_update = new_num_vote.get('num_votes') + 1

        await self._messenger.send_update_vote_transaction(
            private_key=private_key,
            vote_id=vote_id,
            timestamp=get_time(),
            voting_option_id=new_voting_option_id)

        # remove -1 to old voting option
        await self._database.update_voting_option_num_vote_resource(
            voting_option_id=old_voting_option_id, num_votes=num_votes_remove)

        # add +1 to new voting option
        await self._database.update_voting_option_num_vote_resource(
            voting_option_id=new_voting_option_id, num_votes=num_votes_update)

        return json_response({'data': 'Update Vote transaction submitted'})
Пример #16
0
    async def update_election(self, request):
        private_key, public_key, user = await self._authorize(request)
        body = await decode_request(request)
        election_id = request.match_info.get('electionId', '')

        if election_id == '':
            raise ApiBadRequest(
                'The election ID is a required query string parameter')

        election = await self._database.fetch_election_resource(
            election_id=election_id)

        if election is None:
            raise ApiNotFound('Election with the election id '
                              '{} was not found'.format(election_id))

        current_time = get_time()

        if election.get('start_timestamp') < current_time:
            raise ApiBadRequest('Election with the election id '
                                '{} already start.'.format(election_id))

        if election.get('admin_id') != user.get('voter_id'):
            raise ApiBadRequest(
                'User is not the owner of the election with the id '
                '{} .'.format(election_id))

        await self._messenger.send_update_election_transaction(
            private_key=private_key,
            election_id=election_id,
            name=body.get('name')
            if body.get('name') is not None else election.get('name'),
            description=body.get('description') if body.get('description')
            is not None else election.get('description'),
            start_timestamp=body.get('start_timestamp')
            if body.get('start_timestamp') is not None else
            election.get('start_timestamp'),
            end_timestamp=body.get('end_timestamp')
            if body.get('end_timestamp') is not None else
            election.get('end_timestamp'),
            results_permission=body.get('results_permission')
            if body.get('results_permission') is not None else
            election.get('results_permission'),
            can_change_vote=body.get('can_change_vote')
            if body.get('can_change_vote') is not None else
            election.get('can_change_vote'),
            can_show_realtime=body.get('can_show_realtime')
            if body.get('can_show_realtime') is not None else
            election.get('can_show_realtime'),
            admin_id=user.get('voter_id'),
            status=body.get('status')
            if body.get('status') is not None else election.get('status'),
            timestamp=get_time())

        if body.get('voting_options') is not None:
            for voting_option in body.get('voting_options'):
                voting_option_id = uuid.uuid1().hex

                await self._messenger.send_create_voting_option_transaction(
                    private_key=private_key,
                    voting_option_id=voting_option_id,
                    name=voting_option.get('name'),
                    description=voting_option.get('description'),
                    election_id=election_id,
                    status=1,
                    timestamp=get_time())

                await self._database.insert_voting_option_num_vote_resource(
                    voting_option_id=voting_option_id,
                    name=voting_option.get('name'),
                    election_id=election_id)
        if body.get('poll_book') is not None:
            for poll_book in body.get('poll_book'):
                await self._messenger.send_create_poll_registration_transaction(
                    private_key=private_key,
                    voter_id=poll_book.get('id'),
                    name=poll_book.get('name'),
                    election_id=election_id,
                    status=1,
                    timestamp=get_time())

        return json_response({'data': 'Update Election transaction submitted'})
Пример #17
0
    async def create_vote(self, request):
        body = await decode_request(request)
        required_fields = []
        validate_fields(required_fields, body)

        private_key, public_key, user = await self._authorize(request)
        voting_option_id = request.match_info.get('votingOptionId', '')

        if voting_option_id == '':
            raise ApiBadRequest(
                'The voting option ID is a required query string parameter')

        voter = await self._database.fetch_voter_resource(public_key=public_key
                                                          )

        if voter is None:
            raise ApiNotFound('Voter with the public_key '
                              '{} was not found'.format(public_key))

        voting_option = await self._database.fetch_voting_option_resource(
            voting_option_id=voting_option_id)
        vo_count_vote = await self._database.fetch_voting_option_num_vote_resource(
            voting_option_id=voting_option_id)

        if voting_option is None:
            raise ApiNotFound('Voting Option with the voting option id '
                              '{} was not found'.format(voting_option_id))

        election_id = voting_option.get('election_id')
        election = await self._database.fetch_election_resource(
            election_id=election_id)

        if election.get('status') == 0:
            raise ApiBadRequest('Election with the election id '
                                '{} is cancelled'.format(election_id))

        current_time = get_time()

        if election.get('end_timestamp') < current_time or election.get(
                'start_timestamp') > current_time:
            raise ApiBadRequest('Not in election time.'.format())

        poll_registration = await self._database.fetch_poll_book_registration(
            voter_id=user.get('voter_id'), election_id=election_id)

        if poll_registration is None:
            raise ApiBadRequest(
                'Voter is not registered in the poll book of the election with the id '
                '{} .'.format(election_id))

        num_votes_update = vo_count_vote.get('num_votes') + 1

        await self._messenger.send_create_vote_transaction(
            private_key=private_key,
            vote_id=uuid.uuid1().hex,
            timestamp=get_time(),
            voter_id=voter.get('voter_id'),
            election_id=voting_option.get('election_id'),
            voting_option_id=voting_option_id)

        await self._database.update_voting_option_num_vote_resource(
            voting_option_id=voting_option_id, num_votes=num_votes_update)

        return json_response({'data': 'Create vote transaction submitted'})