| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | __filename__ = "acceptreject.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							| 
									
										
										
										
											2019-08-29 13:35:29 +00:00
										 |  |  | __version__ = "1.0.0" | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@freedombone.net" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import json | 
					
						
							|  |  |  | import commentjson | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  | from capabilities import capabilitiesAccept | 
					
						
							|  |  |  | from capabilities import capabilitiesGrantedSave | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | from utils import getStatusNumber | 
					
						
							|  |  |  | from utils import createOutboxDir | 
					
						
							|  |  |  | from utils import urlPermitted | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  | from utils import getDomainFromActor | 
					
						
							|  |  |  | from utils import getNicknameFromActor | 
					
						
							|  |  |  | from utils import domainPermitted | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  | from utils import followPerson | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-09 14:20:23 +00:00
										 |  |  | def createAcceptReject(baseDir: str,federationList: [], \ | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |                        nickname: str,domain: str,port: int, \ | 
					
						
							|  |  |  |                        toUrl: str,ccUrl: str,httpPrefix: str, \ | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  |                        objectJson: {},ocapJson,acceptType: str) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |     """Accepts or rejects something (eg. a follow request or offer)
 | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |     Typically toUrl will be https://www.w3.org/ns/activitystreams#Public | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |     and ccUrl might be a specific person favorited or repeated and | 
					
						
							|  |  |  |     the followers url objectUrl is typically the url of the message, | 
					
						
							|  |  |  |     corresponding to url or atomUri in createPostBase | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if not objectJson.get('actor'): | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-09 14:20:23 +00:00
										 |  |  |     if not urlPermitted(objectJson['actor'],federationList,"inbox:write"): | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 20:35:11 +00:00
										 |  |  |     if port: | 
					
						
							|  |  |  |         if port!=80 and port!=443: | 
					
						
							|  |  |  |             if ':' not in domain: | 
					
						
							|  |  |  |                 domain=domain+':'+str(port) | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     newAccept = { | 
					
						
							| 
									
										
										
										
											2019-08-18 11:07:06 +00:00
										 |  |  |         "@context": "https://www.w3.org/ns/activitystreams", | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |         'type': acceptType, | 
					
						
							| 
									
										
										
										
											2019-07-03 19:00:03 +00:00
										 |  |  |         'actor': httpPrefix+'://'+domain+'/users/'+nickname, | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |         'to': [toUrl], | 
					
						
							|  |  |  |         'cc': [], | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |         'object': objectJson | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if ccUrl: | 
					
						
							|  |  |  |         if len(ccUrl)>0: | 
					
						
							| 
									
										
										
										
											2019-07-19 18:18:06 +00:00
										 |  |  |             newAccept['cc']=[ccUrl] | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  |     # attach capabilities for follow accept | 
					
						
							|  |  |  |     if ocapJson: | 
					
						
							|  |  |  |         newAccept['capabilities']=ocapJson | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  |     return newAccept | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-09 14:20:23 +00:00
										 |  |  | def createAccept(baseDir: str,federationList: [], \ | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |                  nickname: str,domain: str,port: int, \ | 
					
						
							|  |  |  |                  toUrl: str,ccUrl: str,httpPrefix: str, \ | 
					
						
							| 
									
										
										
										
											2019-07-09 17:54:08 +00:00
										 |  |  |                  objectJson: {},acceptedCaps=["inbox:write","objects:read"]) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  |     # create capabilities accept | 
					
						
							| 
									
										
										
										
											2019-07-09 17:54:08 +00:00
										 |  |  |     ocapNew=capabilitiesAccept(baseDir,httpPrefix,nickname,domain,port,toUrl,True,acceptedCaps) | 
					
						
							| 
									
										
										
										
											2019-07-09 14:20:23 +00:00
										 |  |  |     return createAcceptReject(baseDir,federationList, \ | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |                               nickname,domain,port, \ | 
					
						
							|  |  |  |                               toUrl,ccUrl,httpPrefix, \ | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  |                               objectJson,ocapNew,'Accept') | 
					
						
							| 
									
										
										
										
											2019-07-02 11:31:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-09 14:20:23 +00:00
										 |  |  | def createReject(baseDir: str,federationList: [], \ | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |                  nickname: str,domain: str,port: int, \ | 
					
						
							|  |  |  |                  toUrl: str,ccUrl: str,httpPrefix: str, \ | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |                  objectJson: {}) -> {}: | 
					
						
							| 
									
										
										
										
											2019-07-09 14:20:23 +00:00
										 |  |  |     return createAcceptReject(baseDir,federationList, \ | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |                               nickname,domain,port, \ | 
					
						
							|  |  |  |                               toUrl,ccUrl, \ | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  |                               httpPrefix,objectJson,None,'Reject') | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def acceptFollow(baseDir: str,domain : str,messageJson: {}, \ | 
					
						
							| 
									
										
										
										
											2019-07-09 14:20:23 +00:00
										 |  |  |                  federationList: [],debug : bool) -> None: | 
					
						
							| 
									
										
										
										
											2019-07-20 08:33:18 +00:00
										 |  |  |     """Receiving a follow Accept activity
 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if not messageJson.get('object'): | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     if not messageJson['object'].get('type'): | 
					
						
							|  |  |  |         return  | 
					
						
							|  |  |  |     if not messageJson['object'].get('actor'): | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     # no, this isn't a mistake | 
					
						
							|  |  |  |     if not messageJson['object'].get('object'): | 
					
						
							|  |  |  |         return  | 
					
						
							|  |  |  |     if not messageJson['object']['type']=='Follow': | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2019-07-07 13:53:12 +00:00
										 |  |  |     if not messageJson.get('to'): | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: No "to" parameter in follow Accept') | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2019-08-18 09:39:12 +00:00
										 |  |  |     #if len(messageJson['object']['to'])!=1: | 
					
						
							|  |  |  |     #    if debug: | 
					
						
							|  |  |  |     #        print('DEBUG: "to" does not contain a single recipient') | 
					
						
							|  |  |  |     #        print(str(messageJson['object']['to'])) | 
					
						
							|  |  |  |     #    if messageJson['object'].get('object'): | 
					
						
							|  |  |  |     #        if not isinstance(messageJson['object']['object'], str): | 
					
						
							|  |  |  |     #            messageJson['object']['to']=messageJson['object']['object'] | 
					
						
							|  |  |  |     #        else: | 
					
						
							|  |  |  |     #            return | 
					
						
							|  |  |  |     #    else: | 
					
						
							|  |  |  |     #        return         | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: follow Accept received') | 
					
						
							|  |  |  |     thisActor=messageJson['object']['actor'] | 
					
						
							|  |  |  |     nickname=getNicknameFromActor(thisActor) | 
					
						
							|  |  |  |     acceptedDomain,acceptedPort=getDomainFromActor(thisActor) | 
					
						
							|  |  |  |     if not acceptedDomain: | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: domain not found in '+thisActor) | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2019-07-07 13:53:12 +00:00
										 |  |  |     #if acceptedDomain != domain: | 
					
						
							|  |  |  |     #    if debug: | 
					
						
							|  |  |  |     #        print('DEBUG: domain mismatch '+acceptedDomain+' != '+domain) | 
					
						
							|  |  |  |     #    return | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     if not nickname: | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: nickname not found in '+thisActor)         | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     if acceptedPort: | 
					
						
							| 
									
										
										
										
											2019-07-07 13:53:12 +00:00
										 |  |  |         if not '/'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname in thisActor: | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |             if debug: | 
					
						
							| 
									
										
										
										
											2019-07-07 13:53:12 +00:00
										 |  |  |                 print('Port: '+str(acceptedPort)) | 
					
						
							|  |  |  |                 print('Expected: /'+acceptedDomain+':'+str(acceptedPort)+'/users/'+nickname) | 
					
						
							|  |  |  |                 print('Actual:   '+thisActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |                 print('DEBUG: unrecognized actor '+thisActor) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |     else: | 
					
						
							| 
									
										
										
										
											2019-07-07 13:53:12 +00:00
										 |  |  |         if not '/'+acceptedDomain+'/users/'+nickname in thisActor: | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |             if debug: | 
					
						
							| 
									
										
										
										
											2019-07-07 13:53:12 +00:00
										 |  |  |                 print('Expected: /'+acceptedDomain+'/users/'+nickname) | 
					
						
							|  |  |  |                 print('Actual:   '+thisActor) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |                 print('DEBUG: unrecognized actor '+thisActor) | 
					
						
							|  |  |  |             return     | 
					
						
							|  |  |  |     followedActor=messageJson['object']['object'] | 
					
						
							|  |  |  |     followedDomain,port=getDomainFromActor(followedActor) | 
					
						
							|  |  |  |     if not followedDomain: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     followedDomainFull=followedDomain | 
					
						
							|  |  |  |     if port: | 
					
						
							|  |  |  |         followedDomainFull=followedDomain+':'+str(port) | 
					
						
							|  |  |  |     followedNickname=getNicknameFromActor(followedActor) | 
					
						
							|  |  |  |     if not followedNickname: | 
					
						
							|  |  |  |         return | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 22:57:45 +00:00
										 |  |  |     acceptedDomainFull=acceptedDomain | 
					
						
							|  |  |  |     if acceptedPort: | 
					
						
							|  |  |  |         acceptedDomainFull=acceptedDomain+':'+str(acceptedPort) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  |     # are capabilities attached? If so then store them | 
					
						
							| 
									
										
										
										
											2019-07-07 16:06:38 +00:00
										 |  |  |     if messageJson.get('capabilities'): | 
					
						
							|  |  |  |         if isinstance(messageJson['capabilities'], dict): | 
					
						
							| 
									
										
										
										
											2019-07-07 15:51:04 +00:00
										 |  |  |             capabilitiesGrantedSave(baseDir, \ | 
					
						
							| 
									
										
										
										
											2019-07-07 16:06:38 +00:00
										 |  |  |                                     nickname,acceptedDomainFull, \ | 
					
						
							|  |  |  |                                     messageJson['capabilities']) | 
					
						
							| 
									
										
										
										
											2019-07-07 11:53:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-07 13:53:12 +00:00
										 |  |  |     if followPerson(baseDir, \ | 
					
						
							| 
									
										
										
										
											2019-07-16 22:57:45 +00:00
										 |  |  |                     nickname,acceptedDomainFull, \ | 
					
						
							|  |  |  |                     followedNickname,followedDomainFull, \ | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |                     federationList,debug): | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2019-07-16 22:57:45 +00:00
										 |  |  |             print('DEBUG: '+nickname+'@'+acceptedDomainFull+' followed '+followedNickname+'@'+followedDomainFull) | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         if debug: | 
					
						
							| 
									
										
										
										
											2019-07-07 13:53:12 +00:00
										 |  |  |             print('DEBUG: Unable to create follow - '+nickname+'@'+acceptedDomain+' -> '+followedNickname+'@'+followedDomain) | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-06 19:24:52 +00:00
										 |  |  | def receiveAcceptReject(session,baseDir: str, \ | 
					
						
							|  |  |  |                         httpPrefix: str,domain :str,port: int, \ | 
					
						
							| 
									
										
										
										
											2019-07-06 17:00:22 +00:00
										 |  |  |                         sendThreads: [],postLog: [],cachedWebfingers: {}, \ | 
					
						
							|  |  |  |                         personCache: {},messageJson: {},federationList: [], \ | 
					
						
							| 
									
										
										
										
											2019-07-09 14:20:23 +00:00
										 |  |  |                         debug : bool) -> bool: | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |     """Receives an Accept or Reject within the POST section of HTTPServer
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if messageJson['type']!='Accept' and messageJson['type']!='Reject': | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     if not messageJson.get('actor'): | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: '+messageJson['type']+' has no actor') | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     if '/users/' not in messageJson['actor']: | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: "users" missing from actor in '+messageJson['type']) | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     domain,tempPort=getDomainFromActor(messageJson['actor']) | 
					
						
							|  |  |  |     if not domainPermitted(domain,federationList): | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: '+messageJson['type']+' from domain not permitted - '+domain) | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     nickname=getNicknameFromActor(messageJson['actor']) | 
					
						
							|  |  |  |     if not nickname: | 
					
						
							|  |  |  |         if debug: | 
					
						
							|  |  |  |             print('DEBUG: '+messageJson['type']+' does not contain a nickname') | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  |     handle=nickname.lower()+'@'+domain.lower() | 
					
						
							| 
									
										
										
										
											2019-07-20 08:33:18 +00:00
										 |  |  |     # receive follow accept | 
					
						
							| 
									
										
										
										
											2019-07-09 14:20:23 +00:00
										 |  |  |     acceptFollow(baseDir,domain,messageJson,federationList,debug) | 
					
						
							| 
									
										
										
										
											2019-07-06 15:17:21 +00:00
										 |  |  |     if debug: | 
					
						
							|  |  |  |         print('DEBUG: Uh, '+messageJson['type']+', I guess') | 
					
						
							|  |  |  |     return True |