Test for post deletion

master
Bob Mottram 2019-07-17 18:16:48 +01:00
parent 89c1c01f82
commit 27908a5fad
5 changed files with 186 additions and 18 deletions

View File

@ -35,6 +35,7 @@ from auth import createPassword
from threads import threadWithTrace from threads import threadWithTrace
from media import getMediaPath from media import getMediaPath
from media import createMediaDirs from media import createMediaDirs
from delete import outboxDelete
import os import os
import sys import sys
@ -179,6 +180,7 @@ class PubServer(BaseHTTPRequestHandler):
postId=None postId=None
if self.server.debug: if self.server.debug:
pprint(messageJson) pprint(messageJson)
print('DEBUG: savePostToBox')
savePostToBox(self.server.baseDir, \ savePostToBox(self.server.baseDir, \
self.server.httpPrefix, \ self.server.httpPrefix, \
postId, \ postId, \
@ -204,6 +206,9 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.debug: if self.server.debug:
print('DEBUG: handle any unfollow requests') print('DEBUG: handle any unfollow requests')
outboxUndoFollow(self.server.baseDir,messageJson,self.server.debug) outboxUndoFollow(self.server.baseDir,messageJson,self.server.debug)
if self.server.debug:
print('DEBUG: handle delete requests')
outboxDelete(self.server.baseDir,self.server.httpPrefix,messageJson,self.server.debug)
if self.server.debug: if self.server.debug:
print('DEBUG: sending c2s post to named addresses') print('DEBUG: sending c2s post to named addresses')
print('c2s sender: '+self.postToNickname+'@'+self.server.domain+':'+str(self.server.port)) print('c2s sender: '+self.postToNickname+'@'+self.server.domain+':'+str(self.server.port))

131
delete.py
View File

@ -14,7 +14,13 @@ from utils import createOutboxDir
from utils import urlPermitted from utils import urlPermitted
from utils import getNicknameFromActor from utils import getNicknameFromActor
from utils import getDomainFromActor from utils import getDomainFromActor
from utils import locatePost
from utils import deletePost
from posts import sendSignedJson from posts import sendSignedJson
from session import postJson
from webfinger import webfingerHandle
from auth import createBasicAuthHeader
from posts import getPersonBox
def createDelete(session,baseDir: str,federationList: [], \ def createDelete(session,baseDir: str,federationList: [], \
nickname: str, domain: str, port: int, \ nickname: str, domain: str, port: int, \
@ -72,6 +78,73 @@ def createDelete(session,baseDir: str,federationList: [], \
return newDelete return newDelete
def sendDeleteViaServer(session,fromNickname: str,password: str,
fromDomain: str,fromPort: int, \
httpPrefix: str,deleteObjectUrl: str, \
cachedWebfingers: {},personCache: {}, \
debug: bool) -> {}:
"""Creates a delete request message via c2s
"""
if not session:
print('WARN: No session for sendDeleteViaServer')
return 6
fromDomainFull=fromDomain
if fromPort!=80 and fromPort!=443:
fromDomainFull=fromDomain+':'+str(fromPort)
toUrl = 'https://www.w3.org/ns/activitystreams#Public'
ccUrl = httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers'
newDeleteJson = {
'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname,
'cc': [ccUrl],
'object': deleteObjectUrl,
'to': [toUrl],
'type': 'Delete'
}
handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname
# lookup the inbox for the To handle
wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers)
if not wfRequest:
if debug:
print('DEBUG: announce webfinger failed for '+handle)
return 1
postToBox='outbox'
# get the actor inbox for the To handle
inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition = \
getPersonBox(session,wfRequest,personCache,postToBox)
if not inboxUrl:
if debug:
print('DEBUG: No '+postToBox+' was found for '+handle)
return 3
if not fromPersonId:
if debug:
print('DEBUG: No actor was found for '+handle)
return 4
authHeader=createBasicAuthHeader(fromNickname,password)
headers = {'host': fromDomain, \
'Content-type': 'application/json', \
'Authorization': authHeader}
postResult = \
postJson(session,newDeleteJson,[],inboxUrl,headers,"inbox:write")
#if not postResult:
# if debug:
# print('DEBUG: POST announce failed for c2s to '+inboxUrl)
# return 5
if debug:
print('DEBUG: c2s POST delete request success')
return newDeleteJson
def deletePublic(session,baseDir: str,federationList: [], \ def deletePublic(session,baseDir: str,federationList: [], \
nickname: str, domain: str, port: int, httpPrefix: str, \ nickname: str, domain: str, port: int, httpPrefix: str, \
objectUrl: str,clientToServer: bool, \ objectUrl: str,clientToServer: bool, \
@ -95,14 +168,14 @@ def deletePublic(session,baseDir: str,federationList: [], \
personCache,cachedWebfingers, \ personCache,cachedWebfingers, \
debug) debug)
def deletePost(session,baseDir: str,federationList: [], \ def deletePostPub(session,baseDir: str,federationList: [], \
nickname: str, domain: str, port: int, httpPrefix: str, \ nickname: str, domain: str, port: int, httpPrefix: str, \
deleteNickname: str, deleteDomain: str, \ deleteNickname: str, deleteDomain: str, \
deletePort: int, deleteHttpsPrefix: str, \ deletePort: int, deleteHttpsPrefix: str, \
deleteStatusNumber: int,clientToServer: bool, \ deleteStatusNumber: int,clientToServer: bool, \
sendThreads: [],postLog: [], \ sendThreads: [],postLog: [], \
personCache: {},cachedWebfingers: {}, \ personCache: {},cachedWebfingers: {}, \
debug: bool) -> {}: debug: bool) -> {}:
"""Deletes a given status post """Deletes a given status post
""" """
deletedDomain=deleteDomain deletedDomain=deleteDomain
@ -120,3 +193,45 @@ def deletePost(session,baseDir: str,federationList: [], \
personCache,cachedWebfingers, \ personCache,cachedWebfingers, \
debug) debug)
def outboxDelete(baseDir: str,httpPrefix: str,messageJson: {},debug: bool) -> None:
"""When a delete request is received by the outbox from c2s
"""
if not messageJson.get('type'):
if debug:
print('DEBUG: delete - no type')
return
if not messageJson['type']=='Delete':
if debug:
print('DEBUG: not a delete')
return
if not messageJson.get('object'):
if debug:
print('DEBUG: no object in delete')
return
if not isinstance(messageJson['object'], str):
if debug:
print('DEBUG: delete object is not string')
return
if debug:
print('DEBUG: c2s delete request arrived in outbox')
messageId=messageJson['object'].replace('/activity','')
if '/statuses/' not in messageId:
if debug:
print('DEBUG: c2s delete object is not a status')
return
if '/users/' not in messageId:
if debug:
print('DEBUG: c2s delete object has no nickname')
return
deleteNickname=getNicknameFromActor(messageId)
deleteDomain,deletePort=getDomainFromActor(messageId)
postFilename=locatePost(baseDir,deleteNickname,deleteDomain,messageId)
if not postFilename:
if debug:
print('DEBUG: c2s delete post not found in inbox or outbox')
print(messageId)
return True
deletePost(baseDir,httpPrefix,deleteNickname,deleteDomain,postFilename,debug)
if debug:
print('DEBUG: post deleted via c2s - '+postFilename)

View File

@ -62,6 +62,7 @@ from auth import createPassword
from utils import getDomainFromActor from utils import getDomainFromActor
from utils import getNicknameFromActor from utils import getNicknameFromActor
from media import archiveMedia from media import archiveMedia
from delete import sendDeleteViaServer
import argparse import argparse
def str2bool(v): def str2bool(v):
@ -218,8 +219,8 @@ if args.tests:
if args.testsnetwork: if args.testsnetwork:
print('Network Tests') print('Network Tests')
testPostMessageBetweenServers() #testPostMessageBetweenServers()
testFollowBetweenServers() #testFollowBetweenServers()
testClientToServer() testClientToServer()
sys.exit() sys.exit()

View File

@ -623,6 +623,8 @@ def receiveDelete(session,handle: str,baseDir: str, \
if debug: if debug:
print('DEBUG: '+messageJson['type']+' has no actor') print('DEBUG: '+messageJson['type']+' has no actor')
return False return False
if debug:
print('DEBUG: Delete activity arrived')
if not messageJson.get('object'): if not messageJson.get('object'):
if debug: if debug:
print('DEBUG: '+messageJson['type']+' has no object') print('DEBUG: '+messageJson['type']+' has no object')
@ -649,11 +651,12 @@ def receiveDelete(session,handle: str,baseDir: str, \
if not os.path.isdir(baseDir+'/accounts/'+handle): if not os.path.isdir(baseDir+'/accounts/'+handle):
print('DEBUG: unknown recipient of like - '+handle) print('DEBUG: unknown recipient of like - '+handle)
# if this post in the outbox of the person? # if this post in the outbox of the person?
postFilename=locatePost(baseDir,handle.split('@')[0],handle.split('@')[1],messageJson['object']) messageId=messageJson['object'].replace('/activity','')
postFilename=locatePost(baseDir,handle.split('@')[0],handle.split('@')[1],messageId)
if not postFilename: if not postFilename:
if debug: if debug:
print('DEBUG: delete post not found in inbox or outbox') print('DEBUG: delete post not found in inbox or outbox')
print(messageJson['object']) print(messageId)
return True return True
deletePost(baseDir,httpPrefix,handle.split('@')[0],handle.split('@')[1],postFilename,debug) deletePost(baseDir,httpPrefix,handle.split('@')[0],handle.split('@')[1],postFilename,debug)
if debug: if debug:

View File

@ -52,6 +52,7 @@ from like import likePost
from announce import announcePublic from announce import announcePublic
from announce import sendAnnounceViaServer from announce import sendAnnounceViaServer
from media import getMediaPath from media import getMediaPath
from delete import sendDeleteViaServer
testServerAliceRunning = False testServerAliceRunning = False
testServerBobRunning = False testServerBobRunning = False
@ -1091,14 +1092,37 @@ def testClientToServer():
assert os.path.isfile(aliceDir+'/accounts/alice@'+aliceDomain+'/following.txt') assert os.path.isfile(aliceDir+'/accounts/alice@'+aliceDomain+'/following.txt')
assert 'alice@'+aliceDomain+':'+str(alicePort) in open(bobDir+'/accounts/bob@'+bobDomain+'/followers.txt').read() assert 'alice@'+aliceDomain+':'+str(alicePort) in open(bobDir+'/accounts/bob@'+bobDomain+'/followers.txt').read()
assert 'bob@'+bobDomain+':'+str(bobPort) in open(aliceDir+'/accounts/alice@'+aliceDomain+'/following.txt').read() assert 'bob@'+bobDomain+':'+str(bobPort) in open(aliceDir+'/accounts/alice@'+aliceDomain+'/following.txt').read()
print('\n\nBob follows Alice')
sendFollowRequestViaServer(sessionAlice,'bob','bobpass', \
bobDomain,bobPort, \
'alice',aliceDomain,alicePort, \
httpPrefix, \
cachedWebfingers,personCache, \
True)
for t in range(10):
if os.path.isfile(aliceDir+'/accounts/alice@'+aliceDomain+'/followers.txt'):
if 'bob@'+bobDomain+':'+str(bobPort) in open(aliceDir+'/accounts/alice@'+aliceDomain+'/followers.txt').read():
if os.path.isfile(bobDir+'/accounts/bob@'+bobDomain+'/following.txt'):
if 'alice@'+aliceDomain+':'+str(alicePort) in open(bobDir+'/accounts/bob@'+bobDomain+'/following.txt').read():
break
time.sleep(1)
assert os.path.isfile(aliceDir+'/accounts/alice@'+aliceDomain+'/followers.txt')
assert os.path.isfile(bobDir+'/accounts/bob@'+bobDomain+'/following.txt')
assert 'bob@'+bobDomain+':'+str(bobPort) in open(aliceDir+'/accounts/alice@'+aliceDomain+'/followers.txt').read()
assert 'alice@'+aliceDomain+':'+str(alicePort) in open(bobDir+'/accounts/bob@'+bobDomain+'/following.txt').read()
print('\n\nBob repeats the post') print('\n\nBob repeats the post')
sessionBob = createSession(bobDomain,bobPort,useTor) sessionBob = createSession(bobDomain,bobPort,useTor)
password='bobpass' password='bobpass'
outboxPath=bobDir+'/accounts/bob@'+bobDomain+'/outbox' outboxPath=bobDir+'/accounts/bob@'+bobDomain+'/outbox'
inboxPath=aliceDir+'/accounts/alice@'+aliceDomain+'/inbox' inboxPath=aliceDir+'/accounts/alice@'+aliceDomain+'/inbox'
assert len([name for name in os.listdir(outboxPath) if os.path.isfile(os.path.join(outboxPath, name))])==0 print(str(len([name for name in os.listdir(outboxPath) if os.path.isfile(os.path.join(outboxPath, name))])))
assert len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])==0 assert len([name for name in os.listdir(outboxPath) if os.path.isfile(os.path.join(outboxPath, name))])==1
print(str(len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])))
assert len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])==1
sendAnnounceViaServer(sessionBob,'bob',password, \ sendAnnounceViaServer(sessionBob,'bob',password, \
bobDomain,bobPort, \ bobDomain,bobPort, \
httpPrefix,outboxPostId, \ httpPrefix,outboxPostId, \
@ -1106,16 +1130,36 @@ def testClientToServer():
personCache,True) personCache,True)
for i in range(20): for i in range(20):
if os.path.isdir(outboxPath) and os.path.isdir(inboxPath): if os.path.isdir(outboxPath) and os.path.isdir(inboxPath):
if len([name for name in os.listdir(outboxPath) if os.path.isfile(os.path.join(outboxPath, name))])==1: if len([name for name in os.listdir(outboxPath) if os.path.isfile(os.path.join(outboxPath, name))])==2:
if len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])==1: if len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])==2:
break break
time.sleep(1) time.sleep(1)
assert len([name for name in os.listdir(outboxPath) if os.path.isfile(os.path.join(outboxPath, name))])==1 assert len([name for name in os.listdir(outboxPath) if os.path.isfile(os.path.join(outboxPath, name))])==2
assert len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])==1 assert len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])==2
print('Post repeated') print('Post repeated')
inboxPath=bobDir+'/accounts/bob@'+bobDomain+'/inbox'
outboxPath=aliceDir+'/accounts/alice@'+aliceDomain+'/outbox'
postsBefore = len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])
print('\n\nAlice deletes her post: '+outboxPostId+' '+str(postsBefore))
password='alicepass'
sendDeleteViaServer(sessionAlice,'alice',password,
aliceDomain,alicePort, \
httpPrefix,outboxPostId, \
cachedWebfingers,personCache, \
True)
for i in range(30):
if os.path.isdir(inboxPath):
if len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])==postsBefore-1:
break
time.sleep(1)
assert len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, name))])==postsBefore-1
print(">>> post deleted from Alice's outbox and Bob's inbox")
print('\n\nAlice unfollows Bob') print('\n\nAlice unfollows Bob')
password='alicepass' password='alicepass'
sendUnfollowRequestViaServer(sessionAlice,'alice',password, \ sendUnfollowRequestViaServer(sessionAlice,'alice',password, \