Example json

master
Bob Mottram 2019-07-07 14:53:12 +01:00
parent 258fa7abf3
commit 3e3e4fec4e
4 changed files with 80 additions and 25 deletions

View File

@ -40,23 +40,23 @@ This is one proposed way that OCAP could work.
Default capabilities are initially set up when a follow request is made. The Accept activity sent back from a follow request can be received by any instance. A capabilities accept activity is attached to the follow accept. Default capabilities are initially set up when a follow request is made. The Accept activity sent back from a follow request can be received by any instance. A capabilities accept activity is attached to the follow accept.
``` text ``` text
Actor A Alice
| |
V V
Follow Request Follow Request
| |
V V
Actor B Bob
| |
V V
Create/store default Capabilities Create/store default Capabilities
for Actor A for Alice
| |
V V
Follow Accept + default Capabilities Follow Accept + default Capabilities
| |
V V
Actor A Alice
| |
V V
Store Granted Capabilities Store Granted Capabilities
@ -64,18 +64,51 @@ Default capabilities are initially set up when a follow request is made. The Acc
The default capabilities could be *any preferred policy* of the instance. They could be no capabilities at all, read only or full access to everything. The default capabilities could be *any preferred policy* of the instance. They could be no capabilities at all, read only or full access to everything.
Example Follow request from **Alice** to **Bob**:
``` json
{'actor': 'http://alicedomain.net/users/alice',
'cc': ['https://www.w3.org/ns/activitystreams#Public'],
'id': 'http://alicedomain.net/users/alice/statuses/1562507338839876',
'object': 'http://bobdomain.net/users/bob',
'published': '2019-07-07T13:48:58Z',
'to': ['http://bobdomain.net/users/bob'],
'type': 'Follow'}
```
Follow Accept from **Bob** to **Alice** with attached capabilities.
``` json
{'actor': 'http://bobdomain.net/users/bob',
'capabilities': {'actor': 'http://bobdomain.net/users/bob',
'capability': ['inbox:write', 'objects:read'],
'id': 'http://bobdomain.net/caps/rOYtHApyr4ZWDUgEE1KqjhTe0kI3T2wJ',
'scope': 'http://alicedomain.net/users/alice',
'type': 'Capability'},
'cc': [],
'object': {'actor': 'http://alicedomain.net/users/alice',
'cc': ['https://www.w3.org/ns/activitystreams#Public'],
'id': 'http://alicedomain.net/users/alice/statuses/1562507338839876',
'object': 'http://bobdomain.net/users/bob',
'published': '2019-07-07T13:48:58Z',
'to': ['http://bobdomain.net/users/bob'],
'type': 'Follow'},
'to': ['http://alicedomain.net/users/alice'],
'type': 'Accept'}
```
When posts are subsequently sent from the following instance (server-to-server) they should have the corresponding capability id string attached within the Create wrapper. When posts are subsequently sent from the following instance (server-to-server) they should have the corresponding capability id string attached within the Create wrapper.
``` text ``` text
Actor A Alice
| |
V V
Send Post Send Post
Attach id from Stored Capabilities Attach id from Stored Capabilities
granted by Actor B granted by Bob
| |
V V
Actor B Bob
| |
V V
Check Capability id matches Check Capability id matches
@ -88,7 +121,7 @@ When posts are subsequently sent from the following instance (server-to-server)
Accept or reject incoming post Accept or reject incoming post
``` ```
Subsequently **Actor B** could change the stored capabilities for **Actor A** in its database, giving the new object a different id. This could be sent back to **Actor A**, perhaps as another **follow Accept** activity with attached capabilities. This could then change the way in which **Actor A** can interact with **Actor B**, for example by adding or removing the ability to like or reply to posts. Subsequently **Bob** could change the stored capabilities for **Alice** in their database, giving the new object a different id. This could be sent back to **Alice**, perhaps as another **follow Accept** activity with attached capabilities. This could then change the way in which **Alice** can interact with **Bob**, for example by adding or removing the ability to like or reply to posts.
## Install ## Install

View File

@ -57,7 +57,7 @@ def createAccept(baseDir: str,federationList: [],ocapGranted: {}, \
toUrl: str,ccUrl: str,httpPrefix: str, \ toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {}) -> {}: objectJson: {}) -> {}:
# create capabilities accept # create capabilities accept
ocapNew=capabilitiesAccept(baseDir,httpPrefix,nickname,domain, toUrl, True) ocapNew=capabilitiesAccept(baseDir,httpPrefix,nickname,domain,port,toUrl,True)
return createAcceptReject(baseDir,federationList,ocapGranted, \ return createAcceptReject(baseDir,federationList,ocapGranted, \
nickname,domain,port, \ nickname,domain,port, \
toUrl,ccUrl,httpPrefix, \ toUrl,ccUrl,httpPrefix, \
@ -85,6 +85,15 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
return return
if not messageJson['object']['type']=='Follow': if not messageJson['object']['type']=='Follow':
return 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']))
return
if debug: if debug:
print('DEBUG: follow Accept received') print('DEBUG: follow Accept received')
thisActor=messageJson['object']['actor'] thisActor=messageJson['object']['actor']
@ -94,22 +103,27 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
if debug: if debug:
print('DEBUG: domain not found in '+thisActor) print('DEBUG: domain not found in '+thisActor)
return return
if acceptedDomain != domain: #if acceptedDomain != domain:
if debug: # if debug:
print('DEBUG: domain mismatch '+acceptedDomain+' != '+domain) # print('DEBUG: domain mismatch '+acceptedDomain+' != '+domain)
return # return
if not nickname: if not nickname:
if debug: if debug:
print('DEBUG: nickname not found in '+thisActor) print('DEBUG: nickname not found in '+thisActor)
return return
if acceptedPort: if acceptedPort:
if not '/'+domain+':'+str(acceptedPort)+'/users/'+nickname in thisActor: if not '/'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname in thisActor:
if debug: if debug:
print('Port: '+str(acceptedPort))
print('Expected: /'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname)
print('Actual: '+thisActor)
print('DEBUG: unrecognized actor '+thisActor) print('DEBUG: unrecognized actor '+thisActor)
return return
else: else:
if not '/'+domain+'/users/'+nickname in thisActor: if not '/'+acceptedDomain+'/users/'+nickname in thisActor:
if debug: if debug:
print('Expected: /'+acceptedDomain+'/users/'+nickname)
print('Actual: '+thisActor)
print('DEBUG: unrecognized actor '+thisActor) print('DEBUG: unrecognized actor '+thisActor)
return return
followedActor=messageJson['object']['object'] followedActor=messageJson['object']['object']
@ -128,14 +142,15 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
if isinstance(messageJson['object']['capabilities'], dict): if isinstance(messageJson['object']['capabilities'], dict):
capabilitiesGrantedSave(baseDir,messageJson['object']['capabilities']) capabilitiesGrantedSave(baseDir,messageJson['object']['capabilities'])
if followPerson(baseDir,nickname,domain, \ if followPerson(baseDir, \
nickname,acceptedDomain, \
followedNickname,followedDomain, \ followedNickname,followedDomain, \
federationList,debug): federationList,debug):
if debug: if debug:
print('DEBUG: '+nickname+'@'+domain+' followed '+followedNickname+'@'+followedDomain) print('DEBUG: '+nickname+'@'+acceptedDomain+' followed '+followedNickname+'@'+followedDomain)
else: else:
if debug: if debug:
print('DEBUG: Unable to create follow - '+nickname+'@'+domain+' -> '+followedNickname+'@'+followedDomain) print('DEBUG: Unable to create follow - '+nickname+'@'+acceptedDomain+' -> '+followedNickname+'@'+followedDomain)
def receiveAcceptReject(session,baseDir: str, \ def receiveAcceptReject(session,baseDir: str, \
httpPrefix: str,domain :str,port: int, \ httpPrefix: str,domain :str,port: int, \

View File

@ -40,7 +40,8 @@ def capabilitiesRequest(baseDir: str,httpPrefix: str,domain: str, \
} }
return ocapRequest return ocapRequest
def capabilitiesAccept(baseDir: str,httpPrefix: str,nickname: str,domain: str, \ def capabilitiesAccept(baseDir: str,httpPrefix: str, \
nickname: str,domain: str, port: int, \
acceptedActor: str, saveToFile: bool, \ acceptedActor: str, saveToFile: bool, \
acceptedCaps=["inbox:write","objects:read"]) -> {}: acceptedCaps=["inbox:write","objects:read"]) -> {}:
# This gets returned to capabilities requester # This gets returned to capabilities requester
@ -50,6 +51,10 @@ def capabilitiesAccept(baseDir: str,httpPrefix: str,nickname: str,domain: str, \
if len(acceptedActor)>256: if len(acceptedActor)>256:
return None return None
fullDomain=domain
if port!=80 and port !=443:
fullDomain=domain+':'+str(port)
# make directories to store capabilities # make directories to store capabilities
capabilitiesMakeDirs(baseDir) capabilitiesMakeDirs(baseDir)
filename=baseDir+'/ocap/accept/'+acceptedActor.replace('/','#')+'.json' filename=baseDir+'/ocap/accept/'+acceptedActor.replace('/','#')+'.json'
@ -63,14 +68,14 @@ def capabilitiesAccept(baseDir: str,httpPrefix: str,nickname: str,domain: str, \
if not ocapAccept: if not ocapAccept:
ocapId=createPassword(32) ocapId=createPassword(32)
ocapAccept = { ocapAccept = {
"id": httpPrefix+"://"+domain+"/caps/"+ocapId, "id": httpPrefix+"://"+fullDomain+"/caps/"+ocapId,
"type": "Capability", "type": "Capability",
"capability": acceptedCaps, "capability": acceptedCaps,
"scope": acceptedActor, "scope": acceptedActor,
"actor": httpPrefix+"://"+domain "actor": httpPrefix+"://"+fullDomain
} }
if nickname: if nickname:
ocapAccept['actor']=httpPrefix+"://"+domain+'/users/'+nickname ocapAccept['actor']=httpPrefix+"://"+fullDomain+'/users/'+nickname
if saveToFile: if saveToFile:
with open(filename, 'w') as fp: with open(filename, 'w') as fp:

View File

@ -282,7 +282,7 @@ def receiveFollowRequest(session,baseDir: str,httpPrefix: str, \
nicknameToFollow+'@'+domainToFollow+' back to '+nickname+'@'+domain) nicknameToFollow+'@'+domainToFollow+' back to '+nickname+'@'+domain)
personUrl=messageJson['actor'] personUrl=messageJson['actor']
acceptJson=createAccept(baseDir,federationList,ocapGranted, \ acceptJson=createAccept(baseDir,federationList,ocapGranted, \
nickname,domain,port, \ nicknameToFollow,domainToFollow,port, \
personUrl,'',httpPrefix,messageJson) personUrl,'',httpPrefix,messageJson)
if debug: if debug:
pprint(acceptJson) pprint(acceptJson)
@ -310,9 +310,11 @@ def sendFollowRequest(session,baseDir: str, \
""" """
if not domainPermitted(followDomain,federationList): if not domainPermitted(followDomain,federationList):
return None return None
fullDomain=domain
followActor=httpPrefix+'://'+domain+'/users/'+nickname followActor=httpPrefix+'://'+domain+'/users/'+nickname
if port!=80 and port!=443: if port!=80 and port!=443:
fullDomain=domain+':'+str(port)
followActor=httpPrefix+'://'+domain+':'+str(port)+'/users/'+nickname followActor=httpPrefix+'://'+domain+':'+str(port)+'/users/'+nickname
requestDomain=followDomain requestDomain=followDomain
@ -329,7 +331,7 @@ def sendFollowRequest(session,baseDir: str, \
followedId=followHttpPrefix+'://'+requestDomain+'/users/'+followNickname followedId=followHttpPrefix+'://'+requestDomain+'/users/'+followNickname
newFollowJson = { newFollowJson = {
'id': httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber, 'id': httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber,
'type': 'Follow', 'type': 'Follow',
'actor': followActor, 'actor': followActor,
'object': followedId, 'object': followedId,