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 media import getMediaPath
from media import createMediaDirs
from delete import outboxDelete
import os
import sys
@ -179,6 +180,7 @@ class PubServer(BaseHTTPRequestHandler):
postId=None
if self.server.debug:
pprint(messageJson)
print('DEBUG: savePostToBox')
savePostToBox(self.server.baseDir, \
self.server.httpPrefix, \
postId, \
@ -204,6 +206,9 @@ class PubServer(BaseHTTPRequestHandler):
if self.server.debug:
print('DEBUG: handle any unfollow requests')
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:
print('DEBUG: sending c2s post to named addresses')
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 getNicknameFromActor
from utils import getDomainFromActor
from utils import locatePost
from utils import deletePost
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: [], \
nickname: str, domain: str, port: int, \
@ -72,6 +78,73 @@ def createDelete(session,baseDir: str,federationList: [], \
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: [], \
nickname: str, domain: str, port: int, httpPrefix: str, \
objectUrl: str,clientToServer: bool, \
@ -95,14 +168,14 @@ def deletePublic(session,baseDir: str,federationList: [], \
personCache,cachedWebfingers, \
debug)
def deletePost(session,baseDir: str,federationList: [], \
nickname: str, domain: str, port: int, httpPrefix: str, \
deleteNickname: str, deleteDomain: str, \
deletePort: int, deleteHttpsPrefix: str, \
deleteStatusNumber: int,clientToServer: bool, \
sendThreads: [],postLog: [], \
personCache: {},cachedWebfingers: {}, \
debug: bool) -> {}:
def deletePostPub(session,baseDir: str,federationList: [], \
nickname: str, domain: str, port: int, httpPrefix: str, \
deleteNickname: str, deleteDomain: str, \
deletePort: int, deleteHttpsPrefix: str, \
deleteStatusNumber: int,clientToServer: bool, \
sendThreads: [],postLog: [], \
personCache: {},cachedWebfingers: {}, \
debug: bool) -> {}:
"""Deletes a given status post
"""
deletedDomain=deleteDomain
@ -120,3 +193,45 @@ def deletePost(session,baseDir: str,federationList: [], \
personCache,cachedWebfingers, \
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 getNicknameFromActor
from media import archiveMedia
from delete import sendDeleteViaServer
import argparse
def str2bool(v):
@ -218,8 +219,8 @@ if args.tests:
if args.testsnetwork:
print('Network Tests')
testPostMessageBetweenServers()
testFollowBetweenServers()
#testPostMessageBetweenServers()
#testFollowBetweenServers()
testClientToServer()
sys.exit()

View File

@ -623,6 +623,8 @@ def receiveDelete(session,handle: str,baseDir: str, \
if debug:
print('DEBUG: '+messageJson['type']+' has no actor')
return False
if debug:
print('DEBUG: Delete activity arrived')
if not messageJson.get('object'):
if debug:
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):
print('DEBUG: unknown recipient of like - '+handle)
# 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 debug:
print('DEBUG: delete post not found in inbox or outbox')
print(messageJson['object'])
print(messageId)
return True
deletePost(baseDir,httpPrefix,handle.split('@')[0],handle.split('@')[1],postFilename,debug)
if debug:

View File

@ -52,6 +52,7 @@ from like import likePost
from announce import announcePublic
from announce import sendAnnounceViaServer
from media import getMediaPath
from delete import sendDeleteViaServer
testServerAliceRunning = False
testServerBobRunning = False
@ -1091,14 +1092,37 @@ def testClientToServer():
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 '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')
sessionBob = createSession(bobDomain,bobPort,useTor)
password='bobpass'
outboxPath=bobDir+'/accounts/bob@'+bobDomain+'/outbox'
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
assert len([name for name in os.listdir(inboxPath) if os.path.isfile(os.path.join(inboxPath, 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(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, \
bobDomain,bobPort, \
httpPrefix,outboxPostId, \
@ -1106,16 +1130,36 @@ def testClientToServer():
personCache,True)
for i in range(20):
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(inboxPath) if os.path.isfile(os.path.join(inboxPath, 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))])==2:
break
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(inboxPath) if os.path.isfile(os.path.join(inboxPath, 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))])==2
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')
password='alicepass'
sendUnfollowRequestViaServer(sessionAlice,'alice',password, \