diff --git a/setup.py b/setup.py index f7397f8..dc5a7e0 100644 --- a/setup.py +++ b/setup.py @@ -23,6 +23,6 @@ setup( 'aiosqlite==0.10.0', 'PyNaCl>=1.3.0', 'requests', - 'cython', # Not really needed anymore but w/e + 'cython', ] ) diff --git a/src/database/queries.py b/src/database/queries.py index 5e9f45d..7487b6a 100644 --- a/src/database/queries.py +++ b/src/database/queries.py @@ -118,12 +118,13 @@ def insert_comment(conn: sqlite3.Connection, claim_id: str, comment: str, parent with conn: conn.execute( """ - INSERT INTO COMMENT(CommentId, LbryClaimId, ChannelId, Body, ParentId, Timestamp, Signature, SigningTs) + INSERT INTO COMMENT(CommentId, LbryClaimId, ChannelId, Body, ParentId, + Timestamp, Signature, SigningTs) VALUES (?, ?, ?, ?, ?, ?, ?, ?) """, (comment_id, claim_id, channel_id, comment, parent_id, timestamp, signature, signing_ts) ) - logger.info('Inserted Comment into DB, `comment_id`: %s', comment_id) + logging.info('Inserted Comment into DB, `comment_id`: %s', comment_id) return comment_id diff --git a/src/database/writes.py b/src/database/writes.py index 7d11922..701bb0b 100644 --- a/src/database/writes.py +++ b/src/database/writes.py @@ -9,10 +9,10 @@ from src.database.queries import get_comment_or_none from src.database.queries import insert_comment from src.database.queries import insert_channel from src.database.queries import get_claim_ids_from_comment_ids -from src.server.misc import is_authentic_delete_signal -from src.server.misc import request_lbrynet from src.server.misc import validate_signature_from_claim from src.server.misc import channel_matches_pattern_or_error +from src.server.misc import get_claim_from_id + logger = logging.getLogger(__name__) @@ -41,9 +41,9 @@ async def abandon_comment(app, comment_id): return await coroutine(delete_comment_by_id)(app['writer'], comment_id) -async def abandon_comment_if_authorized(app, comment_id, **kwargs): - authorized = await is_authentic_delete_signal(app, comment_id, **kwargs) - if not authorized: +async def abandon_comment_if_authorized(app, comment_id, channel_id, signature, signing_ts, **kwargs): + claim = await get_claim_from_id(app, channel_id) + if not validate_signature_from_claim(claim, signature, signing_ts, comment_id): return False job = await app['comment_scheduler'].spawn(abandon_comment(app, comment_id)) @@ -58,10 +58,6 @@ async def hide_comments(app, comment_ids): return await coroutine(hide_comments_by_id)(app['writer'], comment_ids) -async def claim_search(app, **kwargs): - return (await request_lbrynet(app, 'claim_search', **kwargs))['items'][0] - - async def hide_comments_where_authorized(app, pieces: list): comment_cids = get_claim_ids_from_comment_ids( conn=app['reader'], @@ -73,7 +69,7 @@ async def hide_comments_where_authorized(app, pieces: list): for p in pieces: claim_id = comment_cids[p['comment_id']] if claim_id not in claims: - claims[claim_id] = await claim_search(app, claim_id=claim_id, no_totals=True) + claims[claim_id] = await get_claim_from_id(app, claim_id, no_totals=True) channel = claims[claim_id].get('signing_channel') if validate_signature_from_claim(channel, p['signature'], p['signing_ts'], p['comment_id']): comments_to_hide.append(p['comment_id']) diff --git a/src/server/misc.py b/src/server/misc.py index 07567b9..6db95f4 100644 --- a/src/server/misc.py +++ b/src/server/misc.py @@ -59,6 +59,10 @@ async def request_lbrynet(app, method, **params): raise Exception("Server cannot verify delete signature") +async def get_claim_from_id(app, claim_id, **kwargs): + return (await request_lbrynet(app, 'claim_search', no_totals=True, claim_id=claim_id, **kwargs))['items'][0] + + def get_encoded_signature(signature): signature = signature.encode() if type(signature) is str else signature r = int(signature[:int(len(signature) / 2)], 16) @@ -109,21 +113,6 @@ def is_valid_credential_input(channel_id=None, channel_name=None, signature=None return True -async def is_authentic_delete_signal(app, comment_id, channel_name, channel_id, signature, signing_ts): - lbry_url = f'lbry://{channel_name}#{channel_id}' - claim = await request_lbrynet(app, 'resolve', urls=[lbry_url]) - if claim: - public_key = claim['value']['public_key'] - claim_hash = binascii.unhexlify(claim['claim_id'].encode())[::-1] - pieces_injest = b''.join((signing_ts.encode(), claim_hash, comment_id.encode())) - return is_signature_valid( - encoded_signature=get_encoded_signature(signature), - signature_digest=hashlib.sha256(pieces_injest).digest(), - public_key_bytes=binascii.unhexlify(public_key.encode()) - ) - return False - - def validate_signature_from_claim(claim, signature, signing_ts, data: str): try: if claim: diff --git a/test/test_server.py b/test/test_server.py index 0d9f478..8ba5296 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -1,10 +1,5 @@ -import unittest -import atexit import os -from multiprocessing.pool import Pool -import asyncio import aiohttp -import requests import re from itertools import * @@ -64,7 +59,12 @@ class ServerTest(AsyncioTestCase): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.url = 'http://' + config['HOST'] + ':5921/api' + self.host = 'localhost' + self.port = 5931 + + @property + def url(self): + return f'http://{self.host}:{self.port}/api' @classmethod def tearDownClass(cls) -> None: @@ -74,7 +74,7 @@ class ServerTest(AsyncioTestCase): async def asyncSetUp(self): await super().asyncSetUp() self.server = app.CommentDaemon(config, db_file=self.db_file) - await self.server.start() + await self.server.start(host=self.host, port=self.port) self.addCleanup(self.server.stop) async def post_comment(self, **params): @@ -199,24 +199,30 @@ class ListCommentsTest(AsyncioTestCase): 'signature': nothing, 'parent_id': nothing } - db_file = 'list_test.db' - url = 'http://localhost:5921/api' - comment_ids = None - claim_id = '1d8a5cc39ca02e55782d619e67131c0a20843be8' - @classmethod - async def post_comment(cls, **params): - return await jsonrpc_post(cls.url, 'create_comment', **params) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.host = 'localhost' + self.port = 5931 + self.db_file = 'list_test.db' + self.claim_id = '1d8a5cc39ca02e55782d619e67131c0a20843be8' + self.comment_ids = None - @classmethod - def tearDownClass(cls) -> None: + @property + def url(self): + return f'http://{self.host}:{self.port}/api' + + async def post_comment(self, **params): + return await jsonrpc_post(self.url, 'create_comment', **params) + + def tearDown(self) -> None: print('exit reached') - os.remove(cls.db_file) + os.remove(self.db_file) async def asyncSetUp(self): await super().asyncSetUp() self.server = app.CommentDaemon(config, db_file=self.db_file) - await self.server.start() + await self.server.start(self.host, self.port) self.addCleanup(self.server.stop) if self.comment_ids is None: self.comment_list = [{key: self.replace[key]() for key in self.replace.keys()} for _ in range(23)] @@ -226,8 +232,9 @@ class ListCommentsTest(AsyncioTestCase): for comm in self.comment_list] async def testListComments(self): - response_one = await jsonrpc_post(self.url, 'get_claim_comments', page_size=20, - page=1, top_level=1, claim_id=self.claim_id) + response_one = await jsonrpc_post( + self.url, 'get_claim_comments', page_size=20, page=1, top_level=1, claim_id=self.claim_id + ) self.assertIsNotNone(response_one) self.assertIn('result', response_one) response_one: dict = response_one['result']