diff --git a/auth.py b/auth.py index d5499dd2..f1974df3 100644 --- a/auth.py +++ b/auth.py @@ -11,6 +11,7 @@ import hashlib import binascii import os import shutil +import random def hashPassword(password: str) -> str: """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 '): return authorizeBasic(baseDir,path,authHeader,debug) return False + +def createPassword(length=10): + validChars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' + return ''.join((random.choice(validChars) for i in range(length))) diff --git a/daemon.py b/daemon.py index 586eb0cc..ed189ac9 100644 --- a/daemon.py +++ b/daemon.py @@ -144,6 +144,26 @@ class PubServer(BaseHTTPRequestHandler): savePostToBox(self.server.baseDir,postId,self.postToNickname,self.server.domain,messageJson,'outbox') 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): if self.server.debug: print('DEBUG: GET from '+self.server.baseDir+' path: '+self.path+' busy: '+str(self.server.GETbusy)) @@ -384,20 +404,7 @@ class PubServer(BaseHTTPRequestHandler): else: self.postToNickname=pathUsersSection.split('/')[0] if self.postToNickname: - cacheFilename = \ - 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 + if _updateInboxQueue(self.postToNickname,messageJson): return self.send_response(403) self.end_headers() @@ -406,10 +413,8 @@ class PubServer(BaseHTTPRequestHandler): else: if self.path == '/sharedInbox': print('DEBUG: POST to shared inbox') - self.send_response(201) - self.end_headers() - self.server.POSTbusy=False - return + if _updateInboxQueue('sharedinbox',messageJson): + return self.send_response(200) self.end_headers() self.server.POSTbusy=False diff --git a/epicyon.py b/epicyon.py index d7e81655..9e59ae71 100644 --- a/epicyon.py +++ b/epicyon.py @@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net" __status__ = "Production" from person import createPerson +from person import createSharedInbox from person import setPreferredNickname from person import setBio from webfinger import webfingerHandle @@ -40,6 +41,7 @@ from config import setConfigParam from config import getConfigParam from auth import storeBasicCredentials from auth import removePassword +from auth import createPassword import argparse def str2bool(v): @@ -263,6 +265,13 @@ if federationList: if not os.path.isdir(baseDir+'/accounts/'+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) diff --git a/inbox.py b/inbox.py index 80cd1f4a..ac9d527c 100644 --- a/inbox.py +++ b/inbox.py @@ -101,7 +101,7 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str currTime=datetime.datetime.utcnow() published=currTime.strftime("%Y-%m-%dT%H:%M:%SZ") - inboxQueueDir = createInboxQueueDir(nickname,domain,baseDir) + inboxQueueDir=createInboxQueueDir(nickname,domain,baseDir) handle=nickname+'@'+domain destination=baseDir+'/accounts/'+handle+'/inbox/'+postId.replace('/','#')+'.json' diff --git a/person.py b/person.py index 7be3d061..9c1dd697 100644 --- a/person.py +++ b/person.py @@ -22,12 +22,10 @@ def generateRSAKey() -> (str,str): publicKeyPem = key.publickey().exportKey("PEM").decode("utf-8") return privateKeyPem,publicKeyPem -def createPerson(baseDir: str,nickname: str,domain: str,port: int, \ - httpPrefix: str, saveToFile: bool,password=None) -> (str,str,{},{}): +def createPersonBase(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 privateKeyPem,publicKeyPem=generateRSAKey() webfingerEndpoint= \ 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 +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: forbiddenChars=['.',' ','/','?',':',';','@'] for c in forbiddenChars: if c in nickname: return False - reservedNames=['inbox','outbox','following','followers','sharedInbox'] + reservedNames=['inbox','outbox','following','followers','sharedinbox'] if nickname in reservedNames: return False return True @@ -276,4 +288,3 @@ def setBio(baseDir: str,nickname: str, domain: str, bio: str) -> bool: with open(filename, 'w') as fp: commentjson.dump(personJson, fp, indent=4, sort_keys=False) return True -