Create shared inbox on start of daemon

master
Bob Mottram 2019-07-05 12:27:18 +01:00
parent 810dad25da
commit 509ba6b840
5 changed files with 56 additions and 26 deletions

View File

@ -11,6 +11,7 @@ import hashlib
import binascii import binascii
import os import os
import shutil import shutil
import random
def hashPassword(password: str) -> str: def hashPassword(password: str) -> str:
"""Hash a password for storing """Hash a password for storing
@ -135,3 +136,7 @@ def authorize(baseDir: str,path: str,authHeader: str,debug: bool) -> bool:
if authHeader.lower().startswith('basic '): if authHeader.lower().startswith('basic '):
return authorizeBasic(baseDir,path,authHeader,debug) return authorizeBasic(baseDir,path,authHeader,debug)
return False return False
def createPassword(length=10):
validChars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
return ''.join((random.choice(validChars) for i in range(length)))

View File

@ -144,6 +144,26 @@ class PubServer(BaseHTTPRequestHandler):
savePostToBox(self.server.baseDir,postId,self.postToNickname,self.server.domain,messageJson,'outbox') savePostToBox(self.server.baseDir,postId,self.postToNickname,self.server.domain,messageJson,'outbox')
return True return True
def _updateInboxQueue(nickname: str,messageJson: {}) -> bool:
"""Update the inbox queue
"""
cacheFilename = \
savePostToInboxQueue(self.server.baseDir, \
self.server.httpPrefix, \
nickname, \
self.server.domain, \
messageJson,
self.headers['host'],
self.headers['signature'])
if cacheFilename:
if cacheFilename not in self.server.inboxQueue:
self.server.inboxQueue.append(cacheFilename)
self.send_response(201)
self.end_headers()
self.server.POSTbusy=False
return True
return False
def do_GET(self): def do_GET(self):
if self.server.debug: if self.server.debug:
print('DEBUG: GET from '+self.server.baseDir+' path: '+self.path+' busy: '+str(self.server.GETbusy)) print('DEBUG: GET from '+self.server.baseDir+' path: '+self.path+' busy: '+str(self.server.GETbusy))
@ -384,20 +404,7 @@ class PubServer(BaseHTTPRequestHandler):
else: else:
self.postToNickname=pathUsersSection.split('/')[0] self.postToNickname=pathUsersSection.split('/')[0]
if self.postToNickname: if self.postToNickname:
cacheFilename = \ if _updateInboxQueue(self.postToNickname,messageJson):
savePostToInboxQueue(self.server.baseDir, \
self.server.httpPrefix, \
self.postToNickname, \
self.server.domain, \
messageJson,
self.headers['host'],
self.headers['signature'])
if cacheFilename:
if cacheFilename not in self.server.inboxQueue:
self.server.inboxQueue.append(cacheFilename)
self.send_response(201)
self.end_headers()
self.server.POSTbusy=False
return return
self.send_response(403) self.send_response(403)
self.end_headers() self.end_headers()
@ -406,10 +413,8 @@ class PubServer(BaseHTTPRequestHandler):
else: else:
if self.path == '/sharedInbox': if self.path == '/sharedInbox':
print('DEBUG: POST to shared inbox') print('DEBUG: POST to shared inbox')
self.send_response(201) if _updateInboxQueue('sharedinbox',messageJson):
self.end_headers() return
self.server.POSTbusy=False
return
self.send_response(200) self.send_response(200)
self.end_headers() self.end_headers()
self.server.POSTbusy=False self.server.POSTbusy=False

View File

@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
__status__ = "Production" __status__ = "Production"
from person import createPerson from person import createPerson
from person import createSharedInbox
from person import setPreferredNickname from person import setPreferredNickname
from person import setBio from person import setBio
from webfinger import webfingerHandle from webfinger import webfingerHandle
@ -40,6 +41,7 @@ from config import setConfigParam
from config import getConfigParam from config import getConfigParam
from auth import storeBasicCredentials from auth import storeBasicCredentials
from auth import removePassword from auth import removePassword
from auth import createPassword
import argparse import argparse
def str2bool(v): def str2bool(v):
@ -263,6 +265,13 @@ if federationList:
if not os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain): if not os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
print('Creating default admin account '+nickname+'@'+domain) print('Creating default admin account '+nickname+'@'+domain)
createPerson(baseDir,nickname,domain,port,httpPrefix,True) print('See config.json for the password. You can remove the password from config.json after moving it elsewhere.')
adminPassword=createPassword(10)
setConfigParam(baseDir,'adminPassword',adminPassword)
createPerson(baseDir,nickname,domain,port,httpPrefix,True,adminPassword)
if not os.path.isdir(baseDir+'/accounts/sharedinbox@'+domain):
print('Creating shared inbox')
createSharedInbox(baseDir,'sharedinbox',domain,port,httpPrefix)
runDaemon(baseDir,domain,port,httpPrefix,federationList,useTor,debug) runDaemon(baseDir,domain,port,httpPrefix,federationList,useTor,debug)

View File

@ -101,7 +101,7 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str
currTime=datetime.datetime.utcnow() currTime=datetime.datetime.utcnow()
published=currTime.strftime("%Y-%m-%dT%H:%M:%SZ") published=currTime.strftime("%Y-%m-%dT%H:%M:%SZ")
inboxQueueDir = createInboxQueueDir(nickname,domain,baseDir) inboxQueueDir=createInboxQueueDir(nickname,domain,baseDir)
handle=nickname+'@'+domain handle=nickname+'@'+domain
destination=baseDir+'/accounts/'+handle+'/inbox/'+postId.replace('/','#')+'.json' destination=baseDir+'/accounts/'+handle+'/inbox/'+postId.replace('/','#')+'.json'

View File

@ -22,12 +22,10 @@ def generateRSAKey() -> (str,str):
publicKeyPem = key.publickey().exportKey("PEM").decode("utf-8") publicKeyPem = key.publickey().exportKey("PEM").decode("utf-8")
return privateKeyPem,publicKeyPem return privateKeyPem,publicKeyPem
def createPerson(baseDir: str,nickname: str,domain: str,port: int, \ def createPersonBase(baseDir: str,nickname: str,domain: str,port: int, \
httpPrefix: str, saveToFile: bool,password=None) -> (str,str,{},{}): httpPrefix: str, saveToFile: bool,password=None) -> (str,str,{},{}):
"""Returns the private key, public key, actor and webfinger endpoint """Returns the private key, public key, actor and webfinger endpoint
""" """
if not validNickname(nickname):
return None,None,None,None
privateKeyPem,publicKeyPem=generateRSAKey() privateKeyPem,publicKeyPem=generateRSAKey()
webfingerEndpoint= \ webfingerEndpoint= \
createWebfingerEndpoint(nickname,domain,port,httpPrefix,publicKeyPem) createWebfingerEndpoint(nickname,domain,port,httpPrefix,publicKeyPem)
@ -116,12 +114,26 @@ def createPerson(baseDir: str,nickname: str,domain: str,port: int, \
return privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint return privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint
def createPerson(baseDir: str,nickname: str,domain: str,port: int, \
httpPrefix: str, saveToFile: bool,password=None) -> (str,str,{},{}):
"""Returns the private key, public key, actor and webfinger endpoint
"""
if not validNickname(nickname):
return None,None,None,None
return createPersonBase(baseDir,nickname,domain,port,httpPrefix,saveToFile,password)
def createSharedInbox(baseDir: str,nickname: str,domain: str,port: int, \
httpPrefix: str) -> (str,str,{},{}):
"""Generates the shared inbox
"""
return createPersonBase(baseDir,nickname,domain,port,httpPrefix,True,None)
def validNickname(nickname: str) -> bool: def validNickname(nickname: str) -> bool:
forbiddenChars=['.',' ','/','?',':',';','@'] forbiddenChars=['.',' ','/','?',':',';','@']
for c in forbiddenChars: for c in forbiddenChars:
if c in nickname: if c in nickname:
return False return False
reservedNames=['inbox','outbox','following','followers','sharedInbox'] reservedNames=['inbox','outbox','following','followers','sharedinbox']
if nickname in reservedNames: if nickname in reservedNames:
return False return False
return True return True
@ -276,4 +288,3 @@ def setBio(baseDir: str,nickname: str, domain: str, bio: str) -> bool:
with open(filename, 'w') as fp: with open(filename, 'w') as fp:
commentjson.dump(personJson, fp, indent=4, sort_keys=False) commentjson.dump(personJson, fp, indent=4, sort_keys=False)
return True return True