added server sent events wrapper and example

master
Kevin Froman 2020-01-14 02:29:42 -06:00
parent 29421d678e
commit 828f7682b8
10 changed files with 117 additions and 37 deletions

View File

@ -9,6 +9,7 @@ from httpapi import security, friendsapi, profilesapi, configapi, insertblock
from httpapi import miscclientapi, onionrsitesapi, apiutils from httpapi import miscclientapi, onionrsitesapi, apiutils
from httpapi import directconnections from httpapi import directconnections
from httpapi import themeapi from httpapi import themeapi
from httpapi.sse.private import private_sse_blueprint
""" """
This program is free software: you can redistribute it and/or modify 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( app.register_blueprint(directconnections.DirectConnectionManagement(
private_api).direct_conn_management_bp) private_api).direct_conn_management_bp)
app.register_blueprint(themeapi.theme_blueprint) app.register_blueprint(themeapi.theme_blueprint)
app.register_blueprint(private_sse_blueprint)
def _add_events_bp(): def _add_events_bp():
while True: while True:

View File

@ -10,6 +10,7 @@ from filepaths import onboarding_mark_file
from onionrtypes import JSONSerializable from onionrtypes import JSONSerializable
from onionrtypes import OnboardingConfig from onionrtypes import OnboardingConfig
import config import config
from flask import g
""" """
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
@ -37,23 +38,23 @@ def set_config_from_onboarding(config_settings: OnboardingConfig):
get = _get_val_or_none 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'): 'networkContribution'):
config.set('general.security_level', 1) config.set('general.security_level', 1)
config.set('ui.theme', 'light') config.set('ui.theme', 'light')
if get(config_settings, 'useDark'): if get(config_settings, 'useDark'):
config.set('ui.theme', 'dark') config.set('ui.theme', 'dark')
if not get(config_settings, if not get(config_settings,
'useCircles') or config.get('general.security_level') > 0: 'useCircles') or config.get('general.security_level') > 0:
config.set('plugins.disabled', config.set('plugins.disabled',
config.get('plugins.disabled').append('flow')) config.get('plugins.disabled', []).append('flow'))
if not get(config_settings, 'useMail'): if not get(config_settings, 'useMail'):
config.set('plugins.disabled', config.set('plugins.disabled',
config.get('plugins.disabled').append('pms')) config.get('plugins.disabled', []).append('pms'))
config.set('general.store_plaintext_blocks', config.set('general.store_plaintext_blocks',
get(config_settings, 'plainContrib')) get(config_settings, 'plainContrib'))

View File

@ -23,7 +23,7 @@ from onionrservices import httpheaders
from . import pluginwhitelist from . import pluginwhitelist
# Be extremely mindful of this. These are endpoints available without a password # 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', 'staticfiles.friends', 'staticfiles.friendsindex', 'siteapi.site', 'siteapi.siteFile', 'staticfiles.onionrhome',
'themes.getTheme', 'staticfiles.onboarding', 'staticfiles.onboardingIndex'] 'themes.getTheme', 'staticfiles.onboarding', 'staticfiles.onboardingIndex']
@ -50,6 +50,7 @@ class ClientAPISecurity:
if request.endpoint in whitelist_endpoints: if request.endpoint in whitelist_endpoints:
return return
if request.path.startswith('/site/'): return if request.path.startswith('/site/'): return
try: try:
if not hmac.compare_digest(request.headers['token'], client_api.clientToken): if not hmac.compare_digest(request.headers['token'], client_api.clientToken):
if not hmac.compare_digest(request.form['token'], client_api.clientToken): if not hmac.compare_digest(request.form['token'], client_api.clientToken):

View File

@ -0,0 +1,3 @@
# sse
This folder contains a wrapper for handling server sent event loops

View File

@ -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 <https://www.gnu.org/licenses/>.
"""

View File

@ -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)

View File

@ -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 <https://www.gnu.org/licenses/>.
"""
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

View File

@ -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 <https://www.gnu.org/licenses/>.
"""
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)

View File

@ -129,7 +129,7 @@ function getBlocks(){
var ch = document.getElementById('feedIDInput').value var ch = document.getElementById('feedIDInput').value
if (lastLoadedBoard !== ch){ if (lastLoadedBoard !== ch){
requested = [] requested = []
toggleLoadingMessage() toggleLoadingMessage()
loadedAny = false loadedAny = false
@ -184,7 +184,6 @@ function loadMessage(blockHash, blockList, count, channel){
} }
} }
setTimeout(function(){appendMessages(data, blockHash, before, channel)}, delay) setTimeout(function(){appendMessages(data, blockHash, before, channel)}, delay)
//appendMessages(data, blockHash, before)
}) })
} }
@ -208,7 +207,7 @@ newPostForm.onsubmit = function(){
"token": webpass "token": webpass
} }
}) })
.then((resp) => resp.text()) // Transform the data into json .then((resp) => resp.text()) // Transform the data into text
.then(function(data) { .then(function(data) {
newPostForm.style.display = 'block' newPostForm.style.display = 'block'
if (data == 'failure due to duplicate insert'){ if (data == 'failure due to duplicate insert'){

View File

@ -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()