epicyon/acceptreject.py

210 lines
8.2 KiB
Python

__filename__ = "acceptreject.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.0.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
import json
import commentjson
from capabilities import capabilitiesAccept
from capabilities import capabilitiesGrantedSave
from utils import getStatusNumber
from utils import createOutboxDir
from utils import urlPermitted
from utils import getDomainFromActor
from utils import getNicknameFromActor
from utils import domainPermitted
from utils import followPerson
def createAcceptReject(baseDir: str,federationList: [], \
nickname: str,domain: str,port: int, \
toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {},ocapJson,acceptType: str) -> {}:
"""Accepts or rejects something (eg. a follow request or offer)
Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
and ccUrl might be a specific person favorited or repeated and
the followers url objectUrl is typically the url of the message,
corresponding to url or atomUri in createPostBase
"""
if not objectJson.get('actor'):
return None
if not urlPermitted(objectJson['actor'],federationList,"inbox:write"):
return None
if port:
if port!=80 and port!=443:
if ':' not in domain:
domain=domain+':'+str(port)
newAccept = {
"@context": "https://www.w3.org/ns/activitystreams",
'type': acceptType,
'actor': httpPrefix+'://'+domain+'/users/'+nickname,
'to': [toUrl],
'cc': [],
'object': objectJson
}
if ccUrl:
if len(ccUrl)>0:
newAccept['cc']=[ccUrl]
# attach capabilities for follow accept
if ocapJson:
newAccept['capabilities']=ocapJson
return newAccept
def createAccept(baseDir: str,federationList: [], \
nickname: str,domain: str,port: int, \
toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {},acceptedCaps=["inbox:write","objects:read"]) -> {}:
# create capabilities accept
ocapNew=capabilitiesAccept(baseDir,httpPrefix,nickname,domain,port,toUrl,True,acceptedCaps)
return createAcceptReject(baseDir,federationList, \
nickname,domain,port, \
toUrl,ccUrl,httpPrefix, \
objectJson,ocapNew,'Accept')
def createReject(baseDir: str,federationList: [], \
nickname: str,domain: str,port: int, \
toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {}) -> {}:
return createAcceptReject(baseDir,federationList, \
nickname,domain,port, \
toUrl,ccUrl, \
httpPrefix,objectJson,None,'Reject')
def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
federationList: [],debug : bool) -> None:
"""Receiving a follow Accept activity
"""
if not messageJson.get('object'):
return
if not messageJson['object'].get('type'):
return
if not messageJson['object'].get('actor'):
return
# no, this isn't a mistake
if not messageJson['object'].get('object'):
return
if not messageJson['object']['type']=='Follow':
return
if not messageJson.get('to'):
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']
nickname=getNicknameFromActor(thisActor)
if not nickname:
print('WARN: no nickname found in '+thisActor)
return
acceptedDomain,acceptedPort=getDomainFromActor(thisActor)
if not acceptedDomain:
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 debug:
print('Port: '+str(acceptedPort))
print('Expected: /'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname)
print('Actual: '+thisActor)
print('DEBUG: unrecognized actor '+thisActor)
return
else:
if not '/'+acceptedDomain+'/users/'+nickname in thisActor:
if debug:
print('Expected: /'+acceptedDomain+'/users/'+nickname)
print('Actual: '+thisActor)
print('DEBUG: unrecognized actor '+thisActor)
return
followedActor=messageJson['object']['object']
followedDomain,port=getDomainFromActor(followedActor)
if not followedDomain:
return
followedDomainFull=followedDomain
if port:
followedDomainFull=followedDomain+':'+str(port)
followedNickname=getNicknameFromActor(followedActor)
if not followedNickname:
return
acceptedDomainFull=acceptedDomain
if acceptedPort:
acceptedDomainFull=acceptedDomain+':'+str(acceptedPort)
# are capabilities attached? If so then store them
if messageJson.get('capabilities'):
if isinstance(messageJson['capabilities'], dict):
capabilitiesGrantedSave(baseDir, \
nickname,acceptedDomainFull, \
messageJson['capabilities'])
if followPerson(baseDir, \
nickname,acceptedDomainFull, \
followedNickname,followedDomainFull, \
federationList,debug):
if debug:
print('DEBUG: '+nickname+'@'+acceptedDomainFull+' followed '+followedNickname+'@'+followedDomainFull)
else:
if debug:
print('DEBUG: Unable to create follow - '+nickname+'@'+acceptedDomain+' -> '+followedNickname+'@'+followedDomain)
def receiveAcceptReject(session,baseDir: str, \
httpPrefix: str,domain :str,port: int, \
sendThreads: [],postLog: [],cachedWebfingers: {}, \
personCache: {},messageJson: {},federationList: [], \
debug : bool) -> bool:
"""Receives an Accept or Reject within the POST section of HTTPServer
"""
if messageJson['type']!='Accept' and messageJson['type']!='Reject':
return False
if not messageJson.get('actor'):
if debug:
print('DEBUG: '+messageJson['type']+' has no actor')
return False
if '/users/' not in messageJson['actor'] and \
'/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.')
domain,tempPort=getDomainFromActor(messageJson['actor'])
if not domainPermitted(domain,federationList):
if debug:
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.')
handle=nickname.lower()+'@'+domain.lower()
# receive follow accept
acceptFollow(baseDir,domain,messageJson,federationList,debug)
if debug:
print('DEBUG: Uh, '+messageJson['type']+', I guess')
return True