From c502fe098236a509ad39ec2acb0454130c6bf724 Mon Sep 17 00:00:00 2001 From: Douglas Blank Date: Fri, 27 Jul 2018 18:09:58 -0400 Subject: [PATCH] refactored tornado so handler does it all --- LICENSE | 6 +++ activitypub/manager/ap_routes.py | 46 ++++++++++++++++++ activitypub/manager/tornadoman.py | 77 +++++++++++++++++++------------ 3 files changed, 99 insertions(+), 30 deletions(-) diff --git a/LICENSE b/LICENSE index a612ad9..6004944 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,9 @@ +This activitypub Python library is licensed under the MPL 2.0 (see +below). In addition, there may be other code licensed under slightly +different, but compatible, licenses. Each such compatible file will +contain its own license. + +================================== Mozilla Public License Version 2.0 ================================== diff --git a/activitypub/manager/ap_routes.py b/activitypub/manager/ap_routes.py index b3f8dd9..476ca2b 100644 --- a/activitypub/manager/ap_routes.py +++ b/activitypub/manager/ap_routes.py @@ -285,6 +285,52 @@ def route_webfinger(self): return self.error(404) """ +From: https://github.com/tootsuite/mastodon/blob/master/spec/fixtures/requests/activitypub-webfinger.txt + +HTTP/1.1 200 OK +Cache-Control: max-age=0, private, must-revalidate +Content-Type: application/jrd+json; charset=utf-8 +X-Content-Type-Options: nosniff +Date: Sun, 17 Sep 2017 06:22:50 GMT + +{"subject":"acct:foo@ap.example.com","aliases":["https://ap.example.com/@foo","https://ap.example.com/users/foo"],"links":[{"rel":"http://webfinger.net/rel/profile-page","type":"text/html","href":"https://ap.example.com/@foo"},{"rel":"http://schemas.google.com/g/2010#updates-from","type":"application/atom+xml","href":"https://ap.example.com/users/foo.atom"},{"rel":"self","type":"application/activity+json","href":"https://ap.example.com/users/foo"},{"rel":"salmon","href":"https://ap.example.com/api/salmon/1"},{"rel":"magic-public-key","href":"data:application/magic-public-key,RSA.u3L4vnpNLzVH31MeWI394F0wKeJFsLDAsNXGeOu0QF2x-h1zLWZw_agqD2R3JPU9_kaDJGPIV2Sn5zLyUA9S6swCCMOtn7BBR9g9sucgXJmUFB0tACH2QSgHywMAybGfmSb3LsEMNKsGJ9VsvYoh8lDET6X4Pyw-ZJU0_OLo_41q9w-OrGtlsTm_PuPIeXnxa6BLqnDaxC-4IcjG_FiPahNCTINl_1F_TgSSDZ4Taf4U9XFEIFw8wmgploELozzIzKq-t8nhQYkgAkt64euWpva3qL5KD1mTIZQEP-LZvh3s2WHrLi3fhbdRuwQ2c0KkJA2oSTFPDpqqbPGZ3QvuHQ==.AQAB"},{"rel":"http://ostatus.org/schema/1.0/subscribe","template":"https://ap.example.com/authorize_follow?acct={uri}"}]} + +From: https://mastodon.social/.well-known/webfinger?resource=acct:dsblank@mastodon.social + +{"subject": "acct:dsblank@mastodon.social", + "aliases": ["https://mastodon.social/@dsblank", + "https://mastodon.social/users/dsblank"], + "links": [ {"rel": "http://webfinger.net/rel/profile-page", + "type": "text/html", + "href": "https://mastodon.social/@dsblank"}, + {"rel": "http://schemas.google.com/g/2010#updates-from", + "type":"application/atom+xml", + "href":"https://mastodon.social/users/dsblank.atom"}, + {"rel":"self", + "type":"application/activity+json", + "href":"https://mastodon.social/users/dsblank"}, + {"rel":"salmon", + "href":"https://mastodon.social/api/salmon/368878"}, + {"rel":"magic-public-key", + "href":"data:application/magic-public-key,RSA.3L4-ufnddoOSl-YS6pel0q-tz01cjutYsl6sVM3QkJBX9T3Mp9MCarbbh5xEfttxIPCzZZAv1Yv_VRyOsexPi7CfF8z2pOjaZ-HD7KrwovhgiiL8YIwd_6o3qc5eCUibE56DyemUfqxWWNcvJH64D57cF0sMaZpx95DSQ5JKkcIq2M_M1Wm5AQZH5NIKnVyR55eOH7zN09mvZrK_S93b5DYaeBIjNwgtTBRDj4qqNtRtF5SM3_XmdWskA_KArP586W7CI4ZK538WbnT09JNA3d7TJQrwLXwkXJMX1nQARKQfyjbRbg2lXJcdHV_0pJqnJa9p24O0ysOtPN6LqL6v5w==.AQAB"}, + {"rel":"http://ostatus.org/schema/1.0/subscribe", + "template":"https://mastodon.social/authorize_follow?acct={uri}"} + ] +} + +From: https://a4.io/.well-known/webfinger?resource=acct:t@a4.io + +{"subject": "acct:t@a4.io", + "aliases": ["https://a4.io"], + "links": [{"rel": "http://webfinger.net/rel/profile-page", + "type": "text/html", "href": "https://a4.io"}, + {"rel": "self", "type": "application/activity+json", "href": "https://a4.io"}, + {"rel": "http://ostatus.org/schema/1.0/subscribe", "template": "https://a4.io/authorize_follow?profile={uri}"}, + {"rel": "magic-public-key", "href": "data:application/magic-public-key,RSA.zTYvKgiDIanj3XnpoGPdVmwq0A_FPqcoJXqMpNcIOVzWcOGK1WkxLeOnCcXhnxNnKpnXQIjU8MRz2y1tOfVEZHmII_hnOh2hcS3K5Sd_yHWnQkPgfnSBzn46mx3m8Nwi49qOZ0--ARGzVhOaBJhuUX2MvBrHl2A2GRjRtTnzACqFxB-ezZNGG6Ymvzv7CTCPXKUlygNqDy0Hi48SM_2LSmgotz5L0Vng3q33c9XeGR3YAiUlCevCDTyvIAkzN4hlP5zYezp_Bp7CkoY3teIvCaxZS5n92I_Oj2Xyq60v0MeXiqyXioGNPnUB8QtFV20kEhdwJik0_DubiRP_2Iy65w==.AQAB"}, + {"href": "https://sos-ch-dk-2.exo.io/hexaninja/hexaninja-alpha.png", "rel": "http://webfinger.net/rel/avatar", "type": "image/png"}] +} + +From https://willnorris.com/.well-known/webfinger?resource=acct:will@willnorris.com: { "subject": "acct:will@willnorris.com", diff --git a/activitypub/manager/tornadoman.py b/activitypub/manager/tornadoman.py index 4dc6d2e..cc53f1e 100644 --- a/activitypub/manager/tornadoman.py +++ b/activitypub/manager/tornadoman.py @@ -10,6 +10,10 @@ import re from .base import Manager, wrap_function, app from ..classes import ActivityPubBase +class Container(): + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + def make_handler(f, manager, methods, route, kws): """ Make a Tornado Handler @@ -25,14 +29,47 @@ def make_handler(f, manager, methods, route, kws): A handler that replicates some of the methods in Manager so that developers don't need to know. """ + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._filters = None + manager.template_env.filters.update(self.get_filters()) + + def get_template_namespace(self): + ns = super().get_template_namespace() + ns.update({ + 'config': 'John Doe', + }) + return ns + + def __getattr__(self, attr): + return getattr(manager, attr) + def get(self, *args, **kwargs): - self.database = manager.database - for name in ActivityPubBase.CLASSES: - setattr(self, name, getattr(manager, name)) return f(self, *args, **kwargs) + def get_filters(self): + if self._filters is None: + self._filters = {f.__name__: wrap_function(self, f) + for f in app.get_filters()} + return self._filters + + def _render_template(self, name, **kwargs): + tornado.log.logging.warning("kwargs: %s" % list(kwargs.keys())) + values = { + "request": Container(path=self.request.path, + args={k: self.get_argument(k) for k in self.request.arguments}), + "session": Container(logged_in=True), + "config": self.config, + } + for f in app.get_context_processors(): + values.update(f(self)) + values.update(kwargs) + template = manager.template_env.get_template(name) + tornado.log.logging.warning("values: %s" % list(values.keys())) + return template.render(**values) + def render_template(self, name, **kwargs): - self.write(manager.render_template(name, **kwargs)) + self.write(self._render_template(name, **kwargs)) def render_json(self, obj): self.write(obj) # will set header to JSON mimetype @@ -44,8 +81,13 @@ def make_handler(f, manager, methods, route, kws): def url_for(self, name): return manager.url_for(name) + #@property + #def request(self): + # return Request("/test", {k: self.get_argument(k) for k in self.request.arguments}) + # Get for free: # * get_argument + # * request return Handler @@ -56,35 +98,10 @@ class TornadoManager(Manager): self.template_env = jinja2.Environment( loader=jinja2.FileSystemLoader(self.get_template_folder())) - def get_filters(self): - if self._filters is None: - self._filters = {f.__name__: wrap_function(self, f) - for f in app._data.filters} - return self._filters - - def render_template(self, name, **kwargs): - values = {} - for f in app.get_context_processors(): - values.update(f(self)) - values.update(kwargs) - filters = self.get_filters() - tornado.log.logging.warning("%s" % list(filters.keys())) - self.template_env.filters.update(filters) - template = self.template_env.get_template(name) - return template.render(config=self.config, **values) - - ## TODO: move to app.Data - #def login_required(): - # tornado.web.authenticated - - @property - def request(self): - return request - def run(self): self.config["CSS"] = self.CSS routes = [] - for route, methods, f, kwargs in app._data.routes: + for route, methods, f, kwargs in app.get_routes(): re_route = re.sub("\<[^\>]*\>", r"([^/]*)", route) routes.append((re_route, make_handler(f, self, methods, route, kwargs))) self.app = Application(routes)