main2
Bob Mottram 2019-11-03 15:27:29 +00:00
parent 4e84f2c331
commit ad92d8ee08
6 changed files with 453 additions and 240 deletions

View File

@ -58,9 +58,12 @@ def createAcceptReject(baseDir: str,federationList: [], \
def createAccept(baseDir: str,federationList: [], \
nickname: str,domain: str,port: int, \
toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {},acceptedCaps=["inbox:write","objects:read"]) -> {}:
objectJson: {}, \
acceptedCaps=["inbox:write","objects:read"]) -> {}:
# create capabilities accept
ocapNew=capabilitiesAccept(baseDir,httpPrefix,nickname,domain,port,toUrl,True,acceptedCaps)
ocapNew= \
capabilitiesAccept(baseDir,httpPrefix, \
nickname,domain,port,toUrl,True,acceptedCaps)
return createAcceptReject(baseDir,federationList, \
nickname,domain,port, \
toUrl,ccUrl,httpPrefix, \
@ -94,17 +97,6 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
if debug:
print('DEBUG: No "to" parameter in follow Accept')
return
#if len(messageJson['object']['to'])!=1:
# if debug:
# print('DEBUG: "to" does not contain a single recipient')
# print(str(messageJson['object']['to']))
# if messageJson['object'].get('object'):
# if not isinstance(messageJson['object']['object'], str):
# messageJson['object']['to']=messageJson['object']['object']
# else:
# return
# else:
# return
if debug:
print('DEBUG: follow Accept received')
thisActor=messageJson['object']['actor']
@ -117,19 +109,16 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
if debug:
print('DEBUG: domain not found in '+thisActor)
return
#if acceptedDomain != domain:
# if debug:
# print('DEBUG: domain mismatch '+acceptedDomain+' != '+domain)
# return
if not nickname:
if debug:
print('DEBUG: nickname not found in '+thisActor)
return
if acceptedPort:
if not '/'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname in thisActor:
if '/'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname not in thisActor:
if debug:
print('Port: '+str(acceptedPort))
print('Expected: /'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname)
print('Expected: /'+acceptedDomain+':'+str(acceptedPort)+ \
'/users/'+nickname)
print('Actual: '+thisActor)
print('DEBUG: unrecognized actor '+thisActor)
return
@ -167,10 +156,13 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
followedNickname,followedDomainFull, \
federationList,debug):
if debug:
print('DEBUG: '+nickname+'@'+acceptedDomainFull+' followed '+followedNickname+'@'+followedDomainFull)
print('DEBUG: '+nickname+'@'+acceptedDomainFull+ \
' followed '+followedNickname+'@'+followedDomainFull)
else:
if debug:
print('DEBUG: Unable to create follow - '+nickname+'@'+acceptedDomain+' -> '+followedNickname+'@'+followedDomain)
print('DEBUG: Unable to create follow - '+ \
nickname+'@'+acceptedDomain+' -> '+ \
followedNickname+'@'+followedDomain)
def receiveAcceptReject(session,baseDir: str, \
httpPrefix: str,domain :str,port: int, \
@ -189,18 +181,21 @@ def receiveAcceptReject(session,baseDir: str, \
'/channel/' not in messageJson['actor'] and \
'/profile/' not in messageJson['actor']:
if debug:
print('DEBUG: "users" or "profile" missing from actor in '+messageJson['type']+'. Assuming single user instance.')
print('DEBUG: "users" or "profile" missing from actor in '+ \
messageJson['type']+'. Assuming single user instance.')
domain,tempPort=getDomainFromActor(messageJson['actor'])
if not domainPermitted(domain,federationList):
if debug:
print('DEBUG: '+messageJson['type']+' from domain not permitted - '+domain)
print('DEBUG: '+messageJson['type']+ \
' from domain not permitted - '+domain)
return False
nickname=getNicknameFromActor(messageJson['actor'])
if not nickname:
# single user instance
nickname='dev'
if debug:
print('DEBUG: '+messageJson['type']+' does not contain a nickname. Assuming single user instance.')
print('DEBUG: '+messageJson['type']+ \
' does not contain a nickname. Assuming single user instance.')
handle=nickname.lower()+'@'+domain.lower()
# receive follow accept
acceptFollow(baseDir,domain,messageJson,federationList,debug)

View File

@ -46,7 +46,8 @@ def outboxAnnounce(baseDir: str,messageJson: {},debug: bool) -> bool:
domain,port=getDomainFromActor(messageJson['actor'])
postFilename=locatePost(baseDir,nickname,domain,messageJson['object'])
if postFilename:
updateAnnounceCollection(baseDir,postFilename,messageJson['actor'],domain,debug)
updateAnnounceCollection(baseDir,postFilename, \
messageJson['actor'],domain,debug)
return True
if messageJson['type']=='Undo':
if not isinstance(messageJson['object'], dict):
@ -61,22 +62,29 @@ def outboxAnnounce(baseDir: str,messageJson: {},debug: bool) -> bool:
print('WARN: no nickname found in '+messageJson['actor'])
return False
domain,port=getDomainFromActor(messageJson['actor'])
postFilename=locatePost(baseDir,nickname,domain,messageJson['object']['object'])
postFilename= \
locatePost(baseDir,nickname,domain, \
messageJson['object']['object'])
if postFilename:
undoAnnounceCollectionEntry(baseDir,postFilename,messageJson['actor'],domain,debug)
undoAnnounceCollectionEntry(baseDir,postFilename, \
messageJson['actor'], \
domain,debug)
return True
return False
def undoAnnounceCollectionEntry(baseDir: str,postFilename: str,actor: str,domain: str,debug: bool) -> None:
"""Undoes an announce for a particular actor by removing it from the "shares"
collection within a post. Note that the "shares" collection has no relation
to shared items in shares.py. It's shares of posts, not shares of physical objects.
def undoAnnounceCollectionEntry(baseDir: str,postFilename: str, \
actor: str,domain: str,debug: bool) -> None:
"""Undoes an announce for a particular actor by removing it from
the "shares" collection within a post. Note that the "shares"
collection has no relation to shared items in shares.py. It's
shares of posts, not shares of physical objects.
"""
postJsonObject=loadJson(postFilename)
if postJsonObject:
# remove any cached version of this announce so that the like icon is changed
nickname=getNicknameFromActor(actor)
cachedPostFilename=getCachedPostFilename(baseDir,nickname,domain,postJsonObject)
cachedPostFilename= \
getCachedPostFilename(baseDir,nickname,domain,postJsonObject)
if os.path.isfile(cachedPostFilename):
os.remove(cachedPostFilename)
@ -113,19 +121,24 @@ def undoAnnounceCollectionEntry(baseDir: str,postFilename: str,actor: str,domain
print('DEBUG: shares (announcements) was removed from post')
del postJsonObject['object']['shares']
else:
postJsonObject['object']['shares']['totalItems']=len(postJsonObject['object']['shares']['items'])
postJsonObject['object']['shares']['totalItems']= \
len(postJsonObject['object']['shares']['items'])
saveJson(postJsonObject,postFilename)
def updateAnnounceCollection(baseDir: str,postFilename: str,actor: str,domain: str,debug: bool) -> None:
def updateAnnounceCollection(baseDir: str,postFilename: str, \
actor: str,domain: str,debug: bool) -> None:
"""Updates the announcements collection within a post
Confusingly this is known as "shares", but isn't the same as shared items within shares.py
Confusingly this is known as "shares", but isn't the
same as shared items within shares.py
It's shares of posts, not shares of physical objects.
"""
postJsonObject=loadJson(postFilename)
if postJsonObject:
# remove any cached version of this announce so that the like icon is changed
# remove any cached version of this announce so that the like
# icon is changed
nickname=getNicknameFromActor(actor)
cachedPostFilename=getCachedPostFilename(baseDir,nickname,domain,postJsonObject)
cachedPostFilename= \
getCachedPostFilename(baseDir,nickname,domain,postJsonObject)
if os.path.isfile(cachedPostFilename):
os.remove(cachedPostFilename)
@ -139,7 +152,8 @@ def updateAnnounceCollection(baseDir: str,postFilename: str,actor: str,domain: s
postUrl=postJsonObject['id'].replace('/activity','')+'/shares'
if not postJsonObject['object'].get('shares'):
if debug:
print('DEBUG: Adding initial shares (announcements) to '+postUrl)
print('DEBUG: Adding initial shares (announcements) to '+ \
postUrl)
announcementsJson = {
"@context": "https://www.w3.org/ns/activitystreams",
'id': postUrl,
@ -162,7 +176,8 @@ def updateAnnounceCollection(baseDir: str,postFilename: str,actor: str,domain: s
'actor': actor
}
postJsonObject['object']['shares']['items'].append(newAnnounce)
postJsonObject['object']['shares']['totalItems']=len(postJsonObject['object']['shares']['items'])
postJsonObject['object']['shares']['totalItems']= \
len(postJsonObject['object']['shares']['items'])
else:
if debug:
print('DEBUG: shares (announcements) section of post has no items list')
@ -442,7 +457,8 @@ def sendAnnounceViaServer(baseDir: str,session, \
statusNumber,published = getStatusNumber()
newAnnounceId= \
httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/statuses/'+statusNumber
httpPrefix+'://'+fromDomainFull+'/users/'+ \
fromNickname+'/statuses/'+statusNumber
newAnnounceJson = {
"@context": "https://www.w3.org/ns/activitystreams",
'actor': httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname,
@ -489,10 +505,6 @@ def sendAnnounceViaServer(baseDir: str,session, \
'Authorization': authHeader}
postResult = \
postJson(session,newAnnounceJson,[],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 announce success')

View File

@ -17,7 +17,9 @@ def hashPassword(password: str) -> str:
"""Hash a password for storing
"""
salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii')
pwdhash = hashlib.pbkdf2_hmac('sha512', password.encode('utf-8'), salt, 100000)
pwdhash = hashlib.pbkdf2_hmac('sha512', \
password.encode('utf-8'), \
salt, 100000)
pwdhash = binascii.hexlify(pwdhash)
return (salt + pwdhash).decode('ascii')

View File

@ -48,7 +48,8 @@ def getAvailability(baseDir: str,nickname: str,domain: str) -> str:
return actorJson['availability']
return None
def outboxAvailability(baseDir: str,nickname: str,messageJson: {},debug: bool) -> bool:
def outboxAvailability(baseDir: str,nickname: str,messageJson: {}, \
debug: bool) -> bool:
"""Handles receiving an availability update
"""
if not messageJson.get('type'):
@ -133,10 +134,6 @@ def sendAvailabilityViaServer(baseDir: str,session, \
'Authorization': authHeader}
postResult = \
postJson(session,newAvailabilityJson,[],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 availability success')

View File

@ -137,11 +137,13 @@ def isBlocked(baseDir: str,nickname: str,domain: str, \
blockHandle=blockNickname+'@'+blockDomain
if blockHandle in open(globalBlockingFilename).read():
return True
allowFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/allowedinstances.txt'
allowFilename= \
baseDir+'/accounts/'+nickname+'@'+domain+'/allowedinstances.txt'
if os.path.isfile(allowFilename):
if blockDomain not in open(allowFilename).read():
return True
blockingFilename=baseDir+'/accounts/'+nickname+'@'+domain+'/blocking.txt'
blockingFilename= \
baseDir+'/accounts/'+nickname+'@'+domain+'/blocking.txt'
if os.path.isfile(blockingFilename):
if '*@'+blockDomain in open(blockingFilename).read():
return True
@ -168,8 +170,9 @@ def sendBlockViaServer(baseDir: str,session, \
if ':' not in fromDomain:
fromDomainFull=fromDomain+':'+str(fromPort)
toUrl = 'https://www.w3.org/ns/activitystreams#Public'
ccUrl = httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers'
toUrl= 'https://www.w3.org/ns/activitystreams#Public'
ccUrl= \
httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers'
blockActor=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname
newBlockJson = {
@ -215,10 +218,6 @@ def sendBlockViaServer(baseDir: str,session, \
'Authorization': authHeader}
postResult = \
postJson(session,newBlockJson,[],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 block success')
@ -243,8 +242,9 @@ def sendUndoBlockViaServer(baseDir: str,session, \
if ':' not in fromDomain:
fromDomainFull=fromDomain+':'+str(fromPort)
toUrl = 'https://www.w3.org/ns/activitystreams#Public'
ccUrl = httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers'
toUrl= 'https://www.w3.org/ns/activitystreams#Public'
ccUrl= \
httpPrefix + '://'+fromDomainFull+'/users/'+fromNickname+'/followers'
blockActor=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname
newBlockJson = {
@ -263,8 +263,9 @@ def sendUndoBlockViaServer(baseDir: str,session, \
handle=httpPrefix+'://'+fromDomainFull+'/@'+fromNickname
# lookup the inbox for the To handle
wfRequest = webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \
fromDomain,projectVersion)
wfRequest= \
webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \
fromDomain,projectVersion)
if not wfRequest:
if debug:
print('DEBUG: announce webfinger failed for '+handle)
@ -294,10 +295,6 @@ def sendUndoBlockViaServer(baseDir: str,session, \
'Authorization': authHeader}
postResult = \
postJson(session,newBlockJson,[],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 block success')

558
daemon.py

File diff suppressed because it is too large Load Diff