forked from indymedia/epicyon
Test for post deletion
parent
89c1c01f82
commit
27908a5fad
|
@ -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
131
delete.py
|
@ -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)
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
7
inbox.py
7
inbox.py
|
@ -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:
|
||||||
|
|
56
tests.py
56
tests.py
|
@ -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, \
|
||||||
|
|
Loading…
Reference in New Issue