diff --git a/acceptreject.py b/acceptreject.py index b3229992a..5105e3996 100644 --- a/acceptreject.py +++ b/acceptreject.py @@ -7,8 +7,6 @@ __email__ = "bob@freedombone.net" __status__ = "Production" import os -from capabilities import capabilitiesAccept -from capabilities import capabilitiesGrantedSave from utils import urlPermitted from utils import getDomainFromActor from utils import getNicknameFromActor @@ -19,7 +17,7 @@ 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) -> {}: + objectJson: {}, 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 @@ -48,9 +46,6 @@ def createAcceptReject(baseDir: str, federationList: [], if ccUrl: if len(ccUrl) > 0: newAccept['cc'] = [ccUrl] - # attach capabilities for follow accept - if ocapJson: - newAccept['capabilities'] = ocapJson return newAccept @@ -59,14 +54,10 @@ def createAccept(baseDir: str, federationList: [], 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') + objectJson, 'Accept') def createReject(baseDir: str, federationList: [], @@ -154,13 +145,6 @@ def acceptFollow(baseDir: str, domain: str, messageJson: {}, 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']) - # has this person already been unfollowed? unfollowedFilename = baseDir + '/accounts/' + \ nickname + '@' + acceptedDomainFull + '/unfollowed.txt' diff --git a/capabilities.py b/capabilities.py deleted file mode 100644 index f8ef2bb60..000000000 --- a/capabilities.py +++ /dev/null @@ -1,283 +0,0 @@ -__filename__ = "capabilities.py" -__author__ = "Bob Mottram" -__license__ = "AGPL3+" -__version__ = "1.1.0" -__maintainer__ = "Bob Mottram" -__email__ = "bob@freedombone.net" -__status__ = "Production" - -import os -from auth import createPassword -from utils import getNicknameFromActor -from utils import getDomainFromActor -from utils import loadJson -from utils import saveJson - - -def getOcapFilename(baseDir: str, - nickname: str, domain: str, - actor: str, subdir: str) -> str: - """Returns the filename for a particular capability accepted or granted - Also creates directories as needed - """ - if not actor: - return None - - if ':' in domain: - domain = domain.split(':')[0] - - if not os.path.isdir(baseDir + '/accounts'): - os.mkdir(baseDir + '/accounts') - - ocDir = baseDir + '/accounts/' + nickname + '@' + domain - if not os.path.isdir(ocDir): - os.mkdir(ocDir) - - ocDir = baseDir + '/accounts/' + nickname + '@' + domain + '/ocap' - if not os.path.isdir(ocDir): - os.mkdir(ocDir) - - ocDir = baseDir + '/accounts/' + \ - nickname + '@' + domain + '/ocap/' + subdir - if not os.path.isdir(ocDir): - os.mkdir(ocDir) - - return baseDir + '/accounts/' + \ - nickname + '@' + domain + '/ocap/' + \ - subdir + '/' + actor.replace('/', '#') + '.json' - - -def CapablePost(postJson: {}, capabilityList: [], debug: bool) -> bool: - """Determines whether a post arriving in the inbox - should be accepted accoring to the list of capabilities - """ - if postJson.get('type'): - # No announces/repeats - if postJson['type'] == 'Announce': - if 'inbox:noannounce' in capabilityList: - if debug: - print('DEBUG: ' + - 'inbox post rejected because inbox:noannounce') - return False - # No likes - if postJson['type'] == 'Like': - if 'inbox:nolike' in capabilityList: - if debug: - print('DEBUG: ' + - 'inbox post rejected because inbox:nolike') - return False - if postJson['type'] == 'Create': - if postJson.get('object'): - # Does this have a reply? - if postJson['object'].get('inReplyTo'): - if postJson['object']['inReplyTo']: - if 'inbox:noreply' in capabilityList: - if debug: - print('DEBUG: ' + - 'inbox post rejected because ' + - 'inbox:noreply') - return False - # are content warnings enforced? - if postJson['object'].get('sensitive'): - if not postJson['object']['sensitive']: - if 'inbox:cw' in capabilityList: - if debug: - print('DEBUG: ' + - 'inbox post rejected because inbox:cw') - return False - # content warning must have non-zero summary - if postJson['object'].get('summary'): - if len(postJson['object']['summary']) < 2: - if 'inbox:cw' in capabilityList: - if debug: - print('DEBUG: ' + - 'inbox post rejected because ' + - 'inbox:cw, summary missing') - return False - if 'inbox:write' in capabilityList: - return True - return True - - -def capabilitiesRequest(baseDir: str, httpPrefix: str, domain: str, - requestedActor: str, requestedDomain: str, - requestedCaps=["inbox:write", "objects:read"]) -> {}: - # This is sent to the capabilities endpoint /caps/new - # which could be instance wide or for a particular person - # This could also be added to a follow activity - ocapId = createPassword(32) - ocapRequest = { - "@context": "https://www.w3.org/ns/activitystreams", - "id": httpPrefix + "://" + requestedDomain + "/caps/request/" + ocapId, - "type": "Request", - "capability": requestedCaps, - "actor": requestedActor - } - return ocapRequest - - -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 - # This could also be added to a follow Accept activity - - # reject excessively long actors - if len(acceptedActor) > 256: - return None - - fullDomain = domain - if port: - if port != 80 and port != 443: - if ':' not in domain: - fullDomain = domain + ':' + str(port) - - # make directories to store capabilities - ocapFilename = \ - getOcapFilename(baseDir, nickname, fullDomain, acceptedActor, 'accept') - if not ocapFilename: - return None - ocapAccept = None - - # if the capability already exists then load it from file - if os.path.isfile(ocapFilename): - ocapAccept = loadJson(ocapFilename) - # otherwise create a new capability - if not ocapAccept: - acceptedActorNickname = getNicknameFromActor(acceptedActor) - if not acceptedActorNickname: - print('WARN: unable to find nickname in ' + acceptedActor) - return None - acceptedActorDomain, acceptedActorPort = \ - getDomainFromActor(acceptedActor) - if acceptedActorPort: - ocapId = acceptedActorNickname + '@' + acceptedActorDomain + \ - ':' + str(acceptedActorPort) + '#'+createPassword(32) - else: - ocapId = acceptedActorNickname + '@' + acceptedActorDomain + \ - '#' + createPassword(32) - ocapAccept = { - "@context": "https://www.w3.org/ns/activitystreams", - "id": httpPrefix + "://" + fullDomain + "/caps/" + ocapId, - "type": "Capability", - "capability": acceptedCaps, - "scope": acceptedActor, - "actor": httpPrefix + "://" + fullDomain - } - if nickname: - ocapAccept['actor'] = \ - httpPrefix + "://" + fullDomain + '/users/' + nickname - - if saveToFile: - saveJson(ocapAccept, ocapFilename) - return ocapAccept - - -def capabilitiesGrantedSave(baseDir: str, - nickname: str, domain: 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 - ocapFilename = \ - getOcapFilename(baseDir, nickname, domain, ocap['actor'], 'granted') - if not ocapFilename: - return False - saveJson(ocap, ocapFilename) - return True - - -def capabilitiesUpdate(baseDir: str, httpPrefix: str, - nickname: str, domain: str, port: int, - updateActor: str, - updateCaps: []) -> {}: - """Used to sends an update for a change of object capabilities - Note that the capability id gets changed with a new random token - so that the old capabilities can't continue to be used - """ - - # reject excessively long actors - if len(updateActor) > 256: - return None - - fullDomain = domain - if port: - if port != 80 and port != 443: - if ':' not in domain: - fullDomain = domain + ':' + str(port) - - # Get the filename of the capability - ocapFilename = \ - getOcapFilename(baseDir, nickname, fullDomain, updateActor, 'accept') - if not ocapFilename: - return None - - # The capability should already exist for it to be updated - if not os.path.isfile(ocapFilename): - return None - - # create an update activity - ocapUpdate = { - "@context": "https://www.w3.org/ns/activitystreams", - 'type': 'Update', - 'actor': httpPrefix + '://' + fullDomain + '/users/' + nickname, - 'to': [updateActor], - 'cc': [], - 'object': {} - } - - # read the existing capability - ocapJson = loadJson(ocapFilename) - - # set the new capabilities list. eg. ["inbox:write","objects:read"] - ocapJson['capability'] = updateCaps - - # change the id, so that the old capabilities can't continue to be used - updateActorNickname = getNicknameFromActor(updateActor) - if not updateActorNickname: - print('WARN: unable to find nickname in ' + updateActor) - return None - updateActorDomain, updateActorPort = getDomainFromActor(updateActor) - if updateActorPort: - ocapId = updateActorNickname + '@' + updateActorDomain + \ - ':' + str(updateActorPort) + '#' + createPassword(32) - else: - ocapId = updateActorNickname + '@' + updateActorDomain + \ - '#' + createPassword(32) - ocapJson['id'] = httpPrefix + "://" + fullDomain + "/caps/" + ocapId - ocapUpdate['object'] = ocapJson - - # save it again - saveJson(ocapJson, ocapFilename) - - return ocapUpdate - - -def capabilitiesReceiveUpdate(baseDir: str, - nickname: str, domain: str, port: int, - actor: str, - newCapabilitiesId: str, - capabilityList: [], debug: bool) -> bool: - """An update for a capability or the given actor has arrived - """ - ocapFilename = \ - getOcapFilename(baseDir, nickname, domain, actor, 'granted') - if not ocapFilename: - return False - - if not os.path.isfile(ocapFilename): - if debug: - print('DEBUG: capabilities file not found during update') - print(ocapFilename) - return False - - ocapJson = loadJson(ocapFilename) - - if ocapJson: - ocapJson['id'] = newCapabilitiesId - ocapJson['capability'] = capabilityList - - return saveJson(ocapJson, ocapFilename) - return False diff --git a/daemon.py b/daemon.py index 9bcd5e07f..135a00111 100644 --- a/daemon.py +++ b/daemon.py @@ -10299,7 +10299,6 @@ class PubServer(BaseHTTPRequestHandler): self.path.endswith('/inbox') or self.path.endswith('/shares') or self.path.endswith('/moderationaction') or - self.path.endswith('/caps/new') or self.path == '/sharedInbox'): print('Attempt to POST to invalid path ' + self.path) self._400() diff --git a/epicyon.py b/epicyon.py index 507e58ab4..ef8c569b3 100644 --- a/epicyon.py +++ b/epicyon.py @@ -230,26 +230,6 @@ parser.add_argument("--testsnetwork", type=str2bool, nargs='?', parser.add_argument("--testdata", type=str2bool, nargs='?', const=True, default=False, help="Generate some data for testing purposes") -parser.add_argument("--ocap", type=str2bool, nargs='?', - const=True, default=False, - help="Always strictly enforce object capabilities") -parser.add_argument("--noreply", type=str2bool, nargs='?', - const=True, default=False, - help="Default capabilities don't allow replies on posts") -parser.add_argument("--nolike", type=str2bool, nargs='?', - const=True, default=False, - help="Default capabilities don't allow " + - "likes/favourites on posts") -parser.add_argument("--nopics", type=str2bool, nargs='?', - const=True, default=False, - help="Default capabilities don't allow attached pictures") -parser.add_argument("--noannounce", "--norepeat", type=str2bool, nargs='?', - const=True, default=False, - help="Default capabilities don't allow announce/repeat") -parser.add_argument("--cw", type=str2bool, nargs='?', - const=True, default=False, - help="Default capabilities don't allow posts " + - "without content warnings") parser.add_argument('--icon', '--avatar', dest='avatar', type=str, default=None, help='Set the avatar filename for an account') @@ -1920,8 +1900,8 @@ if __name__ == "__main__": port, proxyPort, httpPrefix, federationList, args.maxMentions, args.maxEmoji, args.authenticatedFetch, - args.noreply, args.nolike, args.nopics, - args.noannounce, args.cw, ocapAlways, + False, False, False, + False, False, ocapAlways, proxyType, args.maxReplies, args.domainMaxPostsPerDay, args.accountMaxPostsPerDay, diff --git a/follow.py b/follow.py index f641e916e..5b00d81f1 100644 --- a/follow.py +++ b/follow.py @@ -1045,14 +1045,12 @@ def getFollowersOfActor(baseDir: str, actor: str, debug: bool) -> {}: """In a shared inbox if we receive a post we know who it's from and if it's addressed to followers then we need to get a list of those. This returns a list of account handles which follow the given actor - and also the corresponding capability id if it exists """ if debug: print('DEBUG: getting followers of ' + actor) recipientsDict = {} if ':' not in actor: return recipientsDict - httpPrefix = actor.split(':')[0] nickname = getNicknameFromActor(actor) if not nickname: if debug: @@ -1084,35 +1082,7 @@ def getFollowersOfActor(baseDir: str, actor: str, debug: bool) -> {}: if debug: print('DEBUG: ' + account + ' follows ' + actorHandle) - ocapFilename = baseDir + '/accounts/' + \ - account + '/ocap/accept/' + httpPrefix + \ - ':##' + domain + ':' + str(port) + \ - '#users#' + nickname + '.json' - if debug: - print('DEBUG: checking capabilities of' + account) - if os.path.isfile(ocapFilename): - ocapJson = loadJson(ocapFilename) - if ocapJson: - if ocapJson.get('id'): - if debug: - print('DEBUG: ' + - 'capabilities id found for ' + - account) - - recipientsDict[account] = ocapJson['id'] - else: - if debug: - print('DEBUG: ' + - 'capabilities has no ' + - 'id attribute') - recipientsDict[account] = None - else: - if debug: - print('DEBUG: ' + - 'No capabilities file found for ' + - account + ' granted by ' + actorHandle) - print(ocapFilename) - recipientsDict[account] = None + recipientsDict[account] = None return recipientsDict diff --git a/inbox.py b/inbox.py index e1b0c0b89..74ed927a4 100644 --- a/inbox.py +++ b/inbox.py @@ -40,9 +40,6 @@ from pprint import pprint from cache import getPersonFromCache from cache import storePersonInCache from acceptreject import receiveAcceptReject -from capabilities import getOcapFilename -from capabilities import CapablePost -from capabilities import capabilitiesReceiveUpdate from bookmarks import updateBookmarksCollection from bookmarks import undoBookmarksCollectionEntry from blocking import isBlocked @@ -437,81 +434,12 @@ def savePostToInboxQueue(baseDir: str, httpPrefix: str, return filename -def inboxCheckCapabilities(baseDir: str, nickname: str, domain: str, - actor: str, queueFilename: str, queue: [], - queueJson: {}, capabilityId: str, - debug: bool) -> bool: - if nickname == 'inbox': - return True - - ocapFilename = \ - getOcapFilename(baseDir, - queueJson['nickname'], queueJson['domain'], - actor, 'accept') - if not ocapFilename: - return False - if not os.path.isfile(ocapFilename): - if debug: - print('DEBUG: capabilities for ' + - actor + ' do not exist') - if os.path.isfile(queueFilename): - os.remove(queueFilename) - if len(queue) > 0: - queue.pop(0) - return False - - oc = loadJson(ocapFilename) - if not oc: - return False - - if not oc.get('id'): - if debug: - print('DEBUG: capabilities for ' + actor + ' do not contain an id') - if os.path.isfile(queueFilename): - os.remove(queueFilename) - if len(queue) > 0: - queue.pop(0) - return False - - if oc['id'] != capabilityId: - if debug: - print('DEBUG: capability id mismatch') - if os.path.isfile(queueFilename): - os.remove(queueFilename) - if len(queue) > 0: - queue.pop(0) - return False - - if not oc.get('capability'): - if debug: - print('DEBUG: missing capability list') - if os.path.isfile(queueFilename): - os.remove(queueFilename) - if len(queue) > 0: - queue.pop(0) - return False - - if not CapablePost(queueJson['post'], oc['capability'], debug): - if debug: - print('DEBUG: insufficient capabilities to write to inbox from ' + - actor) - if os.path.isfile(queueFilename): - os.remove(queueFilename) - if len(queue) > 0: - queue.pop(0) - return False - - if debug: - print('DEBUG: object capabilities check success') - return True - - def inboxPostRecipientsAdd(baseDir: str, httpPrefix: str, toList: [], recipientsDict: {}, domainMatch: str, domain: str, actor: str, debug: bool) -> bool: """Given a list of post recipients (toList) from 'to' or 'cc' parameters - populate a recipientsDict with the handle and capabilities id for each + populate a recipientsDict with the handle for each """ followerRecipients = False for recipient in toList: @@ -523,24 +451,7 @@ def inboxPostRecipientsAdd(baseDir: str, httpPrefix: str, toList: [], nickname = recipient.split(domainMatch)[1] handle = nickname+'@'+domain if os.path.isdir(baseDir + '/accounts/' + handle): - # are capabilities granted for this account to the - # sender (actor) of the post? - ocapFilename = \ - baseDir + '/accounts/' + handle + \ - '/ocap/accept/' + actor.replace('/', '#') + '.json' - if os.path.isfile(ocapFilename): - # read the granted capabilities and obtain the id - ocapJson = loadJson(ocapFilename) - if ocapJson: - if ocapJson.get('id'): - # append with the capabilities id - recipientsDict[handle] = ocapJson['id'] - else: - recipientsDict[handle] = None - else: - if debug: - print('DEBUG: ' + ocapFilename + ' not found') - recipientsDict[handle] = None + recipientsDict[handle] = None else: if debug: print('DEBUG: ' + baseDir + '/accounts/' + @@ -1005,24 +916,6 @@ def receiveUpdate(recentPostsCache: {}, session, baseDir: str, print('DEBUG: Profile update was received for ' + messageJson['object']['url']) return True - - if messageJson['object'].get('capability') and \ - messageJson['object'].get('scope'): - nickname = getNicknameFromActor(messageJson['object']['scope']) - if nickname: - domain, tempPort = \ - getDomainFromActor(messageJson['object']['scope']) - - if messageJson['object']['type'] == 'Capability': - capability = messageJson['object']['capability'] - if capabilitiesReceiveUpdate(baseDir, nickname, domain, port, - messageJson['actor'], - messageJson['object']['id'], - capability, - debug): - if debug: - print('DEBUG: An update was received') - return True return False @@ -2124,20 +2017,20 @@ def inboxUpdateIndex(boxname: str, baseDir: str, handle: str, return False -def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int, - session, keyId: str, handle: str, messageJson: {}, - baseDir: str, httpPrefix: str, sendThreads: [], - postLog: [], cachedWebfingers: {}, personCache: {}, - queue: [], domain: str, - onionDomain: str, i2pDomain: str, - port: int, proxyType: str, - federationList: [], ocapAlways: bool, debug: bool, - acceptedCaps: [], - queueFilename: str, destinationFilename: str, - maxReplies: int, allowDeletion: bool, - maxMentions: int, maxEmoji: int, translate: {}, - unitTest: bool, YTReplacementDomain: str) -> bool: - """ Anything which needs to be done after capabilities checks have passed +def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, + session, keyId: str, handle: str, messageJson: {}, + baseDir: str, httpPrefix: str, sendThreads: [], + postLog: [], cachedWebfingers: {}, personCache: {}, + queue: [], domain: str, + onionDomain: str, i2pDomain: str, + port: int, proxyType: str, + federationList: [], ocapAlways: bool, debug: bool, + acceptedCaps: [], + queueFilename: str, destinationFilename: str, + maxReplies: int, allowDeletion: bool, + maxMentions: int, maxEmoji: int, translate: {}, + unitTest: bool, YTReplacementDomain: str) -> bool: + """ Anything which needs to be done after initial checks have passed """ actor = keyId if '#' in actor: @@ -2247,7 +2140,7 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int, return False if debug: - print('DEBUG: object capabilities passed') + print('DEBUG: initial checks passed') print('copy queue file from ' + queueFilename + ' to ' + destinationFilename) @@ -2929,10 +2822,6 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int, # Copy any posts addressed to followers into the shared inbox # this avoid copying file multiple times to potentially many # individual inboxes - # This obviously bypasses object capabilities and so - # any checking will needs to be handled at the time when inbox - # GET happens on individual accounts. - # See posts.py/createBoxBase if len(recipientsDictFollowers) > 0: sharedInboxPostFilename = \ queueJson['destination'].replace(inboxHandle, inboxHandle) @@ -2943,61 +2832,26 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int, for handle, capsId in recipientsDict.items(): destination = \ queueJson['destination'].replace(inboxHandle, handle) - # check that capabilities are accepted - if queueJson['post'].get('capability'): - capabilityIdList = queueJson['post']['capability'] - # does the capability id list within the post - # contain the id of the recipient with this handle? - # Here the capability id begins with the handle, - # so this could also be matched separately, but it's - # probably not necessary - if capsId in capabilityIdList: - inboxAfterCapabilities(recentPostsCache, - maxRecentPosts, - session, keyId, handle, - queueJson['post'], - baseDir, httpPrefix, - sendThreads, postLog, - cachedWebfingers, - personCache, queue, - domain, - onionDomain, i2pDomain, - port, proxyType, - federationList, ocapAlways, - debug, acceptedCaps, - queueFilename, destination, - maxReplies, allowDeletion, - maxMentions, maxEmoji, - translate, unitTest, - YTReplacementDomain) - else: - print('Queue: object capabilities check has failed') - if debug: - pprint(queueJson['post']) - else: - if not ocapAlways: - inboxAfterCapabilities(recentPostsCache, - maxRecentPosts, - session, keyId, handle, - queueJson['post'], - baseDir, httpPrefix, - sendThreads, postLog, - cachedWebfingers, - personCache, queue, - domain, - onionDomain, i2pDomain, - port, proxyType, - federationList, ocapAlways, - debug, acceptedCaps, - queueFilename, destination, - maxReplies, allowDeletion, - maxMentions, maxEmoji, - translate, unitTest, - YTReplacementDomain) - if debug: - pprint(queueJson['post']) - print('No capability list within post') - print('ocapAlways: ' + str(ocapAlways)) + inboxAfterInitial(recentPostsCache, + maxRecentPosts, + session, keyId, handle, + queueJson['post'], + baseDir, httpPrefix, + sendThreads, postLog, + cachedWebfingers, + personCache, queue, + domain, + onionDomain, i2pDomain, + port, proxyType, + federationList, ocapAlways, + debug, acceptedCaps, + queueFilename, destination, + maxReplies, allowDeletion, + maxMentions, maxEmoji, + translate, unitTest, + YTReplacementDomain) + if debug: + pprint(queueJson['post']) print('Queue: Queue post accepted') if os.path.isfile(queueFilename): diff --git a/person.py b/person.py index 071f4beda..cbeca6652 100644 --- a/person.py +++ b/person.py @@ -259,7 +259,6 @@ def createPersonBase(baseDir: str, nickname: str, domain: str, port: int, 'id': personId+'/endpoints', 'sharedInbox': httpPrefix+'://'+domain+'/inbox', }, - 'capabilityAcquisitionEndpoint': httpPrefix+'://'+domain+'/caps/new', 'followers': personId+'/followers', 'following': personId+'/following', 'shares': personId+'/shares', @@ -506,15 +505,6 @@ def createSharedInbox(baseDir: str, nickname: str, domain: str, port: int, True, True, None) -def createCapabilitiesInbox(baseDir: str, nickname: str, - domain: str, port: int, - httpPrefix: str) -> (str, str, {}, {}): - """Generates the capabilities inbox to sign requests - """ - return createPersonBase(baseDir, nickname, domain, port, - httpPrefix, True, True, None) - - def personUpgradeActor(baseDir: str, personJson: {}, handle: str, filename: str) -> None: """Alter the actor to add any new properties diff --git a/posts.py b/posts.py index cffc4d8f6..37d806d50 100644 --- a/posts.py +++ b/posts.py @@ -45,8 +45,6 @@ from utils import validNickname from utils import locatePost from utils import loadJson from utils import saveJson -from capabilities import getOcapFilename -from capabilities import capabilitiesUpdate from media import attachMedia from media import replaceYouTube from content import removeHtml @@ -893,24 +891,12 @@ def createPostBase(baseDir: str, nickname: str, domain: str, port: int, if not clientToServer: actorUrl = httpPrefix + '://' + domain + '/users/' + nickname - # if capabilities have been granted for this actor - # then get the corresponding id - capabilityIdList = [] - ocapFilename = getOcapFilename(baseDir, nickname, domain, - toUrl, 'granted') - if ocapFilename: - if os.path.isfile(ocapFilename): - oc = loadJson(ocapFilename) - if oc: - if oc.get('id'): - capabilityIdList = [oc['id']] idStr = \ httpPrefix + '://' + domain + '/users/' + nickname + \ '/statuses/' + statusNumber + '/replies' newPost = { '@context': postContext, 'id': newPostId + '/activity', - 'capability': capabilityIdList, 'type': 'Create', 'actor': actorUrl, 'published': published, @@ -1674,20 +1660,13 @@ def sendPost(projectVersion: str, projectVersion, httpPrefix, nickname, domain, postToBox) - # If there are more than one followers on the target domain - # then send to the shared inbox indead of the individual inbox - if nickname == 'capabilities': - inboxUrl = capabilityAcquisition - if not capabilityAcquisition: - return 2 - if not inboxUrl: return 3 if not pubKey: return 4 if not toPersonId: return 5 - # sharedInbox and capabilities are optional + # sharedInbox is optional postJsonObject = \ createPostBase(baseDir, nickname, domain, port, @@ -2003,7 +1982,7 @@ def sendSignedJson(postJsonObject: {}, session, baseDir: str, else: postToBox = 'outbox' - # get the actor inbox/outbox/capabilities for the To handle + # get the actor inbox/outbox for the To handle (inboxUrl, pubKeyId, pubKey, toPersonId, sharedInboxUrl, capabilityAcquisition, avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest, @@ -2011,17 +1990,12 @@ def sendSignedJson(postJsonObject: {}, session, baseDir: str, projectVersion, httpPrefix, nickname, domain, postToBox) - if nickname == 'capabilities': - inboxUrl = capabilityAcquisition - if not capabilityAcquisition: - return 2 - else: - print("inboxUrl: " + str(inboxUrl)) - print("toPersonId: " + str(toPersonId)) - print("sharedInboxUrl: " + str(sharedInboxUrl)) - if inboxUrl: - if inboxUrl.endswith('/actor/inbox'): - inboxUrl = sharedInboxUrl + print("inboxUrl: " + str(inboxUrl)) + print("toPersonId: " + str(toPersonId)) + print("sharedInboxUrl: " + str(sharedInboxUrl)) + if inboxUrl: + if inboxUrl.endswith('/actor/inbox'): + inboxUrl = sharedInboxUrl if not inboxUrl: if debug: @@ -2039,7 +2013,7 @@ def sendSignedJson(postJsonObject: {}, session, baseDir: str, if debug: print('DEBUG: missing personId') return 5 - # sharedInbox and capabilities are optional + # sharedInbox is optional # get the senders private key privateKeyPem = getPersonKey(nickname, domain, baseDir, 'private', debug) @@ -2791,32 +2765,8 @@ def createSharedInboxIndex(baseDir: str, sharedBoxDir: str, if actorNickname + '@' + actorDomain not in followingHandles: continue - if ocapAlways: - capsList = None - # Note: should this be in the Create or the object of a post? - if postJsonObject.get('capability'): - if isinstance(postJsonObject['capability'], list): - capsList = postJsonObject['capability'] - - # Have capabilities been granted for the sender? - ocapFilename = \ - baseDir + '/accounts/' + handle + '/ocap/granted/' + \ - postJsonObject['actor'].replace('/', '#') + '.json' - if not os.path.isfile(ocapFilename): - continue - - # read the capabilities id - ocapJson = loadJson(ocapFilename, 0) - if not ocapJson: - print('WARN: json load exception createSharedInboxIndex') - else: - if ocapJson.get('id'): - if ocapJson['id'] in capsList: - postsInBoxDict[statusNumber] = sharedInboxFilename - postsCtr += 1 - else: - postsInBoxDict[statusNumber] = sharedInboxFilename - postsCtr += 1 + postsInBoxDict[statusNumber] = sharedInboxFilename + postsCtr += 1 return postsCtr @@ -3413,45 +3363,6 @@ def checkDomains(session, baseDir: str, print(followerWarningStr) -def sendCapabilitiesUpdate(session, baseDir: str, httpPrefix: str, - nickname: str, domain: str, port: int, - followerUrl, updateCaps: [], - sendThreads: [], postLog: [], - cachedWebfingers: {}, personCache: {}, - federationList: [], debug: bool, - projectVersion: str) -> int: - """When the capabilities for a follower are changed this - sends out an update. followerUrl is the actor of the follower. - """ - updateJson = \ - capabilitiesUpdate(baseDir, httpPrefix, - nickname, domain, port, - followerUrl, updateCaps) - - if not updateJson: - return 1 - - if debug: - pprint(updateJson) - print('DEBUG: sending capabilities update from ' + - nickname + '@' + domain + ' port ' + str(port) + - ' to ' + followerUrl) - - clientToServer = False - followerNickname = getNicknameFromActor(followerUrl) - if not followerNickname: - print('WARN: unable to find nickname in ' + followerUrl) - return 1 - followerDomain, followerPort = getDomainFromActor(followerUrl) - return sendSignedJson(updateJson, session, baseDir, - nickname, domain, port, - followerNickname, followerDomain, followerPort, '', - httpPrefix, True, clientToServer, - federationList, - sendThreads, postLog, cachedWebfingers, - personCache, debug, projectVersion) - - def populateRepliesJson(baseDir: str, nickname: str, domain: str, postRepliesFilename: str, authorized: bool, repliesJson: {}) -> None: diff --git a/session.py b/session.py index 26322bad7..9e3a14ec5 100644 --- a/session.py +++ b/session.py @@ -141,13 +141,6 @@ def postJsonString(session, postJsonStr: str, conversions between string and json format don't invalidate the message body digest of http signatures """ - # always allow capability requests - if not capability.startswith('cap'): - # check that we are posting to a permitted domain - if not urlPermitted(inboxUrl, federationList, capability): - print('postJson: ' + inboxUrl + ' not permitted by capabilities') - return None, None - try: postResult = \ session.post(url=inboxUrl, data=postJsonStr, headers=headers) diff --git a/utils.py b/utils.py index 014c5bc20..445ffc5ff 100644 --- a/utils.py +++ b/utils.py @@ -669,7 +669,7 @@ def validNickname(domain: str, nickname: str) -> bool: return False reservedNames = ('inbox', 'dm', 'outbox', 'following', 'public', 'followers', - 'channel', 'capabilities', 'calendar', + 'channel', 'calendar', 'tlreplies', 'tlmedia', 'tlblogs', 'tlevents', 'moderation', 'activity', 'undo',