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.
``` text
Actor A
Alice
|
V
Follow Request
|
V
Actor B
Bob
|
V
Create/store default Capabilities
for Actor A
for Alice
|
V
Follow Accept + default Capabilities
|
V
Actor A
Alice
|
V
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.
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.
``` text
Actor A
Alice
|
V
Send Post
Attach id from Stored Capabilities
granted by Actor B
granted by Bob
|
V
Actor B
Bob
|
V
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
```
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

View File

@ -57,7 +57,7 @@ def createAccept(baseDir: str,federationList: [],ocapGranted: {}, \
toUrl: str,ccUrl: str,httpPrefix: str, \
objectJson: {}) -> {}:
# 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, \
nickname,domain,port, \
toUrl,ccUrl,httpPrefix, \
@ -85,6 +85,15 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
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']))
return
if debug:
print('DEBUG: follow Accept received')
thisActor=messageJson['object']['actor']
@ -94,22 +103,27 @@ 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 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 '/'+domain+':'+str(acceptedPort)+'/users/'+nickname in thisActor:
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 '/'+domain+'/users/'+nickname in thisActor:
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']
@ -128,14 +142,15 @@ def acceptFollow(baseDir: str,domain : str,messageJson: {}, \
if isinstance(messageJson['object']['capabilities'], dict):
capabilitiesGrantedSave(baseDir,messageJson['object']['capabilities'])
if followPerson(baseDir,nickname,domain, \
if followPerson(baseDir, \
nickname,acceptedDomain, \
followedNickname,followedDomain, \
federationList,debug):
if debug:
print('DEBUG: '+nickname+'@'+domain+' followed '+followedNickname+'@'+followedDomain)
print('DEBUG: '+nickname+'@'+acceptedDomain+' followed '+followedNickname+'@'+followedDomain)
else:
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, \
httpPrefix: str,domain :str,port: int, \

View File

@ -40,7 +40,8 @@ def capabilitiesRequest(baseDir: str,httpPrefix: str,domain: str, \
}
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, \
acceptedCaps=["inbox:write","objects:read"]) -> {}:
# This gets returned to capabilities requester
@ -50,6 +51,10 @@ def capabilitiesAccept(baseDir: str,httpPrefix: str,nickname: str,domain: str, \
if len(acceptedActor)>256:
return None
fullDomain=domain
if port!=80 and port !=443:
fullDomain=domain+':'+str(port)
# make directories to store capabilities
capabilitiesMakeDirs(baseDir)
filename=baseDir+'/ocap/accept/'+acceptedActor.replace('/','#')+'.json'
@ -63,14 +68,14 @@ def capabilitiesAccept(baseDir: str,httpPrefix: str,nickname: str,domain: str, \
if not ocapAccept:
ocapId=createPassword(32)
ocapAccept = {
"id": httpPrefix+"://"+domain+"/caps/"+ocapId,
"id": httpPrefix+"://"+fullDomain+"/caps/"+ocapId,
"type": "Capability",
"capability": acceptedCaps,
"scope": acceptedActor,
"actor": httpPrefix+"://"+domain
"actor": httpPrefix+"://"+fullDomain
}
if nickname:
ocapAccept['actor']=httpPrefix+"://"+domain+'/users/'+nickname
ocapAccept['actor']=httpPrefix+"://"+fullDomain+'/users/'+nickname
if saveToFile:
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)
personUrl=messageJson['actor']
acceptJson=createAccept(baseDir,federationList,ocapGranted, \
nickname,domain,port, \
nicknameToFollow,domainToFollow,port, \
personUrl,'',httpPrefix,messageJson)
if debug:
pprint(acceptJson)
@ -311,8 +311,10 @@ def sendFollowRequest(session,baseDir: str, \
if not domainPermitted(followDomain,federationList):
return None
fullDomain=domain
followActor=httpPrefix+'://'+domain+'/users/'+nickname
if port!=80 and port!=443:
fullDomain=domain+':'+str(port)
followActor=httpPrefix+'://'+domain+':'+str(port)+'/users/'+nickname
requestDomain=followDomain
@ -329,7 +331,7 @@ def sendFollowRequest(session,baseDir: str, \
followedId=followHttpPrefix+'://'+requestDomain+'/users/'+followNickname
newFollowJson = {
'id': httpPrefix+'://'+domain+'/users/'+nickname+'/statuses/'+statusNumber,
'id': httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber,
'type': 'Follow',
'actor': followActor,
'object': followedId,