From ef3a951452ba2eda50a433ce6a26a2ebb4c3f05f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Sat, 6 Jul 2019 14:49:25 +0100 Subject: [PATCH] Test for follow request --- acceptreject.py | 8 ++-- daemon.py | 18 +++++--- epicyon.py | 4 +- follow.py | 66 ++++++++++++++++++-------- inbox.py | 42 +++++++++++------ posts.py | 39 ++++++++++++---- tests.py | 120 +++++++++++++++++++++++++++++++++++++++++------- 7 files changed, 226 insertions(+), 71 deletions(-) diff --git a/acceptreject.py b/acceptreject.py index 9c954558..fcf496d1 100644 --- a/acceptreject.py +++ b/acceptreject.py @@ -36,8 +36,8 @@ def createAcceptReject(baseDir: str,federationList: [],capsList: [],nickname: st newAccept['cc']=ccUrl return newAccept -def createAccept(baseDir: str,federationList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,httpPrefix: str,objectUrl: str) -> {}: - return createAcceptReject(baseDir,federationList,nickname,domain,port,toUrl,ccUrl,httpPrefix,objectUrl,'Accept') +def createAccept(baseDir: str,federationList: [],capsList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,httpPrefix: str,objectUrl: str) -> {}: + return createAcceptReject(baseDir,federationList,capsList,nickname,domain,port,toUrl,ccUrl,httpPrefix,objectUrl,'Accept') -def createReject(baseDir: str,federationList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,httpPrefix: str,objectUrl: str) -> {}: - return createAcceptReject(baseDir,federationList,nickname,domain,port,toUrl,ccUrl,httpPrefix,objectUrl,'Reject') +def createReject(baseDir: str,federationList: [],capsList: [],nickname: str,domain: str,port: int,toUrl: str,ccUrl: str,httpPrefix: str,objectUrl: str) -> {}: + return createAcceptReject(baseDir,federationList,capsList,nickname,domain,port,toUrl,ccUrl,httpPrefix,objectUrl,'Reject') diff --git a/daemon.py b/daemon.py index 06f75da5..38a37358 100644 --- a/daemon.py +++ b/daemon.py @@ -147,7 +147,7 @@ class PubServer(BaseHTTPRequestHandler): def _updateInboxQueue(self,nickname: str,messageJson: {}) -> bool: """Update the inbox queue """ - cacheFilename = \ + queueFilename = \ savePostToInboxQueue(self.server.baseDir, \ self.server.httpPrefix, \ nickname, \ @@ -155,10 +155,12 @@ class PubServer(BaseHTTPRequestHandler): messageJson, self.headers['host'], self.headers['signature'], - '/'+self.path.split('/')[-1]) - if cacheFilename: - if cacheFilename not in self.server.inboxQueue: - self.server.inboxQueue.append(cacheFilename) + '/'+self.path.split('/')[-1], + self.server.debug) + if queueFilename: + print('**************************************') + if queueFilename not in self.server.inboxQueue: + self.server.inboxQueue.append(queueFilename) self.send_response(201) self.end_headers() self.server.POSTbusy=False @@ -370,6 +372,8 @@ class PubServer(BaseHTTPRequestHandler): if self.path.endswith('/inbox') or \ self.path=='/sharedInbox': if not inboxMessageHasParams(messageJson): + if self.server.debug: + print("DEBUG: inbox message doesn't have the required parameters") self.send_response(403) self.end_headers() self.server.POSTbusy=False @@ -397,7 +401,7 @@ class PubServer(BaseHTTPRequestHandler): return if self.server.debug: - print('DEBUG: POST saving to inbox cache') + print('DEBUG: POST saving to inbox queue') if '/users/' in self.path: pathUsersSection=self.path.split('/users/')[1] if '/' not in pathUsersSection: @@ -452,6 +456,6 @@ def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https',fedList=[],cap httpd.sendThreads=[] httpd.postLog=[] print('Running ActivityPub daemon on ' + domain + ' port ' + str(port)) - httpd.thrInboxQueue=threadWithTrace(target=runInboxQueue,args=(baseDir,httpPrefix,httpd.sendThreads,httpd.postLog,httpd.cachedWebfingers,httpd.personCache,httpd.inboxQueue,domain,port,useTor,httpd.federationList,debug),daemon=True) + httpd.thrInboxQueue=threadWithTrace(target=runInboxQueue,args=(baseDir,httpPrefix,httpd.sendThreads,httpd.postLog,httpd.cachedWebfingers,httpd.personCache,httpd.inboxQueue,domain,port,useTor,httpd.federationList,httpd.capsList,debug),daemon=True) httpd.thrInboxQueue.start() httpd.serve_forever() diff --git a/epicyon.py b/epicyon.py index 81b5f285..2c40c8a0 100644 --- a/epicyon.py +++ b/epicyon.py @@ -40,6 +40,7 @@ from follow import unfollowPerson from follow import unfollowerOfPerson from follow import getFollowersOfPerson from tests import testPostMessageBetweenServers +from tests import testFollowBetweenServers from tests import runAllTests from config import setConfigParam from config import getConfigParam @@ -111,7 +112,8 @@ if args.tests: if args.testsnetwork: print('Network Tests') - testPostMessageBetweenServers() + testFollowBetweenServers() + #testPostMessageBetweenServers() sys.exit() if args.posts: diff --git a/follow.py b/follow.py index 8fbdd1ad..4d58c5d3 100644 --- a/follow.py +++ b/follow.py @@ -14,6 +14,7 @@ from person import validNickname from utils import domainPermitted from posts import sendSignedJson from capabilities import isCapable +from acceptreject import createAccept def getFollowersOfPerson(baseDir: str,nickname: str,domain: str,followFile='following.txt') -> []: """Returns a list containing the followers of the given person @@ -230,58 +231,82 @@ def getFollowingFeed(baseDir: str,domain: str,port: int,path: str,httpPrefix: st following['next']=httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page='+str(lastPage) return following -def receiveFollowRequest(session,baseDir: str,httpPrefix: str,port: int,sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {},messageJson: {},federationList: []) -> bool: +def receiveFollowRequest(session,baseDir: str,httpPrefix: str,port: int,sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {},messageJson: {},federationList: [],capsList: [],debug : bool) -> bool: """Receives a follow request within the POST section of HTTPServer """ - if not messageJson.get('actor'): - return False if not messageJson['type'].startswith('Follow'): return False + if not messageJson.get('actor'): + if debug: + print('DEBUG: follow request has no actor') + return False if '/users/' not in messageJson['actor']: + if debug: + print('DEBUG: "users" missing from actor') return False domain=messageJson['actor'].split('/users/')[0].replace('https://','').replace('http://','').replace('dat://','') + if ':' in domain: + domain=domain.split(':')[0] if not domainPermitted(domain,federationList): + if debug: + print('DEBUG: follower from domain not permitted - '+domain) return False nickname=messageJson['actor'].split('/users/')[1].replace('@','') handle=nickname.lower()+'@'+domain.lower() - if not os.path.isdir(baseDir+'/accounts/'+handle): - return False if '/users/' not in messageJson['object']: + if debug: + print('DEBUG: "users" not found within object') return False domainToFollow=messageJson['object'].split('/users/')[0].replace('https://','').replace('http://','').replace('dat://','') + toPort=port + if ':' in domainToFollow: + toPort=domainToFollow.split(':')[1] + domainToFollow=domainToFollow.split(':')[0] if not domainPermitted(domainToFollow,federationList): + if debug: + print('DEBUG: follow domain not permitted '+domainToFollow) return False nicknameToFollow=messageJson['object'].split('/users/')[1].replace('@','') handleToFollow=nicknameToFollow.lower()+'@'+domainToFollow.lower() if domainToFollow==domain: if not os.path.isdir(baseDir+'/accounts/'+handleToFollow): + if debug: + print('DEBUG: followed account not found - '+baseDir+'/accounts/'+handleToFollow) return False if not followerOfPerson(baseDir,nickname,domain,nicknameToFollow,domainToFollow,federationList): + if debug: + print('DEBUG: '+nickname+'@'+domain+' is already a follower of '+nicknameToFollow+'@'+domainToFollow) return False # send accept back + if debug: + print('DEBUG: sending Accept from '+nickname+'@'+domain+' for follow request') personUrl=messageJson['actor'] - acceptJson=createAccept(baseDir,federationList,nickname,domain,port, \ + acceptJson=createAccept(baseDir,federationList,capsList,nickname,domain,port, \ personUrl,'',httpPrefix,messageJson['object']) + clientToServer=False sendSignedJson(acceptJson,session,baseDir,nickname,domain,port, \ nicknameToFollow,domainToFollow,toPort, '', \ - httpPrefix,saveToFile,clientToServer,federationList, \ - sendThreads,postLog,cachedWebfingers,personCache) + httpPrefix,True,clientToServer, \ + federationList, capsList, \ + sendThreads,postLog,cachedWebfingers,personCache,debug) -def sendFollowRequest(baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \ +def sendFollowRequest(session,baseDir: str,nickname: str,domain: str,port: int,httpPrefix: str, \ followNickname: str,followDomain: str,followPort: bool,followHttpPrefix: str, \ - federationList: [],capsList: []) -> {}: + clientToServer: bool,federationList: [],capsList: [], \ + sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {}, + debug : bool) -> {}: """Gets the json object for sending a follow request - """ + """ if not domainPermitted(followDomain,federationList): return None - + + followActor=httpPrefix+'://'+domain+'/users/'+nickname if port!=80 and port!=443: - domain=domain+':'+str(port) + followActor=httpPrefix+'://'+domain+':'+str(port)+'/users/'+nickname + requestDomain=followDomain if followPort!=80 and followPort!=443: - followDomain=followDomain+':'+str(followPort) - - followActor=httpPrefix+'://'+domain+'/users/'+nickname + requestDomain=followDomain+':'+str(followPort) # check that we are capable if capsList: @@ -291,12 +316,13 @@ def sendFollowRequest(baseDir: str,nickname: str,domain: str,port: int,httpPrefi newFollowJson = { 'type': 'Follow', 'actor': followActor, - 'object': followHttpPrefix+'://'+followDomain+'/users/'+followNickname + 'object': followHttpPrefix+'://'+requestDomain+'/users/'+followNickname } sendSignedJson(newFollowJson,session,baseDir,nickname,domain,port, \ - nicknameToFollow,domainToFollow,toPort, '', \ - httpPrefix,saveToFile,clientToServer,federationList, \ - sendThreads,postLog,cachedWebfingers,personCache) + followNickname,followDomain,followPort, '', \ + httpPrefix,True,clientToServer, \ + federationList, capsList, \ + sendThreads,postLog,cachedWebfingers,personCache, debug) return newFollowJson diff --git a/inbox.py b/inbox.py index b5ee5c99..48626695 100644 --- a/inbox.py +++ b/inbox.py @@ -15,6 +15,7 @@ import commentjson from shutil import copyfile from utils import urlPermitted from utils import createInboxQueueDir +from utils import getStatusNumber from httpsig import verifyPostHeaders from session import createSession from session import getJson @@ -53,10 +54,14 @@ def getPersonPubKey(session,personUrl: str,personCache: {},debug: bool) -> str: def inboxMessageHasParams(messageJson: {}) -> bool: """Checks whether an incoming message contains expected parameters """ - expectedParams=['type','to','actor','object'] + expectedParams=['type','actor','object'] for param in expectedParams: if not messageJson.get(param): return False + if not messageJson.get('to'): + allowedWithoutToParam=['Follow','Request','Capability'] + if messageJson['type'] not in allowedWithoutToParam: + return False return True def inboxPermittedMessage(domain: str,messageJson: {},federationList: [],capsList: []) -> bool: @@ -73,11 +78,12 @@ def inboxPermittedMessage(domain: str,messageJson: {},federationList: [],capsLis if not urlPermitted(actor,federationList,capsList,"inbox:write"): return False - if messageJson.get('object'): - if messageJson['object'].get('inReplyTo'): - inReplyTo=messageJson['object']['inReplyTo'] - if not urlPermitted(inReplyTo,federationList,capsList): - return False + if messageJson['type']!='Follow': + if messageJson.get('object'): + if messageJson['object'].get('inReplyTo'): + inReplyTo=messageJson['object']['inReplyTo'] + if not urlPermitted(inReplyTo,federationList,capsList): + return False return True @@ -89,16 +95,18 @@ def validPublishedDate(published) -> bool: return False return True -def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str,postJson: {},host: str,headers: str,postPath: str) -> str: +def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str,postJson: {},host: str,headers: str,postPath: str,debug: bool) -> str: """Saves the give json to the inbox queue for the person keyId specifies the actor sending the post """ if ':' in domain: domain=domain.split(':')[0] - if not postJson.get('id'): - return None - postId=postJson['id'].replace('/activity','') - + if postJson.get('id'): + postId=postJson['id'].replace('/activity','') + else: + statusNumber,published = getStatusNumber() + postId=httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber + currTime=datetime.datetime.utcnow() published=currTime.strftime("%Y-%m-%dT%H:%M:%SZ") @@ -107,7 +115,8 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str handle=nickname+'@'+domain destination=baseDir+'/accounts/'+handle+'/inbox/'+postId.replace('/','#')+'.json' if os.path.isfile(destination): - # inbox item already exists + if debug: + print('DEBUG: inbox item already exists') return None filename=inboxQueueDir+'/'+postId.replace('/','#')+'.json' @@ -125,12 +134,16 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str 'filename': filename, 'destination': destination } + + if debug: + print('Inbox queue item created') + pprint(newQueueItem) with open(filename, 'w') as fp: commentjson.dump(newQueueItem, fp, indent=4, sort_keys=False) return filename -def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {},queue: [],domain: str,port: int,useTor: bool,federationList: [],debug: bool) -> None: +def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {},queue: [],domain: str,port: int,useTor: bool,federationList: [],capsList: [],debug: bool) -> None: """Processes received items and moves them to the appropriate directories """ @@ -218,7 +231,8 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cache cachedWebfingers, personCache, queueJson['post'], \ - federationList): + federationList,capsList, \ + debug): if debug: print('DEBUG: Follow accepted from '+keyId) os.remove(queueFilename) diff --git a/posts.py b/posts.py index a6c8a6c4..3f16c2db 100644 --- a/posts.py +++ b/posts.py @@ -52,17 +52,21 @@ def noOfFollowersOnDomain(baseDir: str,handle: str, domain: str, followFile='fol ctr+=1 return ctr -def getPersonKey(nickname: str,domain: str,baseDir: str,keyType='public'): +def getPersonKey(nickname: str,domain: str,baseDir: str,keyType='public',debug=False): """Returns the public or private key of a person """ handle=nickname+'@'+domain keyFilename=baseDir+'/keys/'+keyType+'/'+handle.lower()+'.key' if not os.path.isfile(keyFilename): + if debug: + print('DEBUG: private key file not found: '+keyFilename) return '' keyPem='' with open(keyFilename, "r") as pemFile: keyPem=pemFile.read() if len(keyPem)<20: + if debug: + print('DEBUG: private key was too short: '+keyPem) return '' return keyPem @@ -453,7 +457,8 @@ def createPublicPost(baseDir: str, inReplyTo, inReplyToAtomUri, subject) def threadSendPost(session,postJsonObject: {},federationList: [],capsList: [],\ - inboxUrl: str, baseDir: str,signatureHeaderJson: {},postLog: []) -> None: + inboxUrl: str, baseDir: str,signatureHeaderJson: {},postLog: [], + debug :bool) -> None: """Sends a post with exponential backoff """ tries=0 @@ -463,6 +468,8 @@ def threadSendPost(session,postJsonObject: {},federationList: [],capsList: [],\ capsList,inboxUrl,signatureHeaderJson, \ "inbox:write") if postResult: + if debug: + print('DEBUG: json post to '+inboxUrl+' succeeded') postLog.append(postJsonObject['published']+' '+postResult+'\n') # keep the length of the log finite # Don't accumulate massive files on systems with limited resources @@ -475,6 +482,8 @@ def threadSendPost(session,postJsonObject: {},federationList: [],capsList: [],\ print(line, file=logFile) # our work here is done break + if debug: + print('DEBUG: json post to '+inboxUrl+' failed. Waiting for '+str(backoffTime)+' seconds.') time.sleep(backoffTime) backoffTime *= 2 @@ -484,13 +493,14 @@ def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \ saveToFile: bool, clientToServer: bool, \ federationList: [], capsList: [],\ sendThreads: [], postLog: [], cachedWebfingers: {},personCache: {}, \ - inReplyTo=None, inReplyToAtomUri=None, subject=None) -> int: + debug=False,inReplyTo=None,inReplyToAtomUri=None,subject=None) -> int: """Post to another inbox """ withDigest=True if toPort!=80 and toPort!=443: - toDomain=toDomain+':'+str(toPort) + if ':' not in toDomain: + toDomain=toDomain+':'+str(toPort) handle=httpPrefix+'://'+toDomain+'/@'+toNickname @@ -557,7 +567,8 @@ def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \ capsList, \ inboxUrl,baseDir, \ signatureHeaderJson.copy(), \ - postLog),daemon=True) + postLog, + debug),daemon=True) sendThreads.append(thr) thr.start() return 0 @@ -566,19 +577,23 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str,nickname: str, domain toNickname: str, toDomain: str, toPort: int, cc: str, \ httpPrefix: str, saveToFile: bool, clientToServer: bool, \ federationList: [], capsList: [], \ - sendThreads: [], postLog: [], cachedWebfingers: {},personCache: {}) -> int: + sendThreads: [], postLog: [], cachedWebfingers: {},personCache: {}, \ + debug: bool) -> int: """Sends a signed json object to an inbox/outbox """ withDigest=True if toPort!=80 and toPort!=443: - toDomain=toDomain+':'+str(toPort) + if ':' not in toDomain: + toDomain=toDomain+':'+str(toPort) handle=httpPrefix+'://'+toDomain+'/@'+toNickname # lookup the inbox for the To handle wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers) if not wfRequest: + if debug: + print('DEBUG: webfinger for '+handle+' failed') return 1 if not clientToServer: @@ -599,6 +614,9 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str,nickname: str, domain else: if noOfFollowersOnDomain(baseDir,handle,toDomain)>1 and sharedInbox: inboxUrl=sharedInbox + + if debug: + print('DEBUG: Sending to endpoint '+inboxUrl) if not inboxUrl: return 3 @@ -609,8 +627,10 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str,nickname: str, domain # sharedInbox and capabilities are optional # get the senders private key - privateKeyPem=getPersonKey(nickname,domain,baseDir,'private') + privateKeyPem=getPersonKey(nickname,domain,baseDir,'private',debug) if len(privateKeyPem)==0: + if debug: + print('DEBUG: Private key not found for '+nickname+'@'+domain+' in '+baseDir+'/keys/private') return 6 if toDomain not in inboxUrl: @@ -632,7 +652,8 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str,nickname: str, domain capsList, \ inboxUrl,baseDir, \ signatureHeaderJson.copy(), \ - postLog),daemon=True) + postLog, + debug),daemon=True) sendThreads.append(thr) thr.start() return 0 diff --git a/tests.py b/tests.py index b37265c0..e63a5c40 100644 --- a/tests.py +++ b/tests.py @@ -31,6 +31,7 @@ from follow import followerOfPerson from follow import unfollowPerson from follow import unfollowerOfPerson from follow import getFollowersOfPerson +from follow import sendFollowRequest from person import createPerson from person import setPreferredNickname from person import setBio @@ -107,7 +108,7 @@ def testThreads(): thr.join() assert thr.isAlive()==False -def createServerAlice(path: str,domain: str,port: int,federationList: [],capsList: []): +def createServerAlice(path: str,domain: str,port: int,federationList: [],capsList: [],hasFollows: bool,hasPosts :bool): print('Creating test server: Alice on port '+str(port)) if os.path.isdir(path): shutil.rmtree(path) @@ -121,17 +122,19 @@ def createServerAlice(path: str,domain: str,port: int,federationList: [],capsLis privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,nickname,domain,port,httpPrefix,True,password) deleteAllPosts(path,nickname,domain,'inbox') deleteAllPosts(path,nickname,domain,'outbox') - followPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList) - followerOfPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList) - createPublicPost(path,nickname, domain, port,httpPrefix, "No wise fish would go anywhere without a porpoise", False, True, clientToServer,capsList) - createPublicPost(path,nickname, domain, port,httpPrefix, "Curiouser and curiouser!", False, True, clientToServer,capsList) - createPublicPost(path,nickname, domain, port,httpPrefix, "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", False, True, clientToServer,capsList) + if hasFollows: + followPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList) + followerOfPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList) + if hasPosts: + createPublicPost(path,nickname, domain, port,httpPrefix, "No wise fish would go anywhere without a porpoise", False, True, clientToServer,capsList) + createPublicPost(path,nickname, domain, port,httpPrefix, "Curiouser and curiouser!", False, True, clientToServer,capsList) + createPublicPost(path,nickname, domain, port,httpPrefix, "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", False, True, clientToServer,capsList) global testServerAliceRunning testServerAliceRunning = True print('Server running: Alice') runDaemon(path,domain,port,httpPrefix,federationList,capsList,useTor,True) -def createServerBob(path: str,domain: str,port: int,federationList: [],capsList: []): +def createServerBob(path: str,domain: str,port: int,federationList: [],capsList: [],hasFollows: bool,hasPosts :bool): print('Creating test server: Bob on port '+str(port)) if os.path.isdir(path): shutil.rmtree(path) @@ -145,11 +148,13 @@ def createServerBob(path: str,domain: str,port: int,federationList: [],capsList: privateKeyPem,publicKeyPem,person,wfEndpoint=createPerson(path,nickname,domain,port,httpPrefix,True,password) deleteAllPosts(path,nickname,domain,'inbox') deleteAllPosts(path,nickname,domain,'outbox') - followPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList) - followerOfPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList) - createPublicPost(path,nickname, domain, port,httpPrefix, "It's your life, live it your way.", False, True, clientToServer,capsList) - createPublicPost(path,nickname, domain, port,httpPrefix, "One of the things I've realised is that I am very simple", False, True, clientToServer,capsList) - createPublicPost(path,nickname, domain, port,httpPrefix, "Quantum physics is a bit of a passion of mine", False, True, clientToServer,capsList) + if hasFollows: + followPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList) + followerOfPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList) + if hasPosts: + createPublicPost(path,nickname, domain, port,httpPrefix, "It's your life, live it your way.", False, True, clientToServer,capsList) + createPublicPost(path,nickname, domain, port,httpPrefix, "One of the things I've realised is that I am very simple", False, True, clientToServer,capsList) + createPublicPost(path,nickname, domain, port,httpPrefix, "Quantum physics is a bit of a passion of mine", False, True, clientToServer,capsList) global testServerBobRunning testServerBobRunning = True print('Server running: Bob') @@ -169,19 +174,20 @@ def testPostMessageBetweenServers(): capsList=[] baseDir=os.getcwd() - if not os.path.isdir(baseDir+'/.tests'): - os.mkdir(baseDir+'/.tests') + if os.path.isdir(baseDir+'/.tests'): + shutil.rmtree(baseDir+'/.tests') + os.mkdir(baseDir+'/.tests') # create the servers aliceDir=baseDir+'/.tests/alice' aliceDomain='127.0.0.50' alicePort=61935 - thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,capsList),daemon=True) + thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,capsList,True,True),daemon=True) bobDir=baseDir+'/.tests/bob' bobDomain='127.0.0.100' bobPort=61936 - thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,capsList),daemon=True) + thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,capsList,True,True),daemon=True) thrAlice.start() thrBob.start() @@ -237,6 +243,88 @@ def testPostMessageBetweenServers(): shutil.rmtree(aliceDir) shutil.rmtree(bobDir) +def testFollowBetweenServers(): + print('Testing sending a follow request from one server to another') + + global testServerAliceRunning + global testServerBobRunning + testServerAliceRunning = False + testServerBobRunning = False + + httpPrefix='http' + useTor=False + federationList=['127.0.0.42','127.0.0.64'] + capsList=[] + + baseDir=os.getcwd() + if os.path.isdir(baseDir+'/.tests'): + shutil.rmtree(baseDir+'/.tests') + os.mkdir(baseDir+'/.tests') + + # create the servers + aliceDir=baseDir+'/.tests/alice' + aliceDomain='127.0.0.42' + alicePort=61935 + thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,capsList,False,False),daemon=True) + + bobDir=baseDir+'/.tests/bob' + bobDomain='127.0.0.64' + bobPort=61936 + thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,capsList,False,False),daemon=True) + + thrAlice.start() + thrBob.start() + assert thrAlice.isAlive()==True + assert thrBob.isAlive()==True + + # wait for both servers to be running + while not (testServerAliceRunning and testServerBobRunning): + time.sleep(1) + + time.sleep(1) + + # In the beginning all was calm and there were no follows + + print('Alice sends a follow request to Bob') + os.chdir(aliceDir) + sessionAlice = createSession(aliceDomain,alicePort,useTor) + inReplyTo=None + inReplyToAtomUri=None + subject=None + aliceSendThreads = [] + alicePostLog = [] + followersOnly=False + saveToFile=True + clientToServer=False + ccUrl=None + alicePersonCache={} + aliceCachedWebfingers={} + aliceSendThreads=[] + alicePostLog=[] + sendResult = \ + sendFollowRequest(sessionAlice,aliceDir, \ + 'alice',aliceDomain,alicePort,httpPrefix, \ + 'bob',bobDomain,bobPort,httpPrefix, \ + clientToServer,federationList,capsList, + aliceSendThreads,alicePostLog, \ + aliceCachedWebfingers,alicePersonCache,True) + print('sendResult: '+str(sendResult)) + + time.sleep(10) + + + # stop the servers + thrAlice.kill() + thrAlice.join() + assert thrAlice.isAlive()==False + + thrBob.kill() + thrBob.join() + assert thrBob.isAlive()==False + + os.chdir(baseDir) + #shutil.rmtree(baseDir+'/.tests') + def testFollowersOfPerson(): print('testFollowersOfPerson') currDir=os.getcwd()