diff --git a/src/config/__init__.py b/src/config/__init__.py index 7f8b0e79..02140186 100755 --- a/src/config/__init__.py +++ b/src/config/__init__.py @@ -1,9 +1,12 @@ -''' - Onionr - Private P2P Communication +"""Onionr - Private P2P Communication. - This file deals with configuration management. -''' -''' +This file deals with configuration management. +""" +import os, json, logger +import filepaths + +from . import onboarding +""" This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -16,20 +19,14 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -''' - -import os, json, logger -import filepaths - -from . import onboarding +""" _configfile = filepaths.config_file _config = {} + def get(key, default = None, save = False): - ''' - Gets the key from configuration, or returns `default` - ''' + """Gets the key from configuration, or returns `default`""" key = str(key).split('.') data = _config @@ -41,20 +38,24 @@ def get(key, default = None, save = False): return default data = data[item] - if not last in data: + if last not in data: if save: set(key, default, savefile = True) return default return data[last] + def set(key, value = None, savefile = False): - ''' - Sets the key in configuration to `value` - ''' + """Sets the key in configuration to `value`""" + from . import observers + config_set_observers = { + 'general.store_plaintext_blocks': [observers.delete_plaintext] + } global _config + whole_key = key key = str(key).split('.') data = _config @@ -64,6 +65,11 @@ def set(key, value = None, savefile = False): if (not item in data) or (not type(data[item]) == dict): data[item] = dict() data = data[item] + try: + for observer in config_set_observers[whole_key]: + observer(value) + except KeyError: + pass if value is None: del data[last] @@ -73,6 +79,7 @@ def set(key, value = None, savefile = False): if savefile: save() + def is_set(key): key = str(key).split('.') data = _config @@ -89,18 +96,16 @@ def is_set(key): return True + def check(): - ''' - Checks if the configuration file exists, creates it if not - ''' + """Checks if the configuration file exists, creates it if not""" if not os.path.exists(os.path.dirname(get_config_file())): os.makedirs(os.path.dirname(get_config_file())) + def save(): - ''' - Saves the configuration data to the configuration file - ''' + """Saves the configuration data to the configuration file""" check() try: @@ -109,10 +114,9 @@ def save(): except json.JSONDecodeError: logger.warn('Failed to write to configuration file.') + def reload(): - ''' - Reloads the configuration data in memory from the file - ''' + """Reloads the configuration data in memory from the file""" check() try: with open(get_config_file(), 'r', encoding="utf8") as configfile: @@ -121,28 +125,24 @@ def reload(): pass #logger.debug('Failed to parse configuration file.') + def get_config(): - ''' - Gets the entire configuration as an array - ''' + """Gets the entire configuration as an array""" return _config + def set_config(config): - ''' - Sets the configuration to the array in arguments - ''' + """Sets the configuration to the array in arguments""" global _config _config = config + def get_config_file(): - ''' - Returns the absolute path to the configuration file - ''' + """Returns the absolute path to the configuration file""" return _configfile + def set_config_file(configfile): - ''' - Sets the path to the configuration file - ''' + """Sets the path to the configuration file.""" global _configfile _configfile = os.abs.abspath(configfile) diff --git a/src/config/observers/__init__.py b/src/config/observers/__init__.py new file mode 100644 index 00000000..dbf4e04d --- /dev/null +++ b/src/config/observers/__init__.py @@ -0,0 +1,2 @@ +from . import plaintextdelete +delete_plaintext = plaintextdelete.delete_plaintext diff --git a/src/config/observers/plaintextdelete.py b/src/config/observers/plaintextdelete.py new file mode 100644 index 00000000..f3b384c8 --- /dev/null +++ b/src/config/observers/plaintextdelete.py @@ -0,0 +1,36 @@ +"""Onionr - Private P2P Communication. + +Delete plaintext blocks, used when plaintext is disabled in config +""" +from onionrblocks import onionrblockapi +from coredb import blockmetadb +from onionrstorage.removeblock import remove_block +import onionrstorage +""" + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +""" + + +def delete_plaintext(dont_delete: bool): + """Delete, but do not blacklist, plaintext blocks.""" + if dont_delete: + return + + block_list = blockmetadb.get_block_list() + + for block in block_list: + block = onionrblockapi.Block(hash=block) + if not block.isEncrypted: + remove_block(block.hash) + onionrstorage.deleteBlock(block.hash) diff --git a/src/coredb/blockmetadb/__init__.py b/src/coredb/blockmetadb/__init__.py index 0a2d3438..952f7a49 100644 --- a/src/coredb/blockmetadb/__init__.py +++ b/src/coredb/blockmetadb/__init__.py @@ -1,9 +1,14 @@ -''' +""" Onionr - Private P2P Communication This module works with information relating to blocks stored on the node -''' -''' +""" +import sqlite3 + +from etc import onionrvalues +from . import expiredblocks, updateblockinfo, add +from .. import dbfiles +""" This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or @@ -16,19 +21,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . -''' -import sqlite3 - -from etc import onionrvalues -from . import expiredblocks, updateblockinfo, add -from .. import dbfiles +""" update_block_info = updateblockinfo.update_block_info add_to_block_DB = add.add_to_block_DB + + def get_block_list(dateRec = None, unsaved = False): - ''' + """ Get list of our blocks - ''' + """ if dateRec == None: dateRec = 0 @@ -44,10 +46,11 @@ def get_block_list(dateRec = None, unsaved = False): conn.close() return rows + def get_block_date(blockHash): - ''' + """ Returns the date a block was received - ''' + """ conn = sqlite3.connect(dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT) c = conn.cursor() @@ -60,10 +63,11 @@ def get_block_date(blockHash): conn.close() return None + def get_blocks_by_type(blockType, orderDate=True): - ''' + """ Returns a list of blocks by the type - ''' + """ conn = sqlite3.connect(dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT) c = conn.cursor() @@ -80,4 +84,5 @@ def get_blocks_by_type(blockType, orderDate=True): for i in row: rows.append(i) conn.close() - return rows \ No newline at end of file + return rows + diff --git a/src/onionrblocks/onionrblockapi.py b/src/onionrblocks/onionrblockapi.py index a8c2343b..a03b5788 100755 --- a/src/onionrblocks/onionrblockapi.py +++ b/src/onionrblocks/onionrblockapi.py @@ -95,7 +95,7 @@ class Block: # Check for replay attacks try: if epoch.get_epoch() - blockmetadb.get_block_date(self.hash) > 60: - if not cryptoutils.replay_validator(self.bmetadata['rply']): raise onionrexceptions.ReplayAttack + if not cryptoutils.replay_validator(self.bmetadata['rply']): raise onionrexceptions.ReplayAttack except (AssertionError, KeyError, TypeError, onionrexceptions.ReplayAttack) as e: if not self.bypassReplayCheck: # Zero out variables to prevent reading of replays @@ -187,7 +187,7 @@ class Block: self.date = datetime.datetime.fromtimestamp(self.getDate()) self.valid = True - + if self.autoDecrypt: self.decrypt() @@ -462,61 +462,6 @@ class Block: return self # static functions - - def getBlocks(type = None, signer = None, signed = None, reverse = False, limit = None): - ''' - Returns a list of Block objects based on supplied filters - - Inputs: - - type (str): filters by block type - - signer (str/list): filters by signer (one in the list has to be a signer) - - signed (bool): filters out by whether or not the block is signed - - reverse (bool): reverses the list if True - - Outputs: - - (list): a list of Block objects that match the input - ''' - - try: - - relevant_blocks = list() - blocks = (blockmetadb.get_block_list() if type is None else blockmetadb.get_blocks_by_type(type)) - - for block in blocks: - if Block.exists(block): - block = Block(block) - - relevant = True - - if (not signed is None) and (block.isSigned() != bool(signed)): - relevant = False - if not signer is None: - if isinstance(signer, (str,)): - signer = [signer] - if isinstance(signer, (bytes,)): - signer = [signer.decode()] - - isSigner = False - for key in signer: - if block.isSigner(key): - isSigner = True - break - - if not isSigner: - relevant = False - - if relevant and (limit is None or len(relevant_Blocks) <= int(limit)): - relevant_blocks.append(block) - - if bool(reverse): - relevant_blocks.reverse() - - return relevant_blocks - except Exception as e: - logger.debug('Failed to get blocks.', error = e) - - return list() - def exists(bHash): ''' Checks if a block is saved to file or not @@ -536,7 +481,7 @@ class Block: if isinstance(bHash, Block): bHash = bHash.getHash() - + ret = isinstance(onionrstorage.getData(bHash), type(None)) return not ret diff --git a/src/utils/createdirs.py b/src/utils/createdirs.py index fb61e88c..8f251763 100644 --- a/src/utils/createdirs.py +++ b/src/utils/createdirs.py @@ -19,7 +19,6 @@ ''' import os from . import identifyhome -from onionrsetup import dbcreator import filepaths home = identifyhome.identify_home() @@ -31,6 +30,8 @@ def create_dirs(): if not os.path.exists(path): os.mkdir(path) + from onionrsetup import dbcreator + for db in dbcreator.create_funcs: try: db() diff --git a/tests/README.md b/tests/README.md index e5c435e3..1006e527 100644 --- a/tests/README.md +++ b/tests/README.md @@ -3,5 +3,3 @@ Onionr has two test suites, this directory's unittests and integration tests. In these unittests, be careful to manage import order. The test home directory environment variable needs to be set before most imports. - - diff --git a/tests/test_plaintext_config.py b/tests/test_plaintext_config.py new file mode 100644 index 00000000..c4db9241 --- /dev/null +++ b/tests/test_plaintext_config.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +import sys, os +sys.path.append(".") +sys.path.append("src/") +import unittest, uuid +import json +TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/' +print("Test directory:", TEST_DIR) +os.environ["ONIONR_HOME"] = TEST_DIR + +from utils import identifyhome, createdirs +from onionrsetup import setup_config +createdirs.create_dirs() +setup_config() +import config +from coredb import blockmetadb +from onionrblocks.insert import insert_block + +class TestTemplate(unittest.TestCase): + def test_plaintext_config(self): + b1 = insert_block('test block') + self.assertIn(b1, blockmetadb.get_block_list()) + config.set('general.store_plaintext_blocks', False) + self.assertNotIn(b1, blockmetadb.get_block_list()) + + + +unittest.main() diff --git a/tests/test_template.py b/tests/test_template.py new file mode 100644 index 00000000..3e8cca75 --- /dev/null +++ b/tests/test_template.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import sys, os +sys.path.append(".") +sys.path.append("src/") +import unittest, uuid +import json +TEST_DIR = 'testdata/%s-%s' % (uuid.uuid4(), os.path.basename(__file__)) + '/' +print("Test directory:", TEST_DIR) +os.environ["ONIONR_HOME"] = TEST_DIR + +from utils import identifyhome, createdirs +from onionrsetup import setup_config +createdirs.create_dirs() +setup_config() + +class TestTemplate(unittest.TestCase): + ''' + Tests both the onionrusers class and the contactmanager (which inherits it) + ''' + def test_true(self): + self.assertTrue(True) + + + +unittest.main()