diff --git a/bigchaindb/backend/mongodb/query.py b/bigchaindb/backend/mongodb/query.py index 745ae731..4b3ab742 100644 --- a/bigchaindb/backend/mongodb/query.py +++ b/bigchaindb/backend/mongodb/query.py @@ -208,7 +208,9 @@ def count_backlog(conn): @register_query(MongoDBConnection) def write_vote(conn, vote): - return conn.db['votes'].insert_one(vote) + conn.db['votes'].insert_one(vote) + vote.pop('_id') + return vote @register_query(MongoDBConnection) diff --git a/bigchaindb/web/routes.py b/bigchaindb/web/routes.py index f6ee1886..041acc4e 100644 --- a/bigchaindb/web/routes.py +++ b/bigchaindb/web/routes.py @@ -5,6 +5,7 @@ from bigchaindb.web.views import ( statuses, transactions as tx, unspents, + votes, ) @@ -27,6 +28,7 @@ ROUTES_API_V1 = [ r('transactions/', tx.TransactionApi), r('transactions', tx.TransactionListApi), r('unspents/', unspents.UnspentListApi), + r('votes/', votes.VotesApi), ] diff --git a/bigchaindb/web/views/votes.py b/bigchaindb/web/views/votes.py new file mode 100644 index 00000000..68265b40 --- /dev/null +++ b/bigchaindb/web/views/votes.py @@ -0,0 +1,29 @@ +"""This module provides the blueprint for the votes API endpoints. + +For more information please refer to the documentation on ReadTheDocs: + - https://docs.bigchaindb.com/projects/server/en/latest/drivers-clients/ + http-client-server-api.html +""" +from flask import current_app +from flask_restful import Resource, reqparse + +from bigchaindb import backend + + +class VotesApi(Resource): + def get(self): + """API endpoint to get details about votes on a block. + + Return: + A list of votes voting for a block with ID ``block_id``. + """ + parser = reqparse.RequestParser() + parser.add_argument('block_id', type=str, required=True) + + args = parser.parse_args(strict=True) + + pool = current_app.config['bigchain_pool'] + with pool() as bigchain: + votes = list(backend.query.get_votes_by_block_id(bigchain.connection, args['block_id'])) + + return votes diff --git a/tests/backend/mongodb/test_queries.py b/tests/backend/mongodb/test_queries.py index 5b38e473..9f20cc9f 100644 --- a/tests/backend/mongodb/test_queries.py +++ b/tests/backend/mongodb/test_queries.py @@ -312,7 +312,8 @@ def test_write_vote(structurally_valid_vote): query.write_vote(conn, structurally_valid_vote) # retrieve the vote vote_db = conn.db.votes.find_one( - {'node_pubkey': structurally_valid_vote['node_pubkey']} + {'node_pubkey': structurally_valid_vote['node_pubkey']}, + {'_id': False} ) assert vote_db == structurally_valid_vote diff --git a/tests/web/test_votes.py b/tests/web/test_votes.py new file mode 100644 index 00000000..0f788fc4 --- /dev/null +++ b/tests/web/test_votes.py @@ -0,0 +1,69 @@ +import pytest + +from bigchaindb.models import Transaction + +VOTES_ENDPOINT = '/api/v1/votes' + + +@pytest.mark.bdb +@pytest.mark.usefixtures('inputs') +def test_get_votes_endpoint(b, client): + tx = Transaction.create([b.me], [([b.me], 1)]) + tx = tx.sign([b.me_private]) + + block = b.create_block([tx]) + b.write_block(block) + + # vote the block valid + vote = b.vote(block.id, b.get_last_voted_block().id, True) + b.write_vote(vote) + + res = client.get(VOTES_ENDPOINT + "?block_id=" + block.id) + assert vote == res.json[0] + assert len(res.json) == 1 + assert res.status_code == 200 + + +@pytest.mark.bdb +@pytest.mark.usefixtures('inputs') +def test_get_votes_endpoint_multiple_votes(b, client): + tx = Transaction.create([b.me], [([b.me], 1)]) + tx = tx.sign([b.me_private]) + + block = b.create_block([tx]) + b.write_block(block) + last_block = b.get_last_voted_block().id + # vote the block valid + vote_valid = b.vote(block.id, last_block, True) + b.write_vote(vote_valid) + + # vote the block valid + vote_invalid = b.vote(block.id, last_block, False) + b.write_vote(vote_invalid) + + res = client.get(VOTES_ENDPOINT + "?block_id=" + block.id) + assert len(res.json) == 2 + assert res.status_code == 200 + + +@pytest.mark.bdb +def test_get_votes_endpoint_returns_empty_list_not_found(client): + res = client.get(VOTES_ENDPOINT + "?block_id=") + assert [] == res.json + assert res.status_code == 200 + + res = client.get(VOTES_ENDPOINT + "?block_id=123") + assert [] == res.json + assert res.status_code == 200 + + +@pytest.mark.bdb +def test_get_votes_endpoint_returns_400_bad_query_params(client): + res = client.get(VOTES_ENDPOINT) + assert res.status_code == 400 + + res = client.get(VOTES_ENDPOINT + "?ts_id=123") + assert res.status_code == 400 + + res = client.get(VOTES_ENDPOINT + "?tx_id=123&block_id=123") + assert res.status_code == 400