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

refactorinsert
Kevin Froman 3 years ago
parent ad94c8a4ef
commit 45ddbe5e69
  1. 2
      README.md
  2. 0
      docs/http-api.md
  3. 3
      docs/specs/block-spec.md
  4. 14
      onionr/api.py
  5. 28
      onionr/httpapi/profilesapi/__init__.py
  6. 2
      onionr/httpapi/profilesapi/profiles.py
  7. 2
      onionr/static-data/bootstrap-nodes.txt
  8. 23
      onionr/static-data/default-plugins/pms/mailapi.py
  9. 4
      onionr/static-data/default_config.json
  10. 5
      onionr/static-data/www/mail/index.html
  11. 2
      onionr/static-data/www/mail/mail.css
  12. 42
      onionr/static-data/www/mail/mail.js
  13. 20
      onionr/static-data/www/profiles/index.html
  14. 0
      onionr/static-data/www/profiles/profiles.js

@ -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.
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)
## Main Features

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

@ -26,7 +26,7 @@ import core
from onionrblockapi import Block
import onionrutils, onionrexceptions, onionrcrypto, blockimporter, onionrevents as events, logger, config
import httpapi
from httpapi import friendsapi, simplecache
from httpapi import friendsapi, simplecache, profilesapi
from onionrservices import httpheaders
import onionr
@ -256,7 +256,8 @@ class API:
self.bindPort = bindPort
# 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.timeBypassToken = base64.b16encode(os.urandom(32)).decode()
@ -272,6 +273,7 @@ class API:
onionrInst.setClientAPIInst(self)
app.register_blueprint(friendsapi.friends)
app.register_blueprint(simplecache.simplecache)
app.register_blueprint(profilesapi.profile_BP)
httpapi.load_plugin_blueprints(app)
@app.before_request
@ -318,6 +320,14 @@ class API:
@app.route('/friends/', endpoint='friendsindex')
def loadContacts():
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>')
def serviceActive(pubkey):

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

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

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

@ -42,24 +42,39 @@ def mail_delete(block):
if block not in existing:
existing.append(block)
kv.put('deleted_mail', existing)
kv.flush()
return 'success'
@flask_blueprint.route('/mail/getinbox')
def list_inbox():
return ','.join(loadinbox.load_inbox(c))
@flask_blueprint.route('/mail/getsentbox')
def list_sentbox():
kv.refresh()
sentbox_list = sentboxdb.SentBox(c).listSent()
list_copy = list(sentbox_list)
deleted = kv.get('deleted_mail')
if deleted is None:
deleted = []
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) - 1):
for x in range(len(sentbox_list_copy)):
if sentbox_list_copy[x]['hash'] in deleted:
x -= 1
sentbox_list.pop(x)
sentbox_list.remove(sentbox_list_copy[x]['hash'])
else:
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)
'''

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

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

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

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

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save