From 828f7682b8cc36d2dbbc0ecdbf7779f551ddcd2d Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Tue, 14 Jan 2020 02:29:42 -0600 Subject: [PATCH] added server sent events wrapper and example --- .../private/register_private_blueprints.py | 2 ++ src/config/onboarding.py | 11 +++--- src/httpapi/security/client.py | 3 +- src/httpapi/sse/README.md | 3 ++ src/httpapi/sse/__init__.py | 18 ++++++++++ src/httpapi/sse/private/__init__.py | 16 +++++++++ src/httpapi/sse/wrapper.py | 34 +++++++++++++++++++ src/onionrblocks/deleteplaintext.py | 34 +++++++++++++++++++ static-data/www/board/board.js | 5 ++- tests/test_plaintext_config.py | 28 --------------- 10 files changed, 117 insertions(+), 37 deletions(-) create mode 100644 src/httpapi/sse/README.md create mode 100644 src/httpapi/sse/__init__.py create mode 100644 src/httpapi/sse/private/__init__.py create mode 100644 src/httpapi/sse/wrapper.py create mode 100644 src/onionrblocks/deleteplaintext.py delete mode 100644 tests/test_plaintext_config.py diff --git a/src/apiservers/private/register_private_blueprints.py b/src/apiservers/private/register_private_blueprints.py index b5ba6c5e..d534b0c9 100644 --- a/src/apiservers/private/register_private_blueprints.py +++ b/src/apiservers/private/register_private_blueprints.py @@ -9,6 +9,7 @@ from httpapi import security, friendsapi, profilesapi, configapi, insertblock from httpapi import miscclientapi, onionrsitesapi, apiutils from httpapi import directconnections from httpapi import themeapi +from httpapi.sse.private import private_sse_blueprint """ This program is free software: you can redistribute it and/or modify @@ -44,6 +45,7 @@ def register_private_blueprints(private_api, app): app.register_blueprint(directconnections.DirectConnectionManagement( private_api).direct_conn_management_bp) app.register_blueprint(themeapi.theme_blueprint) + app.register_blueprint(private_sse_blueprint) def _add_events_bp(): while True: diff --git a/src/config/onboarding.py b/src/config/onboarding.py index 063e4210..1df0f9b6 100644 --- a/src/config/onboarding.py +++ b/src/config/onboarding.py @@ -10,6 +10,7 @@ from filepaths import onboarding_mark_file from onionrtypes import JSONSerializable from onionrtypes import OnboardingConfig import config +from flask import g """ 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 @@ -37,23 +38,23 @@ def set_config_from_onboarding(config_settings: OnboardingConfig): get = _get_val_or_none - if get(config_settings, 'stateTarget') or not get(config_settings, + if get(config_settings, 'stateTarget') or not get(config_settings, 'networkContribution'): config.set('general.security_level', 1) config.set('ui.theme', 'light') if get(config_settings, 'useDark'): config.set('ui.theme', 'dark') - + if not get(config_settings, 'useCircles') or config.get('general.security_level') > 0: config.set('plugins.disabled', - config.get('plugins.disabled').append('flow')) + config.get('plugins.disabled', []).append('flow')) if not get(config_settings, 'useMail'): config.set('plugins.disabled', - config.get('plugins.disabled').append('pms')) - + config.get('plugins.disabled', []).append('pms')) + config.set('general.store_plaintext_blocks', get(config_settings, 'plainContrib')) diff --git a/src/httpapi/security/client.py b/src/httpapi/security/client.py index fbc2e6e0..fbb6b288 100644 --- a/src/httpapi/security/client.py +++ b/src/httpapi/security/client.py @@ -23,7 +23,7 @@ from onionrservices import httpheaders from . import pluginwhitelist # Be extremely mindful of this. These are endpoints available without a password -whitelist_endpoints = ['www', 'staticfiles.homedata', 'staticfiles.sharedContent', +whitelist_endpoints = ['www', 'staticfiles.homedata', 'staticfiles.sharedContent', 'staticfiles.friends', 'staticfiles.friendsindex', 'siteapi.site', 'siteapi.siteFile', 'staticfiles.onionrhome', 'themes.getTheme', 'staticfiles.onboarding', 'staticfiles.onboardingIndex'] @@ -50,6 +50,7 @@ class ClientAPISecurity: if request.endpoint in whitelist_endpoints: return if request.path.startswith('/site/'): return + try: if not hmac.compare_digest(request.headers['token'], client_api.clientToken): if not hmac.compare_digest(request.form['token'], client_api.clientToken): diff --git a/src/httpapi/sse/README.md b/src/httpapi/sse/README.md new file mode 100644 index 00000000..b01ca67a --- /dev/null +++ b/src/httpapi/sse/README.md @@ -0,0 +1,3 @@ +# sse + +This folder contains a wrapper for handling server sent event loops \ No newline at end of file diff --git a/src/httpapi/sse/__init__.py b/src/httpapi/sse/__init__.py new file mode 100644 index 00000000..2e46df3e --- /dev/null +++ b/src/httpapi/sse/__init__.py @@ -0,0 +1,18 @@ +"""Onionr - Private P2P Communication. + +server sent event modules, incl a wrapper and endpoints for client + public api +""" +""" + 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 . +""" diff --git a/src/httpapi/sse/private/__init__.py b/src/httpapi/sse/private/__init__.py new file mode 100644 index 00000000..964ef34c --- /dev/null +++ b/src/httpapi/sse/private/__init__.py @@ -0,0 +1,16 @@ +from flask import g, Blueprint +from gevent import sleep + +from .. import wrapper + +private_sse_blueprint = Blueprint('privatesse', __name__) +SSEWrapper = wrapper.SSEWrapper() + + +@private_sse_blueprint.route('/hello') +def srteam_meme(): + def print_hello(): + while True: + yield "hello\n\n" + sleep(1) + return SSEWrapper.handle_sse_request(print_hello) diff --git a/src/httpapi/sse/wrapper.py b/src/httpapi/sse/wrapper.py new file mode 100644 index 00000000..e4907345 --- /dev/null +++ b/src/httpapi/sse/wrapper.py @@ -0,0 +1,34 @@ +"""Onionr - Private P2P Communication. + +wrapper for server sent event endpoints +""" +from typing import Callable + +from flask import Response + +""" + 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 . +""" + + +class SSEWrapper: + def __init__(self): + self.active_count: int = 0 + + def handle_sse_request(self, handler: Callable): + self.active_count += 1 + resp = Response(handler()) + resp.content_type = "text/event-stream" + self.active_count -= 1 + return resp diff --git a/src/onionrblocks/deleteplaintext.py b/src/onionrblocks/deleteplaintext.py new file mode 100644 index 00000000..9789935e --- /dev/null +++ b/src/onionrblocks/deleteplaintext.py @@ -0,0 +1,34 @@ +"""Onionr - P2P Anonymous Storage Network. + +Delete but do not blacklist plaintext blocks +""" +from coredb import blockmetadb +from onionrstorage.removeblock import remove_block +import onionrstorage +from .onionrblockapi import Block +""" + 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_no_blacklist(): + """Delete, but do not blacklist, plaintext blocks.""" + + block_list = blockmetadb.get_block_list() + + for block in block_list: + block = Block(hash=block) + if not block.isEncrypted: + remove_block(block.hash) + onionrstorage.deleteBlock(block.hash) diff --git a/static-data/www/board/board.js b/static-data/www/board/board.js index 5ee7e9ef..e281d5a5 100755 --- a/static-data/www/board/board.js +++ b/static-data/www/board/board.js @@ -129,7 +129,7 @@ function getBlocks(){ var ch = document.getElementById('feedIDInput').value if (lastLoadedBoard !== ch){ requested = [] - + toggleLoadingMessage() loadedAny = false @@ -184,7 +184,6 @@ function loadMessage(blockHash, blockList, count, channel){ } } setTimeout(function(){appendMessages(data, blockHash, before, channel)}, delay) - //appendMessages(data, blockHash, before) }) } @@ -208,7 +207,7 @@ newPostForm.onsubmit = function(){ "token": webpass } }) - .then((resp) => resp.text()) // Transform the data into json + .then((resp) => resp.text()) // Transform the data into text .then(function(data) { newPostForm.style.display = 'block' if (data == 'failure due to duplicate insert'){ diff --git a/tests/test_plaintext_config.py b/tests/test_plaintext_config.py deleted file mode 100644 index c4db9241..00000000 --- a/tests/test_plaintext_config.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/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()