kopia lustrzana https://github.com/snarfed/bridgy-fed
				
				
				
			activitypub: implement HTTP Signatures using httpsig library
thanks @ahknight!pull/27/head
							rodzic
							
								
									2699de6903
								
							
						
					
					
						commit
						b123088158
					
				| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
bs4
 | 
					bs4
 | 
				
			||||||
feedparser
 | 
					feedparser
 | 
				
			||||||
granary>=1.8
 | 
					granary>=1.8
 | 
				
			||||||
 | 
					httpsig
 | 
				
			||||||
mf2py>=1.0.4
 | 
					mf2py>=1.0.4
 | 
				
			||||||
mf2util>=0.5.0
 | 
					mf2util>=0.5.0
 | 
				
			||||||
mock
 | 
					mock
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ import urllib2
 | 
				
			||||||
from django_salmon import magicsigs, utils
 | 
					from django_salmon import magicsigs, utils
 | 
				
			||||||
import feedparser
 | 
					import feedparser
 | 
				
			||||||
from granary import atom, microformats2
 | 
					from granary import atom, microformats2
 | 
				
			||||||
 | 
					from httpsig.sign import HeaderSigner
 | 
				
			||||||
import mf2py
 | 
					import mf2py
 | 
				
			||||||
import mock
 | 
					import mock
 | 
				
			||||||
from mock import call
 | 
					from mock import call
 | 
				
			||||||
| 
						 | 
					@ -105,9 +106,12 @@ class WebmentionTest(testutil.TestCase):
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        }, kwargs['json'])
 | 
					        }, kwargs['json'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        expected_headers = copy.copy(common.HEADERS)
 | 
					        headers = kwargs['headers']
 | 
				
			||||||
        expected_headers['Content-Type'] = activitypub.CONTENT_TYPE_AS
 | 
					        self.assertEqual(activitypub.CONTENT_TYPE_AS, headers['Content-Type'])
 | 
				
			||||||
        self.assertEqual(expected_headers, kwargs['headers'])
 | 
					
 | 
				
			||||||
 | 
					        expected_key = MagicKey.get_by_id('a')
 | 
				
			||||||
 | 
					        rsa_key = kwargs['auth'].header_signer._rsa._key
 | 
				
			||||||
 | 
					        self.assertEqual(expected_key.private_pem(), rsa_key.exportKey())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_salmon(self, mock_get, mock_post):
 | 
					    def test_salmon(self, mock_get, mock_post):
 | 
				
			||||||
        orig_atom = requests_response("""\
 | 
					        orig_atom = requests_response("""\
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@ TODO tests:
 | 
				
			||||||
* actor/attributedTo could be string URL
 | 
					* actor/attributedTo could be string URL
 | 
				
			||||||
* salmon rel via webfinger via author.name + domain
 | 
					* salmon rel via webfinger via author.name + domain
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					import datetime
 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
import urlparse
 | 
					import urlparse
 | 
				
			||||||
| 
						 | 
					@ -15,6 +16,7 @@ import django_salmon
 | 
				
			||||||
from django_salmon import magicsigs, utils
 | 
					from django_salmon import magicsigs, utils
 | 
				
			||||||
import feedparser
 | 
					import feedparser
 | 
				
			||||||
from granary import atom, microformats2
 | 
					from granary import atom, microformats2
 | 
				
			||||||
 | 
					from httpsig.requests_auth import HTTPSignatureAuth
 | 
				
			||||||
import mf2py
 | 
					import mf2py
 | 
				
			||||||
import mf2util
 | 
					import mf2util
 | 
				
			||||||
from oauth_dropins.webutil import util
 | 
					from oauth_dropins.webutil import util
 | 
				
			||||||
| 
						 | 
					@ -93,10 +95,27 @@ class WebmentionHandler(webapp2.RequestHandler):
 | 
				
			||||||
            source_obj['inReplyTo'],
 | 
					            source_obj['inReplyTo'],
 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # deliver source object to target actor's inbox
 | 
					        # prepare HTTP Signature (required by Mastodon)
 | 
				
			||||||
 | 
					        # https://w3c.github.io/activitypub/#authorization-lds
 | 
				
			||||||
 | 
					        # https://tools.ietf.org/html/draft-cavage-http-signatures-07
 | 
				
			||||||
 | 
					        # https://github.com/tootsuite/mastodon/issues/4906#issuecomment-328844846
 | 
				
			||||||
 | 
					        source_domain = urlparse.urlparse(source).netloc
 | 
				
			||||||
 | 
					        key = models.MagicKey.get_or_create(source_domain)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        acct = 'acct:me@%s' % source_domain
 | 
				
			||||||
 | 
					        auth = HTTPSignatureAuth(secret=key.private_pem(), key_id=acct,
 | 
				
			||||||
 | 
					                                 algorithm='rsa-sha256')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # deliver source object to target actor's inbox.
 | 
				
			||||||
 | 
					        headers = {
 | 
				
			||||||
 | 
					            'Content-Type': activitypub.CONTENT_TYPE_AS,
 | 
				
			||||||
 | 
					            # required for HTTP Signature
 | 
				
			||||||
 | 
					            # https://tools.ietf.org/html/draft-cavage-http-signatures-07#section-2.1.3
 | 
				
			||||||
 | 
					            'Date': datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        resp = common.requests_post(
 | 
					        resp = common.requests_post(
 | 
				
			||||||
            urlparse.urljoin(target, inbox_url), json=source_obj,
 | 
					            urlparse.urljoin(target, inbox_url), json=source_obj, auth=auth,
 | 
				
			||||||
            headers={'Content-Type': activitypub.CONTENT_TYPE_AS}, log=True)
 | 
					            headers=headers, log=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def send_salmon(self, source_obj, target_url=None, target_resp=None):
 | 
					    def send_salmon(self, source_obj, target_url=None, target_resp=None):
 | 
				
			||||||
        # fetch target HTML page, extract Atom rel-alternate link
 | 
					        # fetch target HTML page, extract Atom rel-alternate link
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Ładowanie…
	
		Reference in New Issue