added config observers, delete plaintext blocks when plaintext storage is disabled
parent
2e31155a5d
commit
f78809fa2a
|
@ -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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
import os, json, logger
|
|
||||||
import filepaths
|
|
||||||
|
|
||||||
from . import onboarding
|
|
||||||
|
|
||||||
_configfile = filepaths.config_file
|
_configfile = filepaths.config_file
|
||||||
_config = {}
|
_config = {}
|
||||||
|
|
||||||
|
|
||||||
def get(key, default = None, save = False):
|
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('.')
|
key = str(key).split('.')
|
||||||
data = _config
|
data = _config
|
||||||
|
@ -41,20 +38,24 @@ def get(key, default = None, save = False):
|
||||||
return default
|
return default
|
||||||
data = data[item]
|
data = data[item]
|
||||||
|
|
||||||
if not last in data:
|
if last not in data:
|
||||||
if save:
|
if save:
|
||||||
set(key, default, savefile = True)
|
set(key, default, savefile = True)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
return data[last]
|
return data[last]
|
||||||
|
|
||||||
|
|
||||||
def set(key, value = None, savefile = False):
|
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
|
global _config
|
||||||
|
|
||||||
|
whole_key = key
|
||||||
key = str(key).split('.')
|
key = str(key).split('.')
|
||||||
data = _config
|
data = _config
|
||||||
|
|
||||||
|
@ -64,6 +65,11 @@ def set(key, value = None, savefile = False):
|
||||||
if (not item in data) or (not type(data[item]) == dict):
|
if (not item in data) or (not type(data[item]) == dict):
|
||||||
data[item] = dict()
|
data[item] = dict()
|
||||||
data = data[item]
|
data = data[item]
|
||||||
|
try:
|
||||||
|
for observer in config_set_observers[whole_key]:
|
||||||
|
observer(value)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
if value is None:
|
if value is None:
|
||||||
del data[last]
|
del data[last]
|
||||||
|
@ -73,6 +79,7 @@ def set(key, value = None, savefile = False):
|
||||||
if savefile:
|
if savefile:
|
||||||
save()
|
save()
|
||||||
|
|
||||||
|
|
||||||
def is_set(key):
|
def is_set(key):
|
||||||
key = str(key).split('.')
|
key = str(key).split('.')
|
||||||
data = _config
|
data = _config
|
||||||
|
@ -89,18 +96,16 @@ def is_set(key):
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def check():
|
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())):
|
if not os.path.exists(os.path.dirname(get_config_file())):
|
||||||
os.makedirs(os.path.dirname(get_config_file()))
|
os.makedirs(os.path.dirname(get_config_file()))
|
||||||
|
|
||||||
|
|
||||||
def save():
|
def save():
|
||||||
'''
|
"""Saves the configuration data to the configuration file"""
|
||||||
Saves the configuration data to the configuration file
|
|
||||||
'''
|
|
||||||
|
|
||||||
check()
|
check()
|
||||||
try:
|
try:
|
||||||
|
@ -109,10 +114,9 @@ def save():
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
logger.warn('Failed to write to configuration file.')
|
logger.warn('Failed to write to configuration file.')
|
||||||
|
|
||||||
|
|
||||||
def reload():
|
def reload():
|
||||||
'''
|
"""Reloads the configuration data in memory from the file"""
|
||||||
Reloads the configuration data in memory from the file
|
|
||||||
'''
|
|
||||||
check()
|
check()
|
||||||
try:
|
try:
|
||||||
with open(get_config_file(), 'r', encoding="utf8") as configfile:
|
with open(get_config_file(), 'r', encoding="utf8") as configfile:
|
||||||
|
@ -121,28 +125,24 @@ def reload():
|
||||||
pass
|
pass
|
||||||
#logger.debug('Failed to parse configuration file.')
|
#logger.debug('Failed to parse configuration file.')
|
||||||
|
|
||||||
|
|
||||||
def get_config():
|
def get_config():
|
||||||
'''
|
"""Gets the entire configuration as an array"""
|
||||||
Gets the entire configuration as an array
|
|
||||||
'''
|
|
||||||
return _config
|
return _config
|
||||||
|
|
||||||
|
|
||||||
def set_config(config):
|
def set_config(config):
|
||||||
'''
|
"""Sets the configuration to the array in arguments"""
|
||||||
Sets the configuration to the array in arguments
|
|
||||||
'''
|
|
||||||
global _config
|
global _config
|
||||||
_config = config
|
_config = config
|
||||||
|
|
||||||
|
|
||||||
def get_config_file():
|
def get_config_file():
|
||||||
'''
|
"""Returns the absolute path to the configuration file"""
|
||||||
Returns the absolute path to the configuration file
|
|
||||||
'''
|
|
||||||
return _configfile
|
return _configfile
|
||||||
|
|
||||||
|
|
||||||
def set_config_file(configfile):
|
def set_config_file(configfile):
|
||||||
'''
|
"""Sets the path to the configuration file."""
|
||||||
Sets the path to the configuration file
|
|
||||||
'''
|
|
||||||
global _configfile
|
global _configfile
|
||||||
_configfile = os.abs.abspath(configfile)
|
_configfile = os.abs.abspath(configfile)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
from . import plaintextdelete
|
||||||
|
delete_plaintext = plaintextdelete.delete_plaintext
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
|
@ -1,9 +1,14 @@
|
||||||
'''
|
"""
|
||||||
Onionr - Private P2P Communication
|
Onionr - Private P2P Communication
|
||||||
|
|
||||||
This module works with information relating to blocks stored on the node
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
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
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
"""
|
||||||
import sqlite3
|
|
||||||
|
|
||||||
from etc import onionrvalues
|
|
||||||
from . import expiredblocks, updateblockinfo, add
|
|
||||||
from .. import dbfiles
|
|
||||||
|
|
||||||
update_block_info = updateblockinfo.update_block_info
|
update_block_info = updateblockinfo.update_block_info
|
||||||
add_to_block_DB = add.add_to_block_DB
|
add_to_block_DB = add.add_to_block_DB
|
||||||
|
|
||||||
|
|
||||||
def get_block_list(dateRec = None, unsaved = False):
|
def get_block_list(dateRec = None, unsaved = False):
|
||||||
'''
|
"""
|
||||||
Get list of our blocks
|
Get list of our blocks
|
||||||
'''
|
"""
|
||||||
if dateRec == None:
|
if dateRec == None:
|
||||||
dateRec = 0
|
dateRec = 0
|
||||||
|
|
||||||
|
@ -44,10 +46,11 @@ def get_block_list(dateRec = None, unsaved = False):
|
||||||
conn.close()
|
conn.close()
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
|
|
||||||
def get_block_date(blockHash):
|
def get_block_date(blockHash):
|
||||||
'''
|
"""
|
||||||
Returns the date a block was received
|
Returns the date a block was received
|
||||||
'''
|
"""
|
||||||
|
|
||||||
conn = sqlite3.connect(dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
conn = sqlite3.connect(dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
|
@ -60,10 +63,11 @@ def get_block_date(blockHash):
|
||||||
conn.close()
|
conn.close()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_blocks_by_type(blockType, orderDate=True):
|
def get_blocks_by_type(blockType, orderDate=True):
|
||||||
'''
|
"""
|
||||||
Returns a list of blocks by the type
|
Returns a list of blocks by the type
|
||||||
'''
|
"""
|
||||||
|
|
||||||
conn = sqlite3.connect(dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
conn = sqlite3.connect(dbfiles.block_meta_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
|
@ -81,3 +85,4 @@ def get_blocks_by_type(blockType, orderDate=True):
|
||||||
rows.append(i)
|
rows.append(i)
|
||||||
conn.close()
|
conn.close()
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
|
|
|
@ -462,61 +462,6 @@ class Block:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
# static functions
|
# 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):
|
def exists(bHash):
|
||||||
'''
|
'''
|
||||||
Checks if a block is saved to file or not
|
Checks if a block is saved to file or not
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
'''
|
'''
|
||||||
import os
|
import os
|
||||||
from . import identifyhome
|
from . import identifyhome
|
||||||
from onionrsetup import dbcreator
|
|
||||||
import filepaths
|
import filepaths
|
||||||
home = identifyhome.identify_home()
|
home = identifyhome.identify_home()
|
||||||
|
|
||||||
|
@ -31,6 +30,8 @@ def create_dirs():
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
os.mkdir(path)
|
os.mkdir(path)
|
||||||
|
|
||||||
|
from onionrsetup import dbcreator
|
||||||
|
|
||||||
for db in dbcreator.create_funcs:
|
for db in dbcreator.create_funcs:
|
||||||
try:
|
try:
|
||||||
db()
|
db()
|
||||||
|
|
|
@ -3,5 +3,3 @@
|
||||||
Onionr has two test suites, this directory's unittests and integration tests.
|
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.
|
In these unittests, be careful to manage import order. The test home directory environment variable needs to be set before most imports.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
|
@ -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()
|
Loading…
Reference in New Issue