fixes for mail, work on specs, and added files for profile viewer

This commit is contained in:
Kevin Froman 2019-04-09 12:30:54 -05:00
parent ad94c8a4ef
commit 45ddbe5e69
14 changed files with 119 additions and 32 deletions

View File

@ -27,6 +27,8 @@ Users are identified by ed25519 public keys, which can be used to sign blocks or
Onionr can be used for mail, as a social network, instant messenger, file sharing software, or for encrypted group discussion. Onionr can be used for mail, as a social network, instant messenger, file sharing software, or for encrypted group discussion.
The whitepaper (subject to change prior to first alpha release) is available [here](docs/whitepaper.md).
![Tor stinks slide image](docs/tor-stinks-02.png) ![Tor stinks slide image](docs/tor-stinks-02.png)
## Main Features ## Main Features

View File

@ -6,8 +6,7 @@ Onionr 'Blocks' are the primary means of sharing information in Onionr. Blocks a
They contain a JSON metadata section followed by a line break, with the main data following. They contain a JSON metadata section followed by a line break, with the main data following.
In the future, the spec will be updated to use flags and MessagePack instead of JSON with english keys. In the future, the specification will likely be updated to use flags and MessagePack instead of JSON with english keys.
# Encryption and Signatures # Encryption and Signatures

View File

@ -26,7 +26,7 @@ import core
from onionrblockapi import Block from onionrblockapi import Block
import onionrutils, onionrexceptions, onionrcrypto, blockimporter, onionrevents as events, logger, config import onionrutils, onionrexceptions, onionrcrypto, blockimporter, onionrevents as events, logger, config
import httpapi import httpapi
from httpapi import friendsapi, simplecache from httpapi import friendsapi, simplecache, profilesapi
from onionrservices import httpheaders from onionrservices import httpheaders
import onionr import onionr
@ -256,7 +256,8 @@ 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', 'friends', 'friendsindex') self.whitelistEndpoints = ('site', 'www', 'onionrhome', 'board', 'profiles', 'profilesindex',
'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()
@ -272,6 +273,7 @@ class API:
onionrInst.setClientAPIInst(self) onionrInst.setClientAPIInst(self)
app.register_blueprint(friendsapi.friends) app.register_blueprint(friendsapi.friends)
app.register_blueprint(simplecache.simplecache) app.register_blueprint(simplecache.simplecache)
app.register_blueprint(profilesapi.profile_BP)
httpapi.load_plugin_blueprints(app) httpapi.load_plugin_blueprints(app)
@app.before_request @app.before_request
@ -319,6 +321,14 @@ class API:
def loadContacts(): def loadContacts():
return send_from_directory('static-data/www/friends/', 'index.html') return send_from_directory('static-data/www/friends/', 'index.html')
@app.route('/profiles/<path:path>', endpoint='profiles')
def loadContacts(path):
return send_from_directory('static-data/www/profiles/', path)
@app.route('/profiles/', endpoint='profilesindex')
def loadContacts():
return send_from_directory('static-data/www/profiles/', 'index.html')
@app.route('/serviceactive/<pubkey>') @app.route('/serviceactive/<pubkey>')
def serviceActive(pubkey): def serviceActive(pubkey):
try: try:

View File

@ -0,0 +1,28 @@
'''
Onionr - P2P Anonymous Storage Network
This file creates http endpoints for user profile pages
'''
'''
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 flask import Blueprint, Response, request, abort
from . import profiles
profile_BP = Blueprint('profile_BP', __name__)
@profile_BP.route('/profile/get/<pubkey>', endpoint='profiles')
def get_profile_page(pubkey):
return Response(pubkey)

View File

@ -0,0 +1,2 @@
def get_latest_user_profile(pubkey):
return ''

View File

@ -1 +1 @@
huei7fugyuesltkf3yzj27an36skz2f2u55g7ganyaq6yjhauwicwfyd.onion ecaufnpxx67xmvzwcriohapmmnqbj665h3ynemvwrr2juxl5oa5g7cad.onion

View File

@ -42,6 +42,7 @@ def mail_delete(block):
if block not in existing: if block not in existing:
existing.append(block) existing.append(block)
kv.put('deleted_mail', existing) kv.put('deleted_mail', existing)
kv.flush()
return 'success' return 'success'
@flask_blueprint.route('/mail/getinbox') @flask_blueprint.route('/mail/getinbox')
@ -50,16 +51,30 @@ def list_inbox():
@flask_blueprint.route('/mail/getsentbox') @flask_blueprint.route('/mail/getsentbox')
def list_sentbox(): def list_sentbox():
kv.refresh()
sentbox_list = sentboxdb.SentBox(c).listSent() sentbox_list = sentboxdb.SentBox(c).listSent()
sentbox_list_copy = list(sentbox_list) list_copy = list(sentbox_list)
deleted = kv.get('deleted_mail') deleted = kv.get('deleted_mail')
if deleted is None: if deleted is None:
deleted = [] deleted = []
for x in range(len(sentbox_list_copy) - 1): for x in list_copy:
if x['hash'] in deleted:
sentbox_list.remove(x)
return json.dumps(sentbox_list)
'''
@flask_blueprint.route('/mail/getsentbox')
def list_sentbox():
sentbox_list = sentboxdb.SentBox(c).listSent()
sentbox_list_copy = list(sentbox_list)
kv.refresh()
deleted = kv.get('deleted_mail')
if deleted is None:
deleted = []
for x in range(len(sentbox_list_copy)):
if sentbox_list_copy[x]['hash'] in deleted: if sentbox_list_copy[x]['hash'] in deleted:
x -= 1 sentbox_list.remove(sentbox_list_copy[x]['hash'])
sentbox_list.pop(x)
else: else:
sentbox_list[x]['name'] = contactmanager.ContactManager(c, sentbox_list_copy[x]['peer'], saveUser=False).get_info('name') sentbox_list[x]['name'] = contactmanager.ContactManager(c, sentbox_list_copy[x]['peer'], saveUser=False).get_info('name')
return json.dumps(sentbox_list) return json.dumps(sentbox_list)
'''

View File

@ -4,12 +4,12 @@
"display_header" : false, "display_header" : false,
"minimum_block_pow": 4, "minimum_block_pow": 4,
"minimum_send_pow": 4, "minimum_send_pow": 4,
"socket_servers": true, "socket_servers": false,
"security_level": 0, "security_level": 0,
"max_block_age": 2678400, "max_block_age": 2678400,
"bypass_tor_check": false, "bypass_tor_check": false,
"public_key": "", "public_key": "",
"random_bind_ip": true "random_bind_ip": false
}, },
"www" : { "www" : {

View File

@ -36,8 +36,11 @@
<div> <div>
From: <input type='text' id='fromUser' readonly> Signature: <span id='sigValid'></span> From: <input type='text' id='fromUser' readonly> Signature: <span id='sigValid'></span>
</div> </div>
<div class='break-up'>
Subject: <span id='subjectView'></span>
</div>
<div> <div>
<button id='replyBtn' class='primaryBtn'>Reply</button> <button id='replyBtn' class='primaryBtn break-up'>Reply</button>
</div> </div>
<div id='signatureValidity'></div> <div id='signatureValidity'></div>
<div id='threadDisplay' class='pre messageContent'> <div id='threadDisplay' class='pre messageContent'>

View File

@ -92,7 +92,7 @@ input{
color: black; color: black;
} }
#replyBtn{ .break-up{
margin-top: 1em; margin-top: 1em;
} }

View File

@ -26,7 +26,7 @@ threadContent = {}
myPub = httpGet('/getActivePubkey') myPub = httpGet('/getActivePubkey')
replyBtn = document.getElementById('replyBtn') replyBtn = document.getElementById('replyBtn')
function openReply(bHash){ function openReply(bHash, quote, subject){
var inbox = document.getElementsByClassName('threadEntry') var inbox = document.getElementsByClassName('threadEntry')
var entry = '' var entry = ''
var friendName = '' var friendName = ''
@ -41,13 +41,23 @@ function openReply(bHash){
} }
key = entry.getAttribute('data-pubkey') key = entry.getAttribute('data-pubkey')
document.getElementById('draftID').value = key document.getElementById('draftID').value = key
document.getElementById('draftSubject').value = 'RE: ' + subject
// Add quoted reply
var splitQuotes = quote.split('\n')
for (var x = 0; x < splitQuotes.length; x++){
splitQuotes[x] = '>' + splitQuotes[x]
}
quote = splitQuotes.join('\n')
document.getElementById('draftText').value = quote
setActiveTab('send message') setActiveTab('send message')
} }
function openThread(bHash, sender, date, sigBool, pubkey){ function openThread(bHash, sender, date, sigBool, pubkey, subjectLine){
var messageDisplay = document.getElementById('threadDisplay') var messageDisplay = document.getElementById('threadDisplay')
var blockContent = httpGet('/getblockbody/' + bHash) var blockContent = httpGet('/getblockbody/' + bHash)
document.getElementById('fromUser').value = sender document.getElementById('fromUser').value = sender
document.getElementById('subjectView').innerText = subjectLine
messageDisplay.innerText = blockContent messageDisplay.innerText = blockContent
var sigEl = document.getElementById('sigValid') var sigEl = document.getElementById('sigValid')
var sigMsg = 'signature' var sigMsg = 'signature'
@ -64,7 +74,7 @@ function openThread(bHash, sender, date, sigBool, pubkey){
sigEl.innerText = sigMsg sigEl.innerText = sigMsg
overlay('messageDisplay') overlay('messageDisplay')
replyBtn.onclick = function(){ replyBtn.onclick = function(){
openReply(bHash) openReply(bHash, messageDisplay.innerText, subjectLine)
} }
} }
@ -174,7 +184,7 @@ function loadInboxEntries(bHash){
if (event.target.classList.contains('deleteBtn')){ if (event.target.classList.contains('deleteBtn')){
return return
} }
openThread(entry.getAttribute('data-hash'), senderInput.value, dateStr.innerText, resp['meta']['validSig'], entry.getAttribute('data-pubkey')) openThread(entry.getAttribute('data-hash'), senderInput.value, dateStr.innerText, resp['meta']['validSig'], entry.getAttribute('data-pubkey'), subjectLine.innerText)
} }
deleteBtn.onclick = function(){ deleteBtn.onclick = function(){
@ -216,7 +226,7 @@ function getSentbox(){
if (keys.length == 0){ if (keys.length == 0){
threadPart.innerHTML = "nothing to show here yet." threadPart.innerHTML = "nothing to show here yet."
} }
for (var i = 0; i < keys.length; i++){ for (var i = 0; i < keys.length; i++) (function(i, resp){
var entry = document.createElement('div') var entry = document.createElement('div')
var obj = resp[i] var obj = resp[i]
var toLabel = document.createElement('span') var toLabel = document.createElement('span')
@ -245,19 +255,18 @@ function getSentbox(){
entry.appendChild(toEl) entry.appendChild(toEl)
entry.appendChild(preview) entry.appendChild(preview)
entry.appendChild(sentDate) entry.appendChild(sentDate)
entry.onclick = (function(tree, el, msg) {return function() {
console.log(resp)
if (! entry.classList.contains('deleteBtn')){
showSentboxWindow(el.value, msg)
}
};})(entry, toEl, message);
deleteBtn.onclick = function(){
entry.parentNode.removeChild(entry);
deleteMessage(entry.getAttribute('data-hash'))
}
threadPart.appendChild(entry) threadPart.appendChild(entry)
}
entry.onclick = function(e){
if (e.target.classList.contains('deleteBtn')){
deleteMessage(e.target.parentNode.getAttribute('data-hash'))
e.target.parentNode.parentNode.removeChild(e.target.parentNode)
return
}
showSentboxWindow()
}
})(i, resp)
threadPart.appendChild(entry) threadPart.appendChild(entry)
}.bind(threadPart)) }.bind(threadPart))
} }
@ -304,7 +313,6 @@ for (var i = 0; i < document.getElementsByClassName('refresh').length; i++){
document.getElementsByClassName('refresh')[i].style.float = 'right' document.getElementsByClassName('refresh')[i].style.float = 'right'
} }
fetch('/friends/list', { fetch('/friends/list', {
headers: { headers: {
"token": webpass "token": webpass

File diff suppressed because one or more lines are too long