Add capabilities to follow requests

master
Bob Mottram 2019-07-07 12:53:32 +01:00
parent 03a43f64f1
commit e9cf9dfc27
12 changed files with 246 additions and 112 deletions

View File

@ -8,6 +8,8 @@ __status__ = "Production"
import json import json
import commentjson import commentjson
from capabilities import capabilitiesAccept
from capabilities import capabilitiesGrantedSave
from utils import getStatusNumber from utils import getStatusNumber
from utils import createOutboxDir from utils import createOutboxDir
from utils import urlPermitted from utils import urlPermitted
@ -16,10 +18,10 @@ from utils import getNicknameFromActor
from utils import domainPermitted from utils import domainPermitted
from utils import followPerson from utils import followPerson
def createAcceptReject(baseDir: str,federationList: [],capsList: [], \ def createAcceptReject(baseDir: str,federationList: [],ocapGranted: {}, \
nickname: str,domain: str,port: int, \ nickname: str,domain: str,port: int, \
toUrl: str,ccUrl: str,httpPrefix: str, \ toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {},acceptType: str) -> {}: objectJson: {},ocapJson,acceptType: str) -> {}:
"""Accepts or rejects something (eg. a follow request or offer) """Accepts or rejects something (eg. a follow request or offer)
Typically toUrl will be https://www.w3.org/ns/activitystreams#Public Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
and ccUrl might be a specific person favorited or repeated and and ccUrl might be a specific person favorited or repeated and
@ -29,7 +31,7 @@ def createAcceptReject(baseDir: str,federationList: [],capsList: [], \
if not objectJson.get('actor'): if not objectJson.get('actor'):
return None return None
if not urlPermitted(objectJson['actor'],federationList,capsList,"inbox:write"): if not urlPermitted(objectJson['actor'],federationList,ocapGranted,"inbox:write"):
return None return None
if port!=80 and port!=443: if port!=80 and port!=443:
@ -45,28 +47,33 @@ def createAcceptReject(baseDir: str,federationList: [],capsList: [], \
if ccUrl: if ccUrl:
if len(ccUrl)>0: if len(ccUrl)>0:
newAccept['cc']=ccUrl newAccept['cc']=ccUrl
# attach capabilities for follow accept
if ocapJson:
newAccept['capabilities']=ocapJson
return newAccept return newAccept
def createAccept(baseDir: str,federationList: [],capsList: [], \ def createAccept(baseDir: str,federationList: [],ocapGranted: {}, \
nickname: str,domain: str,port: int, \ nickname: str,domain: str,port: int, \
toUrl: str,ccUrl: str,httpPrefix: str, \ toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {}) -> {}: objectJson: {}) -> {}:
return createAcceptReject(baseDir,federationList,capsList, \ # create capabilities accept
ocapNew=capabilitiesAccept(baseDir,httpPrefix,nickname,domain, toUrl, True)
return createAcceptReject(baseDir,federationList,ocapGranted, \
nickname,domain,port, \ nickname,domain,port, \
toUrl,ccUrl,httpPrefix, \ toUrl,ccUrl,httpPrefix, \
objectJson,'Accept') objectJson,ocapNew,'Accept')
def createReject(baseDir: str,federationList: [],capsList: [], \ def createReject(baseDir: str,federationList: [],ocapGranted: {}, \
nickname: str,domain: str,port: int, \ nickname: str,domain: str,port: int, \
toUrl: str,ccUrl: str,httpPrefix: str, \ toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {}) -> {}: objectJson: {}) -> {}:
return createAcceptReject(baseDir,federationList,capsList, \ return createAcceptReject(baseDir,federationList,ocapGranted, \
nickname,domain,port, \ nickname,domain,port, \
toUrl,ccUrl, \ toUrl,ccUrl, \
httpPrefix,objectJson,'Reject') httpPrefix,objectJson,None,'Reject')
def acceptFollow(baseDir: str,domain : str,messageJson: {}, \ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
federationList: [],capsList: [],debug : bool) -> None: federationList: [],ocapGranted: {},debug : bool) -> None:
if not messageJson.get('object'): if not messageJson.get('object'):
return return
if not messageJson['object'].get('type'): if not messageJson['object'].get('type'):
@ -115,6 +122,12 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
followedNickname=getNicknameFromActor(followedActor) followedNickname=getNicknameFromActor(followedActor)
if not followedNickname: if not followedNickname:
return return
# are capabilities attached? If so then store them
if messageJson['object'].get('capabilities'):
if isinstance(messageJson['object']['capabilities'], dict):
capabilitiesGrantedSave(baseDir,messageJson['object']['capabilities'])
if followPerson(baseDir,nickname,domain, \ if followPerson(baseDir,nickname,domain, \
followedNickname,followedDomain, \ followedNickname,followedDomain, \
federationList,debug): federationList,debug):
@ -128,7 +141,7 @@ def receiveAcceptReject(session,baseDir: str, \
httpPrefix: str,domain :str,port: int, \ httpPrefix: str,domain :str,port: int, \
sendThreads: [],postLog: [],cachedWebfingers: {}, \ sendThreads: [],postLog: [],cachedWebfingers: {}, \
personCache: {},messageJson: {},federationList: [], \ personCache: {},messageJson: {},federationList: [], \
capsList: [],debug : bool) -> bool: ocapGranted: {},debug : bool) -> bool:
"""Receives an Accept or Reject within the POST section of HTTPServer """Receives an Accept or Reject within the POST section of HTTPServer
""" """
if messageJson['type']!='Accept' and messageJson['type']!='Reject': if messageJson['type']!='Accept' and messageJson['type']!='Reject':
@ -152,7 +165,7 @@ def receiveAcceptReject(session,baseDir: str, \
print('DEBUG: '+messageJson['type']+' does not contain a nickname') print('DEBUG: '+messageJson['type']+' does not contain a nickname')
return False return False
handle=nickname.lower()+'@'+domain.lower() handle=nickname.lower()+'@'+domain.lower()
acceptFollow(baseDir,domain,messageJson,federationList,capsList,debug) acceptFollow(baseDir,domain,messageJson,federationList,ocapGranted,debug)
if debug: if debug:
print('DEBUG: Uh, '+messageJson['type']+', I guess') print('DEBUG: Uh, '+messageJson['type']+', I guess')
return True return True

View File

@ -12,7 +12,7 @@ from utils import getStatusNumber
from utils import createOutboxDir from utils import createOutboxDir
from utils import urlPermitted from utils import urlPermitted
def createAnnounce(baseDir: str,federationList: [], capsList: [], \ def createAnnounce(baseDir: str,federationList: [], ocapGranted: {}, \
nickname: str, domain: str, port: int, \ nickname: str, domain: str, port: int, \
toUrl: str, ccUrl: str, httpPrefix: str, \ toUrl: str, ccUrl: str, httpPrefix: str, \
objectUrl: str, saveToFile: bool) -> {}: objectUrl: str, saveToFile: bool) -> {}:
@ -22,7 +22,7 @@ def createAnnounce(baseDir: str,federationList: [], capsList: [], \
followers url objectUrl is typically the url of the message, followers url objectUrl is typically the url of the message,
corresponding to url or atomUri in createPostBase corresponding to url or atomUri in createPostBase
""" """
if not urlPermitted(objectUrl,federationList,capsList,"inbox:write"): if not urlPermitted(objectUrl,federationList,ocapGranted,"inbox:write"):
return None return None
if port!=80 and port!=443: if port!=80 and port!=443:

View File

@ -7,42 +7,99 @@ __email__ = "bob@freedombone.net"
__status__ = "Production" __status__ = "Production"
import os import os
import datetime
import time
import json
import commentjson
from auth import createPassword from auth import createPassword
def sendCapabilitiesRequest(baseDir: str,httpPrefix: str,domain: str, \ def capabilitiesMakeDirs(baseDir: str):
if not os.path.isdir(baseDir+'/ocap'):
os.mkdir(baseDir+'/ocap')
# for capabilities accepted by this instance
if not os.path.isdir(baseDir+'/ocap/accept'):
os.mkdir(baseDir+'/ocap/accept')
# for capabilities granted to this instance
if not os.path.isdir(baseDir+'/ocap/granted'):
os.mkdir(baseDir+'/ocap/granted')
def capabilitiesRequest(baseDir: str,httpPrefix: str,domain: str, \
requestedActor: str, \ requestedActor: str, \
requestedCaps=["inbox:write","objects:read"]) -> None: requestedCaps=["inbox:write","objects:read"]) -> {}:
# This is sent to the capabilities endpoint /caps/new # This is sent to the capabilities endpoint /caps/new
# which could be instance wide or for a particular person # which could be instance wide or for a particular person
capId=createPassword(32) # This could also be added to a follow activity
capRequest = { capabilitiesMakeDirs(baseDir)
"id": httpPrefix+"://"+requestedDomain+"/caps/request/"+capId,
ocapId=createPassword(32)
ocapRequest = {
"id": httpPrefix+"://"+requestedDomain+"/caps/request/"+ocapId,
"type": "Request", "type": "Request",
"capability": requestedCaps, "capability": requestedCaps,
"actor": requestedActor "actor": requestedActor
} }
#TODO return ocapRequest
def sendCapabilitiesAccept(baseDir: str,httpPrefix: str,nickname: str,domain: str, \ def capabilitiesAccept(baseDir: str,httpPrefix: str,nickname: str,domain: str, \
acceptedActor: str, \ acceptedActor: str, saveToFile: bool, \
acceptedCaps=["inbox:write","objects:read"]) -> None: acceptedCaps=["inbox:write","objects:read"]) -> {}:
# This gets returned to capabilities requester # This gets returned to capabilities requester
capId=createPassword(32) # This could also be added to a follow Accept activity
capAccept = {
"id": httpPrefix+"://"+domain+"/caps/"+capId, # reject excessively long actors
if len(acceptedActor)>256:
return None
# make directories to store capabilities
capabilitiesMakeDirs(baseDir)
filename=baseDir+'/ocap/accept/'+acceptedActor.replace('/','#')+'.json'
ocapAccept=None
# if the capability already exists then load it from file
if os.path.isfile(filename):
with open(filename, 'r') as fp:
ocapAccept=commentjson.load(fp)
# otherwise create a new capability
if not ocapAccept:
ocapId=createPassword(32)
ocapAccept = {
"id": httpPrefix+"://"+domain+"/caps/"+ocapId,
"type": "Capability", "type": "Capability",
"capability": acceptedCaps, "capability": acceptedCaps,
"scope": acceptedActor, "scope": acceptedActor,
"actor": httpPrefix+"://"+domain "actor": httpPrefix+"://"+domain
} }
if nickname: if nickname:
capAccept['actor']=httpPrefix+"://"+domain+'/users/'+nickname ocapAccept['actor']=httpPrefix+"://"+domain+'/users/'+nickname
#TODO
def isCapable(actor: str,capsJson: [],capability: str) -> bool: if saveToFile:
with open(filename, 'w') as fp:
commentjson.dump(ocapAccept, fp, indent=4, sort_keys=False)
return ocapAccept
def capabilitiesGrantedSave(baseDir :str,ocap: {}) -> bool:
"""A capabilities accept is received, so stor it for
reference when sending to the actor
"""
if not ocap.get('actor'):
return False
filename=baseDir+'/ocap/granted/'+ocap['actor'].replace('/','#')+'.json'
with open(filename, 'w') as fp:
commentjson.dump(ocap, fp, indent=4, sort_keys=False)
return True
def isCapable(actor: str,ocapGranted: {},capability: str) -> bool:
# is the given actor capable of using the current resource? # is the given actor capable of using the current resource?
for cap in capsJson: for id,ocap in ocapGranted.items():
if cap['scope'] in actor: if ocap['scope'] in actor:
if capability in cap['capability']: if capability in ocap['capability']:
return True
return False
def isCapableId(id: str,ocapGranted: {},capability: str) -> bool:
# is the given id capable of using the current resource?
if ocapGranted.get(id):
if ocapGranted['id']['scope'] in actor:
if capability in ocapGranted['id']['capability']:
return True return True
return False return False

View File

@ -451,7 +451,7 @@ class PubServer(BaseHTTPRequestHandler):
if not inboxPermittedMessage(self.server.domain, \ if not inboxPermittedMessage(self.server.domain, \
messageJson, \ messageJson, \
self.server.federationList, \ self.server.federationList, \
self.server.capsList): self.server.ocapGranted):
if self.server.debug: if self.server.debug:
# https://www.youtube.com/watch?v=K3PrSj9XEu4 # https://www.youtube.com/watch?v=K3PrSj9XEu4
print('DEBUG: Ah Ah Ah') print('DEBUG: Ah Ah Ah')
@ -498,7 +498,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.POSTbusy=False self.server.POSTbusy=False
def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \ def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \
fedList=[],capsList=[],useTor=False,debug=False) -> None: fedList=[],ocapGranted={},useTor=False,debug=False) -> None:
if len(domain)==0: if len(domain)==0:
domain='localhost' domain='localhost'
if '.' not in domain: if '.' not in domain:
@ -513,7 +513,7 @@ def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \
httpd.httpPrefix=httpPrefix httpd.httpPrefix=httpPrefix
httpd.debug=debug httpd.debug=debug
httpd.federationList=fedList.copy() httpd.federationList=fedList.copy()
httpd.capsList=capsList.copy() httpd.ocapGranted=ocapGranted.copy()
httpd.baseDir=baseDir httpd.baseDir=baseDir
httpd.personCache={} httpd.personCache={}
httpd.cachedWebfingers={} httpd.cachedWebfingers={}
@ -535,6 +535,6 @@ def runDaemon(baseDir: str,domain: str,port=80,httpPrefix='https', \
httpd.postLog,httpd.cachedWebfingers, \ httpd.postLog,httpd.cachedWebfingers, \
httpd.personCache,httpd.inboxQueue, \ httpd.personCache,httpd.inboxQueue, \
domain,port,useTor,httpd.federationList, \ domain,port,useTor,httpd.federationList, \
httpd.capsList,debug),daemon=True) httpd.ocapGranted,debug),daemon=True)
httpd.thrInboxQueue.start() httpd.thrInboxQueue.start()
httpd.serve_forever() httpd.serve_forever()

View File

@ -6,6 +6,7 @@ __maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net" __email__ = "bob@freedombone.net"
__status__ = "Production" __status__ = "Production"
from capabilities import capabilitiesMakeDirs
from person import createPerson from person import createPerson
from person import createSharedInbox from person import createSharedInbox
from person import createCapabilitiesInbox from person import createCapabilitiesInbox
@ -314,7 +315,7 @@ else:
if configFederationList: if configFederationList:
federationList=configFederationList federationList=configFederationList
capsList=[] ocapGranted={}
if federationList: if federationList:
print('Federating with: '+str(federationList)) print('Federating with: '+str(federationList))
@ -334,6 +335,8 @@ if not os.path.isdir(baseDir+'/accounts/capabilities@'+domain):
print('Creating capabilities account which can sign requests') print('Creating capabilities account which can sign requests')
createCapabilitiesInbox(baseDir,'capabilities',domain,port,httpPrefix) createCapabilitiesInbox(baseDir,'capabilities',domain,port,httpPrefix)
capabilitiesMakeDirs(baseDir)
if args.testdata: if args.testdata:
nickname='testuser567' nickname='testuser567'
print('Generating some test data for user: '+nickname) print('Generating some test data for user: '+nickname)
@ -342,13 +345,13 @@ if args.testdata:
deleteAllPosts(baseDir,nickname,domain,'outbox') deleteAllPosts(baseDir,nickname,domain,'outbox')
followPerson(baseDir,nickname,domain,'admin',domain,federationList,True) followPerson(baseDir,nickname,domain,'admin',domain,federationList,True)
followerOfPerson(baseDir,nickname,domain,'admin',domain,federationList,True) followerOfPerson(baseDir,nickname,domain,'admin',domain,federationList,True)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"like, this is totally just a test, man",False,True,False,capsList) createPublicPost(baseDir,nickname,domain,port,httpPrefix,"like, this is totally just a test, man",False,True,False,ocapGranted)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Zoiks!!!",False,True,False,capsList) createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Zoiks!!!",False,True,False,ocapGranted)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Hey scoob we need like a hundred more milkshakes",False,True,False,capsList) createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Hey scoob we need like a hundred more milkshakes",False,True,False,ocapGranted)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Getting kinda spooky around here",False,True,False,capsList) createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Getting kinda spooky around here",False,True,False,ocapGranted)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"And they would have gotten away with it too if it wasn't for those pesky hackers",False,True,False,capsList) createPublicPost(baseDir,nickname,domain,port,httpPrefix,"And they would have gotten away with it too if it wasn't for those pesky hackers",False,True,False,ocapGranted)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"man, these centralized sites are, like, the worst!",False,True,False,capsList) createPublicPost(baseDir,nickname,domain,port,httpPrefix,"man, these centralized sites are, like, the worst!",False,True,False,ocapGranted)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"another mystery solved hey",False,True,False,capsList) createPublicPost(baseDir,nickname,domain,port,httpPrefix,"another mystery solved hey",False,True,False,ocapGranted)
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"let's go bowling",False,True,False,capsList) createPublicPost(baseDir,nickname,domain,port,httpPrefix,"let's go bowling",False,True,False,ocapGranted)
runDaemon(baseDir,domain,port,httpPrefix,federationList,capsList,useTor,debug) runDaemon(baseDir,domain,port,httpPrefix,federationList,ocapGranted,useTor,debug)

View File

@ -221,7 +221,7 @@ def receiveFollowRequest(session,baseDir: str,httpPrefix: str, \
port: int,sendThreads: [],postLog: [], \ port: int,sendThreads: [],postLog: [], \
cachedWebfingers: {},personCache: {}, \ cachedWebfingers: {},personCache: {}, \
messageJson: {},federationList: [], \ messageJson: {},federationList: [], \
capsList: [],debug : bool) -> bool: ocapGranted: {},debug : bool) -> bool:
"""Receives a follow request within the POST section of HTTPServer """Receives a follow request within the POST section of HTTPServer
""" """
if not messageJson['type'].startswith('Follow'): if not messageJson['type'].startswith('Follow'):
@ -281,7 +281,7 @@ def receiveFollowRequest(session,baseDir: str,httpPrefix: str, \
print('DEBUG: sending Accept for follow request which arrived at '+ \ print('DEBUG: sending Accept for follow request which arrived at '+ \
nicknameToFollow+'@'+domainToFollow+' back to '+nickname+'@'+domain) nicknameToFollow+'@'+domainToFollow+' back to '+nickname+'@'+domain)
personUrl=messageJson['actor'] personUrl=messageJson['actor']
acceptJson=createAccept(baseDir,federationList,capsList, \ acceptJson=createAccept(baseDir,federationList,ocapGranted, \
nickname,domain,port, \ nickname,domain,port, \
personUrl,'',httpPrefix,messageJson) personUrl,'',httpPrefix,messageJson)
if debug: if debug:
@ -295,7 +295,7 @@ def receiveFollowRequest(session,baseDir: str,httpPrefix: str, \
nicknameToFollow,domainToFollow,port, \ nicknameToFollow,domainToFollow,port, \
nickname,domain,fromPort, '', \ nickname,domain,fromPort, '', \
httpPrefix,True,clientToServer, \ httpPrefix,True,clientToServer, \
federationList, capsList, \ federationList, ocapGranted, \
sendThreads,postLog,cachedWebfingers, \ sendThreads,postLog,cachedWebfingers, \
personCache,debug) personCache,debug)
@ -303,7 +303,7 @@ def sendFollowRequest(session,baseDir: str, \
nickname: str,domain: str,port: int,httpPrefix: str, \ nickname: str,domain: str,port: int,httpPrefix: str, \
followNickname: str,followDomain: str, \ followNickname: str,followDomain: str, \
followPort: bool,followHttpPrefix: str, \ followPort: bool,followHttpPrefix: str, \
clientToServer: bool,federationList: [],capsList: [], \ clientToServer: bool,federationList: [],ocapGranted: {}, \
sendThreads: [],postLog: [],cachedWebfingers: {}, \ sendThreads: [],postLog: [],cachedWebfingers: {}, \
personCache: {},debug : bool) -> {}: personCache: {},debug : bool) -> {}:
"""Gets the json object for sending a follow request """Gets the json object for sending a follow request
@ -320,8 +320,8 @@ def sendFollowRequest(session,baseDir: str, \
requestDomain=followDomain+':'+str(followPort) requestDomain=followDomain+':'+str(followPort)
# check that we are capable # check that we are capable
if capsList: if ocapGranted:
if not isCapable(followActor,capsList,'inbox:write'): if not isCapable(followActor,ocapGranted,'inbox:write'):
return None return None
statusNumber,published = getStatusNumber() statusNumber,published = getStatusNumber()
@ -342,7 +342,7 @@ def sendFollowRequest(session,baseDir: str, \
followNickname,followDomain,followPort, \ followNickname,followDomain,followPort, \
'https://www.w3.org/ns/activitystreams#Public', \ 'https://www.w3.org/ns/activitystreams#Public', \
httpPrefix,True,clientToServer, \ httpPrefix,True,clientToServer, \
federationList, capsList, \ federationList, ocapGranted, \
sendThreads,postLog,cachedWebfingers,personCache, debug) sendThreads,postLog,cachedWebfingers,personCache, debug)
return newFollowJson return newFollowJson

View File

@ -65,7 +65,7 @@ def inboxMessageHasParams(messageJson: {}) -> bool:
return False return False
return True return True
def inboxPermittedMessage(domain: str,messageJson: {},federationList: [],capsList: []) -> bool: def inboxPermittedMessage(domain: str,messageJson: {},federationList: [],ocapGranted: {}) -> bool:
""" check that we are receiving from a permitted domain """ check that we are receiving from a permitted domain
""" """
testParam='actor' testParam='actor'
@ -76,14 +76,14 @@ def inboxPermittedMessage(domain: str,messageJson: {},federationList: [],capsLis
if domain in actor: if domain in actor:
return True return True
if not urlPermitted(actor,federationList,capsList,"inbox:write"): if not urlPermitted(actor,federationList,ocapGranted,"inbox:write"):
return False return False
if messageJson['type']!='Follow': if messageJson['type']!='Follow':
if messageJson.get('object'): if messageJson.get('object'):
if messageJson['object'].get('inReplyTo'): if messageJson['object'].get('inReplyTo'):
inReplyTo=messageJson['object']['inReplyTo'] inReplyTo=messageJson['object']['inReplyTo']
if not urlPermitted(inReplyTo,federationList,capsList): if not urlPermitted(inReplyTo,federationList,ocapGranted):
return False return False
return True return True
@ -144,7 +144,7 @@ def savePostToInboxQueue(baseDir: str,httpPrefix: str,nickname: str, domain: str
commentjson.dump(newQueueItem, fp, indent=4, sort_keys=False) commentjson.dump(newQueueItem, fp, indent=4, sort_keys=False)
return filename return filename
def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {},queue: [],domain: str,port: int,useTor: bool,federationList: [],capsList: [],debug: bool) -> None: def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cachedWebfingers: {},personCache: {},queue: [],domain: str,port: int,useTor: bool,federationList: [],ocapGranted: {},debug: bool) -> None:
"""Processes received items and moves them to """Processes received items and moves them to
the appropriate directories the appropriate directories
""" """
@ -174,6 +174,57 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cache
with open(queueFilename, 'r') as fp: with open(queueFilename, 'r') as fp:
queueJson=commentjson.load(fp) queueJson=commentjson.load(fp)
# check that capabilities are accepted
if queueJson['post'].get('capabilities'):
if queueJson['post']['type']!='Accept':
if isinstance(queueJson['post']['capabilities'], dict):
if debug:
print('DEBUG: received post capabilities should be a string, not a dict')
pprint(queueJson['post'])
os.remove(queueFilename)
queue.pop(0)
continue
if not queueJson['post'].get('actor'):
if debug:
print('DEBUG: post should have an actor')
os.remove(queueFilename)
queue.pop(0)
continue
ocapFilename=baseDir+'/ocap/accept/'+queueJson['post']['actor'].replace('/','#')+'.json'
if not os.path.isfile(ocapFilename):
if debug:
print('DEBUG: capabilities for '+queueJson['post']['actor']+' do not exist')
os.remove(queueFilename)
queue.pop(0)
continue
with open(ocapFilename, 'r') as fp:
oc=commentjson.load(fp)
if not oc.get('id'):
if debug:
print('DEBUG: capabilities for '+queueJson['post']['actor']+' do not contain an id')
os.remove(queueFilename)
queue.pop(0)
continue
if oc['id']!=queueJson['post']['capabilities']:
if debug:
print('DEBUG: capabilities id mismatch')
os.remove(queueFilename)
queue.pop(0)
continue
if not queueJson['post']['capabilities'].get('capability'):
if debug:
print('DEBUG: missing capability list')
os.remove(queueFilename)
queue.pop(0)
continue
if 'inbox:write' not in queueJson['post']['capabilities']['capability']:
if debug:
print('DEBUG: insufficient capabilities to write to inbox from '+ \
queueJson['post']['actor'])
os.remove(queueFilename)
queue.pop(0)
continue
# Try a few times to obtain the public key # Try a few times to obtain the public key
pubKey=None pubKey=None
keyId=None keyId=None
@ -232,7 +283,7 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cache
cachedWebfingers, cachedWebfingers,
personCache, personCache,
queueJson['post'], \ queueJson['post'], \
federationList,capsList, \ federationList,ocapGranted, \
debug): debug):
if debug: if debug:
print('DEBUG: Follow accepted from '+keyId) print('DEBUG: Follow accepted from '+keyId)
@ -246,7 +297,7 @@ def runInboxQueue(baseDir: str,httpPrefix: str,sendThreads: [],postLog: [],cache
cachedWebfingers, cachedWebfingers,
personCache, personCache,
queueJson['post'], \ queueJson['post'], \
federationList,capsList, \ federationList,ocapGranted, \
debug): debug):
if debug: if debug:
print('DEBUG: Accept/Reject received from '+keyId) print('DEBUG: Accept/Reject received from '+keyId)

View File

@ -17,7 +17,7 @@ def like(baseDir: str,federationList: [],nickname: str,domain: str,port: int, \
and ccUrl might be a specific person whose post was liked and ccUrl might be a specific person whose post was liked
objectUrl is typically the url of the message, corresponding to url or atomUri in createPostBase objectUrl is typically the url of the message, corresponding to url or atomUri in createPostBase
""" """
if not urlPermitted(objectUrl,federationList,capsList,"inbox:write"): if not urlPermitted(objectUrl,federationList,ocapGranted,"inbox:write"):
return None return None
if port!=80 and port!=443: if port!=80 and port!=443:

View File

@ -153,7 +153,7 @@ def getPersonBox(session,wfRequest: {},personCache: {}, \
def getPosts(session,outboxUrl: str,maxPosts: int,maxMentions: int, \ def getPosts(session,outboxUrl: str,maxPosts: int,maxMentions: int, \
maxEmoji: int,maxAttachments: int, \ maxEmoji: int,maxAttachments: int, \
federationList: [], capsList: [],\ federationList: [], ocapGranted: {},\
personCache: {},raw: bool,simple: bool) -> {}: personCache: {},raw: bool,simple: bool) -> {}:
personPosts={} personPosts={}
if not outboxUrl: if not outboxUrl:
@ -193,7 +193,7 @@ def getPosts(session,outboxUrl: str,maxPosts: int,maxMentions: int, \
if tagItem['icon'].get('url'): if tagItem['icon'].get('url'):
# No emoji from non-permitted domains # No emoji from non-permitted domains
if urlPermitted(tagItem['icon']['url'], \ if urlPermitted(tagItem['icon']['url'], \
federationList,capsList, \ federationList,ocapGranted, \
"objects:read"): "objects:read"):
emojiName=tagItem['name'] emojiName=tagItem['name']
emojiIcon=tagItem['icon']['url'] emojiIcon=tagItem['icon']['url']
@ -217,7 +217,7 @@ def getPosts(session,outboxUrl: str,maxPosts: int,maxMentions: int, \
if item['object']['inReplyTo']: if item['object']['inReplyTo']:
# No replies to non-permitted domains # No replies to non-permitted domains
if not urlPermitted(item['object']['inReplyTo'], \ if not urlPermitted(item['object']['inReplyTo'], \
federationList,capsList, \ federationList,ocapGranted, \
"objects:read"): "objects:read"):
continue continue
inReplyTo = item['object']['inReplyTo'] inReplyTo = item['object']['inReplyTo']
@ -227,7 +227,7 @@ def getPosts(session,outboxUrl: str,maxPosts: int,maxMentions: int, \
if item['object']['conversation']: if item['object']['conversation']:
# no conversations originated in non-permitted domains # no conversations originated in non-permitted domains
if urlPermitted(item['object']['conversation'], \ if urlPermitted(item['object']['conversation'], \
federationList,capsList,"objects:read"): federationList,ocapGranted,"objects:read"):
conversation = item['object']['conversation'] conversation = item['object']['conversation']
attachment = [] attachment = []
@ -237,7 +237,7 @@ def getPosts(session,outboxUrl: str,maxPosts: int,maxMentions: int, \
if attach.get('name') and attach.get('url'): if attach.get('name') and attach.get('url'):
# no attachments from non-permitted domains # no attachments from non-permitted domains
if urlPermitted(attach['url'], \ if urlPermitted(attach['url'], \
federationList,capsList, \ federationList,ocapGranted, \
"objects:read"): "objects:read"):
attachment.append([attach['name'],attach['url']]) attachment.append([attach['name'],attach['url']])
@ -319,7 +319,7 @@ def savePostToBox(baseDir: str,httpPrefix: str,postId: str, \
def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
toUrl: str, ccUrl: str, httpPrefix: str, content: str, \ toUrl: str, ccUrl: str, httpPrefix: str, content: str, \
followersOnly: bool, saveToFile: bool, clientToServer: bool, \ followersOnly: bool, saveToFile: bool, clientToServer: bool, \
capsList: [], \ ocapGranted: {}, \
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}: inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
"""Creates a message """Creates a message
""" """
@ -335,8 +335,7 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
postTo=postCC postTo=postCC
postCC='' postCC=''
newPostId=httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber newPostId=httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber
# TODO
capabilityUrl=''
sensitive=False sensitive=False
summary=None summary=None
if subject: if subject:
@ -344,13 +343,24 @@ def createPostBase(baseDir: str,nickname: str, domain: str, port: int, \
sensitive=True sensitive=True
if not clientToServer: if not clientToServer:
actorUrl=httpPrefix+'://'+domain+'/users/'+nickname actorUrl=httpPrefix+'://'+domain+'/users/'+nickname
if capsList: if ocapGranted:
if not isCapable(actorUrl,capsList,'inbox:write'): if not isCapable(actorUrl,ocapGranted,'inbox:write'):
return None return None
# if capabilities have been granted for this actor
# then get the corresponding id
capabilityId=None
ocapFilename= \
baseDir+'/ocap/granted/'+actorUrl.replace('/','#')+'.json'
if os.path.isfile(ocapFilename):
with open(ocapFilename, 'r') as fp:
oc=commentjson.load(fp)
if oc.get('id'):
capabilityId=oc['id']
newPost = { newPost = {
'id': newPostId+'/activity', 'id': newPostId+'/activity',
'capability': capabilityUrl, 'capability': capabilityId,
'type': 'Create', 'type': 'Create',
'actor': actorUrl, 'actor': actorUrl,
'published': published, 'published': published,
@ -454,7 +464,7 @@ def outboxMessageCreateWrap(httpPrefix: str,nickname: str,domain: str, \
def createPublicPost(baseDir: str, def createPublicPost(baseDir: str,
nickname: str, domain: str, port: int,httpPrefix: str, \ nickname: str, domain: str, port: int,httpPrefix: str, \
content: str, followersOnly: bool, saveToFile: bool, content: str, followersOnly: bool, saveToFile: bool,
clientToServer: bool, capsList: [],\ clientToServer: bool, ocapGranted: {},\
inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}: inReplyTo=None, inReplyToAtomUri=None, subject=None) -> {}:
"""Public post to the outbox """Public post to the outbox
""" """
@ -462,10 +472,10 @@ def createPublicPost(baseDir: str,
'https://www.w3.org/ns/activitystreams#Public', \ 'https://www.w3.org/ns/activitystreams#Public', \
httpPrefix+'://'+domain+'/users/'+nickname+'/followers', \ httpPrefix+'://'+domain+'/users/'+nickname+'/followers', \
httpPrefix, content, followersOnly, saveToFile, \ httpPrefix, content, followersOnly, saveToFile, \
clientToServer, capsList, \ clientToServer, ocapGranted, \
inReplyTo, inReplyToAtomUri, subject) inReplyTo, inReplyToAtomUri, subject)
def threadSendPost(session,postJsonObject: {},federationList: [],capsList: [],\ def threadSendPost(session,postJsonObject: {},federationList: [],ocapGranted: {},\
inboxUrl: str, baseDir: str,signatureHeaderJson: {},postLog: [], inboxUrl: str, baseDir: str,signatureHeaderJson: {},postLog: [],
debug :bool) -> None: debug :bool) -> None:
"""Sends a post with exponential backoff """Sends a post with exponential backoff
@ -474,7 +484,7 @@ def threadSendPost(session,postJsonObject: {},federationList: [],capsList: [],\
backoffTime=60 backoffTime=60
for attempt in range(20): for attempt in range(20):
postResult = postJson(session,postJsonObject,federationList, \ postResult = postJson(session,postJsonObject,federationList, \
capsList,inboxUrl,signatureHeaderJson, \ ocapGranted,inboxUrl,signatureHeaderJson, \
"inbox:write") "inbox:write")
if postResult: if postResult:
if debug: if debug:
@ -501,7 +511,7 @@ def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \
toNickname: str, toDomain: str, toPort: int, cc: str, \ toNickname: str, toDomain: str, toPort: int, cc: str, \
httpPrefix: str, content: str, followersOnly: bool, \ httpPrefix: str, content: str, followersOnly: bool, \
saveToFile: bool, clientToServer: bool, \ saveToFile: bool, clientToServer: bool, \
federationList: [], capsList: [],\ federationList: [], ocapGranted: {},\
sendThreads: [], postLog: [], cachedWebfingers: {},personCache: {}, \ sendThreads: [], postLog: [], cachedWebfingers: {},personCache: {}, \
debug=False,inReplyTo=None,inReplyToAtomUri=None,subject=None) -> int: debug=False,inReplyTo=None,inReplyToAtomUri=None,subject=None) -> int:
"""Post to another inbox """Post to another inbox
@ -550,7 +560,7 @@ def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \
createPostBase(baseDir,nickname,domain,port, \ createPostBase(baseDir,nickname,domain,port, \
toPersonId,cc,httpPrefix,content, \ toPersonId,cc,httpPrefix,content, \
followersOnly,saveToFile,clientToServer, \ followersOnly,saveToFile,clientToServer, \
capsList, \ ocapGranted, \
inReplyTo,inReplyToAtomUri,subject) inReplyTo,inReplyToAtomUri,subject)
# get the senders private key # get the senders private key
@ -574,7 +584,7 @@ def sendPost(session,baseDir: str,nickname: str, domain: str, port: int, \
thr = threadWithTrace(target=threadSendPost,args=(session, \ thr = threadWithTrace(target=threadSendPost,args=(session, \
postJsonObject.copy(), \ postJsonObject.copy(), \
federationList, \ federationList, \
capsList, \ ocapGranted, \
inboxUrl,baseDir, \ inboxUrl,baseDir, \
signatureHeaderJson.copy(), \ signatureHeaderJson.copy(), \
postLog, postLog,
@ -587,7 +597,7 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str, \
nickname: str, domain: str, port: int, \ nickname: str, domain: str, port: int, \
toNickname: str, toDomain: str, toPort: int, cc: str, \ toNickname: str, toDomain: str, toPort: int, cc: str, \
httpPrefix: str, saveToFile: bool, clientToServer: bool, \ httpPrefix: str, saveToFile: bool, clientToServer: bool, \
federationList: [], capsList: [], \ federationList: [], ocapGranted: {}, \
sendThreads: [], postLog: [], cachedWebfingers: {}, \ sendThreads: [], postLog: [], cachedWebfingers: {}, \
personCache: {}, debug: bool) -> int: personCache: {}, debug: bool) -> int:
"""Sends a signed json object to an inbox/outbox """Sends a signed json object to an inbox/outbox
@ -661,7 +671,7 @@ def sendSignedJson(postJsonObject: {},session,baseDir: str, \
args=(session, \ args=(session, \
postJsonObject.copy(), \ postJsonObject.copy(), \
federationList, \ federationList, \
capsList, \ ocapGranted, \
inboxUrl,baseDir, \ inboxUrl,baseDir, \
signatureHeaderJson.copy(), \ signatureHeaderJson.copy(), \
postLog, postLog,
@ -812,7 +822,7 @@ def getPublicPostsOfPerson(nickname: str,domain: str, \
personCache={} personCache={}
cachedWebfingers={} cachedWebfingers={}
federationList=[] federationList=[]
capsList=[] ocapGranted={}
httpPrefix='https' httpPrefix='https'
handle=httpPrefix+"://"+domain+"/@"+nickname handle=httpPrefix+"://"+domain+"/@"+nickname
@ -829,6 +839,6 @@ def getPublicPostsOfPerson(nickname: str,domain: str, \
maxEmoji=10 maxEmoji=10
maxAttachments=5 maxAttachments=5
userPosts = getPosts(session,personUrl,30,maxMentions,maxEmoji, \ userPosts = getPosts(session,personUrl,30,maxMentions,maxEmoji, \
maxAttachments,federationList,capsList, \ maxAttachments,federationList,ocapGranted, \
personCache,raw,simple) personCache,raw,simple)
#print(str(userPosts)) #print(str(userPosts))

View File

@ -39,7 +39,7 @@ def getJson(session,url: str,headers: {},params: {}) -> {}:
pass pass
return None return None
def postJson(session,postJsonObject: {},federationList: [],capsList: [],inboxUrl: str,headers: {},capability: str) -> str: def postJson(session,postJsonObject: {},federationList: [],ocapGranted: {},inboxUrl: str,headers: {},capability: str) -> str:
"""Post a json message to the inbox of another person """Post a json message to the inbox of another person
Supplying a capability, such as "inbox:write" Supplying a capability, such as "inbox:write"
""" """
@ -47,7 +47,7 @@ def postJson(session,postJsonObject: {},federationList: [],capsList: [],inboxUrl
# always allow capability requests # always allow capability requests
if not capability.startswith('cap'): if not capability.startswith('cap'):
# check that we are posting to a permitted domain # check that we are posting to a permitted domain
if not urlPermitted(inboxUrl,federationList,capsList,capability): if not urlPermitted(inboxUrl,federationList,ocapGranted,capability):
return None return None
postResult = session.post(url = inboxUrl, data = json.dumps(postJsonObject), headers=headers) postResult = session.post(url = inboxUrl, data = json.dumps(postJsonObject), headers=headers)

View File

@ -108,7 +108,7 @@ def testThreads():
thr.join() thr.join()
assert thr.isAlive()==False assert thr.isAlive()==False
def createServerAlice(path: str,domain: str,port: int,federationList: [],capsList: [],hasFollows: bool,hasPosts :bool): def createServerAlice(path: str,domain: str,port: int,federationList: [],ocapGranted: {},hasFollows: bool,hasPosts :bool):
print('Creating test server: Alice on port '+str(port)) print('Creating test server: Alice on port '+str(port))
if os.path.isdir(path): if os.path.isdir(path):
shutil.rmtree(path) shutil.rmtree(path)
@ -126,15 +126,15 @@ def createServerAlice(path: str,domain: str,port: int,federationList: [],capsLis
followPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList,True) followPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList,True)
followerOfPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList,True) followerOfPerson(path,nickname,domain,'bob','127.0.0.100:61936',federationList,True)
if hasPosts: if hasPosts:
createPublicPost(path,nickname, domain, port,httpPrefix, "No wise fish would go anywhere without a porpoise", False, True, clientToServer,capsList) createPublicPost(path,nickname, domain, port,httpPrefix, "No wise fish would go anywhere without a porpoise", False, True, clientToServer,ocapGranted)
createPublicPost(path,nickname, domain, port,httpPrefix, "Curiouser and curiouser!", False, True, clientToServer,capsList) createPublicPost(path,nickname, domain, port,httpPrefix, "Curiouser and curiouser!", False, True, clientToServer,ocapGranted)
createPublicPost(path,nickname, domain, port,httpPrefix, "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", False, True, clientToServer,capsList) createPublicPost(path,nickname, domain, port,httpPrefix, "In the gardens of memory, in the palace of dreams, that is where you and I shall meet", False, True, clientToServer,ocapGranted)
global testServerAliceRunning global testServerAliceRunning
testServerAliceRunning = True testServerAliceRunning = True
print('Server running: Alice') print('Server running: Alice')
runDaemon(path,domain,port,httpPrefix,federationList,capsList,useTor,True) runDaemon(path,domain,port,httpPrefix,federationList,ocapGranted,useTor,True)
def createServerBob(path: str,domain: str,port: int,federationList: [],capsList: [],hasFollows: bool,hasPosts :bool): def createServerBob(path: str,domain: str,port: int,federationList: [],ocapGranted: {},hasFollows: bool,hasPosts :bool):
print('Creating test server: Bob on port '+str(port)) print('Creating test server: Bob on port '+str(port))
if os.path.isdir(path): if os.path.isdir(path):
shutil.rmtree(path) shutil.rmtree(path)
@ -152,13 +152,13 @@ def createServerBob(path: str,domain: str,port: int,federationList: [],capsList:
followPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList,True) followPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList,True)
followerOfPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList,True) followerOfPerson(path,nickname,domain,'alice','127.0.0.50:61935',federationList,True)
if hasPosts: if hasPosts:
createPublicPost(path,nickname, domain, port,httpPrefix, "It's your life, live it your way.", False, True, clientToServer,capsList) createPublicPost(path,nickname, domain, port,httpPrefix, "It's your life, live it your way.", False, True, clientToServer,ocapGranted)
createPublicPost(path,nickname, domain, port,httpPrefix, "One of the things I've realised is that I am very simple", False, True, clientToServer,capsList) createPublicPost(path,nickname, domain, port,httpPrefix, "One of the things I've realised is that I am very simple", False, True, clientToServer,ocapGranted)
createPublicPost(path,nickname, domain, port,httpPrefix, "Quantum physics is a bit of a passion of mine", False, True, clientToServer,capsList) createPublicPost(path,nickname, domain, port,httpPrefix, "Quantum physics is a bit of a passion of mine", False, True, clientToServer,ocapGranted)
global testServerBobRunning global testServerBobRunning
testServerBobRunning = True testServerBobRunning = True
print('Server running: Bob') print('Server running: Bob')
runDaemon(path,domain,port,httpPrefix,federationList,capsList,useTor,True) runDaemon(path,domain,port,httpPrefix,federationList,ocapGranted,useTor,True)
def testPostMessageBetweenServers(): def testPostMessageBetweenServers():
print('Testing sending message from one server to the inbox of another') print('Testing sending message from one server to the inbox of another')
@ -171,7 +171,7 @@ def testPostMessageBetweenServers():
httpPrefix='http' httpPrefix='http'
useTor=False useTor=False
federationList=['127.0.0.50','127.0.0.100'] federationList=['127.0.0.50','127.0.0.100']
capsList=[] ocapGranted={}
baseDir=os.getcwd() baseDir=os.getcwd()
if os.path.isdir(baseDir+'/.tests'): if os.path.isdir(baseDir+'/.tests'):
@ -182,12 +182,12 @@ def testPostMessageBetweenServers():
aliceDir=baseDir+'/.tests/alice' aliceDir=baseDir+'/.tests/alice'
aliceDomain='127.0.0.50' aliceDomain='127.0.0.50'
alicePort=61935 alicePort=61935
thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,capsList,True,True),daemon=True) thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,ocapGranted,True,True),daemon=True)
bobDir=baseDir+'/.tests/bob' bobDir=baseDir+'/.tests/bob'
bobDomain='127.0.0.100' bobDomain='127.0.0.100'
bobPort=61936 bobPort=61936
thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,capsList,True,True),daemon=True) thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,ocapGranted,True,True),daemon=True)
thrAlice.start() thrAlice.start()
thrBob.start() thrBob.start()
@ -214,7 +214,7 @@ def testPostMessageBetweenServers():
ccUrl=None ccUrl=None
alicePersonCache={} alicePersonCache={}
aliceCachedWebfingers={} aliceCachedWebfingers={}
sendResult = sendPost(sessionAlice,aliceDir,'alice', aliceDomain, alicePort, 'bob', bobDomain, bobPort, ccUrl, httpPrefix, 'Why is a mouse when it spins?', followersOnly, saveToFile, clientToServer, federationList, capsList, aliceSendThreads, alicePostLog, aliceCachedWebfingers,alicePersonCache,inReplyTo, inReplyToAtomUri, subject) sendResult = sendPost(sessionAlice,aliceDir,'alice', aliceDomain, alicePort, 'bob', bobDomain, bobPort, ccUrl, httpPrefix, 'Why is a mouse when it spins?', followersOnly, saveToFile, clientToServer, federationList, ocapGranted, aliceSendThreads, alicePostLog, aliceCachedWebfingers,alicePersonCache,inReplyTo, inReplyToAtomUri, subject)
print('sendResult: '+str(sendResult)) print('sendResult: '+str(sendResult))
queuePath=bobDir+'/accounts/bob@'+bobDomain+'/queue' queuePath=bobDir+'/accounts/bob@'+bobDomain+'/queue'
@ -254,7 +254,7 @@ def testFollowBetweenServers():
httpPrefix='http' httpPrefix='http'
useTor=False useTor=False
federationList=['127.0.0.42','127.0.0.64'] federationList=['127.0.0.42','127.0.0.64']
capsList=[] ocapGranted={}
baseDir=os.getcwd() baseDir=os.getcwd()
if os.path.isdir(baseDir+'/.tests'): if os.path.isdir(baseDir+'/.tests'):
@ -265,12 +265,12 @@ def testFollowBetweenServers():
aliceDir=baseDir+'/.tests/alice' aliceDir=baseDir+'/.tests/alice'
aliceDomain='127.0.0.42' aliceDomain='127.0.0.42'
alicePort=61935 alicePort=61935
thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,capsList,False,False),daemon=True) thrAlice = threadWithTrace(target=createServerAlice,args=(aliceDir,aliceDomain,alicePort,federationList,ocapGranted,False,False),daemon=True)
bobDir=baseDir+'/.tests/bob' bobDir=baseDir+'/.tests/bob'
bobDomain='127.0.0.64' bobDomain='127.0.0.64'
bobPort=61936 bobPort=61936
thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,capsList,False,False),daemon=True) thrBob = threadWithTrace(target=createServerBob,args=(bobDir,bobDomain,bobPort,federationList,ocapGranted,False,False),daemon=True)
thrAlice.start() thrAlice.start()
thrBob.start() thrBob.start()
@ -305,7 +305,7 @@ def testFollowBetweenServers():
sendFollowRequest(sessionAlice,aliceDir, \ sendFollowRequest(sessionAlice,aliceDir, \
'alice',aliceDomain,alicePort,httpPrefix, \ 'alice',aliceDomain,alicePort,httpPrefix, \
'bob',bobDomain,bobPort,httpPrefix, \ 'bob',bobDomain,bobPort,httpPrefix, \
clientToServer,federationList,capsList, clientToServer,federationList,ocapGranted,
aliceSendThreads,alicePostLog, \ aliceSendThreads,alicePostLog, \
aliceCachedWebfingers,alicePersonCache,True) aliceCachedWebfingers,alicePersonCache,True)
print('sendResult: '+str(sendResult)) print('sendResult: '+str(sendResult))

View File

@ -49,9 +49,9 @@ def domainPermitted(domain: str, federationList: []):
return True return True
return False return False
def urlPermitted(url: str, federationList: [],capsList: [],capability: str): def urlPermitted(url: str, federationList: [],ocapGranted: {},capability: str):
if capsList: if ocapGranted:
if not isCapable(url,capsList,capability): if not isCapable(url,ocapGranted,capability):
return False return False
if len(federationList)==0: if len(federationList)==0:
return True return True