Test for follow request

master
Bob Mottram 2019-07-06 14:49:25 +01:00
parent 31ccb80830
commit ef3a951452
7 changed files with 226 additions and 71 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

120
tests.py
View File

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