work on UI friends manager

This commit is contained in:
Kevin Froman 2019-02-21 14:25:45 -06:00
parent bcb0af2e54
commit 4f39c5792a
11 changed files with 183 additions and 14 deletions

View File

@ -21,10 +21,12 @@ from gevent.pywsgi import WSGIServer, WSGIHandler
from gevent import Timeout from gevent import Timeout
import flask, cgi, uuid import flask, cgi, uuid
from flask import request, Response, abort, send_from_directory from flask import request, Response, abort, send_from_directory
import sys, random, threading, hmac, hashlib, base64, time, math, os, json, socket import sys, random, threading, hmac, base64, time, os, json, socket
import core import core
from onionrblockapi import Block from onionrblockapi import Block
import onionrutils, onionrexceptions, onionrcrypto, blockimporter, onionrevents as events, logger, config, onionr import onionrutils, onionrexceptions, onionrcrypto, blockimporter, onionrevents as events, logger, config
from httpapi import friendsapi
import onionr
class FDSafeHandler(WSGIHandler): class FDSafeHandler(WSGIHandler):
'''Our WSGI handler. Doesn't do much non-default except timeouts''' '''Our WSGI handler. Doesn't do much non-default except timeouts'''
@ -250,7 +252,7 @@ class API:
''' '''
# assert isinstance(onionrInst, onionr.Onionr) # assert isinstance(onionrInst, onionr.Onionr)
# configure logger and stuff # configure logger and stuff
onionr.Onionr.setupConfig('data/', self = self) #onionr.Onionr.setupConfig('data/', self = self)
self.debug = debug self.debug = debug
self._core = onionrInst.onionrCore self._core = onionrInst.onionrCore
@ -262,7 +264,7 @@ class API:
self.bindPort = bindPort self.bindPort = bindPort
# Be extremely mindful of this. These are endpoints available without a password # Be extremely mindful of this. These are endpoints available without a password
self.whitelistEndpoints = ('site', 'www', 'onionrhome', 'board', 'boardContent', 'sharedContent', 'mail', 'mailindex') self.whitelistEndpoints = ('site', 'www', 'onionrhome', 'board', 'boardContent', 'sharedContent', 'mail', 'mailindex', 'friends', 'friendsindex')
self.clientToken = config.get('client.webpassword') self.clientToken = config.get('client.webpassword')
self.timeBypassToken = base64.b16encode(os.urandom(32)).decode() self.timeBypassToken = base64.b16encode(os.urandom(32)).decode()
@ -276,6 +278,7 @@ class API:
self.pluginResponses = {} # Responses for plugin endpoints self.pluginResponses = {} # Responses for plugin endpoints
self.queueResponse = {} self.queueResponse = {}
onionrInst.setClientAPIInst(self) onionrInst.setClientAPIInst(self)
app.register_blueprint(friendsapi.friends)
@app.before_request @app.before_request
def validateRequest(): def validateRequest():
@ -315,6 +318,14 @@ class API:
@app.route('/mail/', endpoint='mailindex') @app.route('/mail/', endpoint='mailindex')
def loadMailIndex(): def loadMailIndex():
return send_from_directory('static-data/www/mail/', 'index.html') return send_from_directory('static-data/www/mail/', 'index.html')
@app.route('/friends/<path:path>', endpoint='friends')
def loadContacts(path):
return send_from_directory('static-data/www/friends/', path)
@app.route('/friends/', endpoint='friendsindex')
def loadContacts():
return send_from_directory('static-data/www/friends/', 'index.html')
@app.route('/board/<path:path>', endpoint='boardContent') @app.route('/board/<path:path>', endpoint='boardContent')
def boardContent(path): def boardContent(path):

View File

@ -171,7 +171,8 @@ class OnionrCommunicatorDaemon:
# Validate new peers are good format and not already in queue # Validate new peers are good format and not already in queue
invalid = [] invalid = []
for x in newPeers: for x in newPeers:
if not self._core._utils.validateID(x) or x in self.newPeers: x = x.strip()
if not self._core._utils.validateID(x) or x in self.newPeers or x == self._core.hsAddress:
invalid.append(x) invalid.append(x)
for x in invalid: for x in invalid:
newPeers.remove(x) newPeers.remove(x)
@ -431,6 +432,8 @@ class OnionrCommunicatorDaemon:
for address in peerList: for address in peerList:
if not config.get('tor.v3onions') and len(address) == 62: if not config.get('tor.v3onions') and len(address) == 62:
continue continue
if address == self._core.hsAddress:
continue
if len(address) == 0 or address in tried or address in self.onlinePeers or address in self.cooldownPeer: if len(address) == 0 or address in tried or address in self.onlinePeers or address in self.cooldownPeer:
continue continue
if self.shutdown: if self.shutdown:

View File

@ -121,7 +121,6 @@ class Core:
''' '''
Hack to refresh some vars which may not be set on first start Hack to refresh some vars which may not be set on first start
''' '''
if os.path.exists(self.dataDir + '/hs/hostname'): if os.path.exists(self.dataDir + '/hs/hostname'):
with open(self.dataDir + '/hs/hostname', 'r') as hs: with open(self.dataDir + '/hs/hostname', 'r') as hs:
self.hsAddress = hs.read().strip() self.hsAddress = hs.read().strip()
@ -597,10 +596,6 @@ class Core:
conn = sqlite3.connect(self.blockDB, timeout=30) conn = sqlite3.connect(self.blockDB, timeout=30)
c = conn.cursor() c = conn.cursor()
# if unsaved:
# execute = 'SELECT hash FROM hashes WHERE dataSaved != 1 ORDER BY RANDOM();'
# else:
# execute = 'SELECT hash FROM hashes ORDER BY dateReceived ASC;'
execute = 'SELECT hash FROM hashes WHERE dateReceived >= ? ORDER BY dateReceived ASC;' execute = 'SELECT hash FROM hashes WHERE dateReceived >= ? ORDER BY dateReceived ASC;'
args = (dateRec,) args = (dateRec,)
rows = list() rows = list()

View File

@ -0,0 +1,48 @@
'''
Onionr - P2P Anonymous Storage Network
This file creates http endpoints for friend management
'''
'''
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/>.
'''
import core
from onionrusers import contactmanager
from flask import Blueprint, Response, request, abort
friends = Blueprint('friends', __name__)
@friends.route('/friends/add/<pubkey>', methods=['POST'])
def add_friend(pubkey):
contactmanager.ContactManager(core.Core(), pubkey, saveUser=True).setTrust(1)
return 'success'
@friends.route('/friends/remove/<pubkey>', methods=['POST'])
def remove_friend(pubkey):
contactmanager.ContactManager(core.Core(), pubkey).setTrust(0)
return 'success'
@friends.route('/friends/setinfo/<pubkey>/<key>', methods=['POST'])
def set_info(pubkey, key):
data = request.form['data']
contactmanager.ContactManager(core.Core(), pubkey).set_info(key, data)
return 'success'
@friends.route('/friends/getinfo/<pubkey>/<key>')
def get_info(pubkey, key):
retData = contactmanager.ContactManager(core.Core(), pubkey).get_info(key)
if retData is None:
abort(404)
else:
return retData

View File

@ -0,0 +1,5 @@
{
"name" : "contactmanager",
"version" : "1.0",
"author" : "onionr"
}

View File

@ -0,0 +1,39 @@
'''
Onionr - P2P Anonymous Storage Network
This is an interactive menu-driven CLI interface for Onionr
'''
'''
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/>.
'''
plugin_name = 'contactmanager'
class OnionrContactManager:
def __init__(self, api):
return
def on_init(api, data = None):
'''
This event is called after Onionr is initialized, but before the command
inputted is executed. Could be called when daemon is starting or when
just the client is running.
'''
# Doing this makes it so that the other functions can access the api object
# by simply referencing the variable `pluginapi`.
pluginapi = api
ui = OnionrCLIUI(api)
#api.commands.register('interactive', ui.start)
return

View File

@ -0,0 +1,21 @@
/*
Onionr - P2P Anonymous Storage Network
This file handles the UI for managing friends/contacts
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/>.
*/
friendListDisplay = document.getElementById('friendList')

View File

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>
Onionr
</title>
<link rel='stylesheet' href='/shared/style/modal.css'>
<link rel='stylesheet' href='/shared/main/style.css'>
<link rel='stylesheet' href='/friends/style.css'>
</head>
<body>
<div id="shutdownNotice" class='overlay'>
<div>
<p>Your node will shutdown. Thank you for using Onionr.</p>
</div>
</div>
<div class='content'>
<img class='logo' src='/shared/onionr-icon.png' alt='onionr logo'>
<span class='logoText'>Onionr Web Control Panel</span>
<h2>Friend Manager</h2>
<form id='addFriend' action='/' method='POST'>
<label>Friend ID: <input type='text' name='addKey' placeholder='public key/ID' required></label>
<label>Set Alias: <input type='text' name='addAlias' placeholder='what to call them' required></label>
<input type='submit' value='Add Friend'>
</form>
<div id='friendList'></div>
</div>
<script src='/shared/misc.js'></script>
<script src='/friends/friends.js'></script>
</body>
</html>

View File

@ -0,0 +1,15 @@
h2, h3{
font-family: Arial, Helvetica, sans-serif;
}
form{
border: 1px solid black;
border-radius: 5px;
padding: 1em;
margin-right: 10%;
}
form label{
display: block;
margin-top: 0.5em;
margin-bottom: 0.5em;
}

View File

@ -14,11 +14,12 @@
<p>Your node will shutdown. Thank you for using Onionr.</p> <p>Your node will shutdown. Thank you for using Onionr.</p>
</div> </div>
</div> </div>
<img class='logo' src='/shared/onionr-icon.png' alt='onionr logo'>
<span class='logoText'>Onionr Web Control Panel</span>
<div class='content'> <div class='content'>
<img class='logo' src='/shared/onionr-icon.png' alt='onionr logo'>
<span class='logoText'>Onionr Web Control Panel</span>
<br><br>
<button id='shutdownNode'>Shutdown Node</button> <button id='refreshStats'>Refresh Stats</button> <button id='shutdownNode'>Shutdown Node</button> <button id='refreshStats'>Refresh Stats</button>
<br><br><a class='idLink' href='/mail/'>Mail</a> <br><br><a class='idLink' href='/mail/'>Mail</a> - <a class='idLink' href='/friends/'>Friend Manager</a>
<h2>Stats</h2> <h2>Stats</h2>
<p>Uptime: <span id='uptime'></span></p> <p>Uptime: <span id='uptime'></span></p>
<p>Last Received Connection: <span id='lastIncoming'>Unknown</span></p> <p>Last Received Connection: <span id='lastIncoming'>Unknown</span></p>

View File

@ -13,7 +13,6 @@ c = core.Core()
class OnionrBlockTests(unittest.TestCase): class OnionrBlockTests(unittest.TestCase):
def test_plaintext_insert(self): def test_plaintext_insert(self):
return
message = 'hello world' message = 'hello world'
c.insertBlock(message) c.insertBlock(message)