From 03315891aa9ad4b1c5afa58a26066f301e47516c Mon Sep 17 00:00:00 2001 From: Ryan Barrett Date: Sat, 25 Nov 2023 20:23:19 -0800 Subject: [PATCH] drop a lot of g.user for #690 --- activitypub.py | 30 +++++++++++++++++------------- atproto.py | 6 ------ follow.py | 2 -- protocol.py | 22 +++------------------- redirect.py | 4 ++-- tests/test_activitypub.py | 5 ----- 6 files changed, 22 insertions(+), 47 deletions(-) diff --git a/activitypub.py b/activitypub.py index 070e14b..b1ee8f6 100644 --- a/activitypub.py +++ b/activitypub.py @@ -358,7 +358,9 @@ class ActivityPub(User, Protocol): converted['object'] = postprocess_as2_actor(converted['object'], user=from_user) - return postprocess_as2(converted, orig_obj=orig_obj) + return postprocess_as2(converted, orig_obj=orig_obj, + # TODO: remove + from_user=from_user) @classmethod def verify_signature(cls, activity): @@ -469,14 +471,12 @@ def signed_post(url, from_user, **kwargs): def signed_request(fn, url, data=None, headers=None, from_user=None, **kwargs): """Wraps ``requests.*`` and adds HTTP Signature. - If the current session has a user (ie in ``g.user``), signs with that user's - key. Otherwise, uses the default user snarfed.org. - Args: fn (callable): :func:`util.requests_get` or :func:`util.requests_post` url (str): data (dict): optional AS2 object - from_user (models.User): user to sign request as; optional + from_user (models.User): user to sign request as; optional. If not + provided, uses the default user ``@snarfed.org@snarfed.org``. kwargs: passed through to requests Returns: @@ -539,7 +539,9 @@ def signed_request(fn, url, data=None, headers=None, from_user=None, **kwargs): return resp -def postprocess_as2(activity, orig_obj=None, wrap=True): +def postprocess_as2(activity, orig_obj=None, wrap=True, + # TODO: remove + from_user=None): """Prepare an AS2 object to be served or sent via ActivityPub. Args: @@ -596,8 +598,8 @@ def postprocess_as2(activity, orig_obj=None, wrap=True): obj['id'] = util.get_first(obj, 'url') or orig_id # for Accepts - if g.user and g.user.is_web_url(as1.get_object(obj).get('id')): - obj['object'] = g.user.ap_actor() + if from_user and from_user.is_web_url(as1.get_object(obj).get('id')): + obj['object'] = from_user.ap_actor() # id is required for most things. default to url if it's not set. if not activity.get('id'): @@ -675,7 +677,9 @@ def postprocess_as2(activity, orig_obj=None, wrap=True): activity['object'] = [ postprocess_as2(o, orig_obj=orig_obj, - wrap=wrap and type in ('Create', 'Update', 'Delete')) + wrap=wrap and type in ('Create', 'Update', 'Delete'), + # TODO: remove + from_user=from_user) for o in as1.get_objects(activity)] if len(activity['object']) == 1: activity['object'] = activity['object'][0] @@ -950,16 +954,16 @@ def outbox(id): if not protocol: error(f"Couldn't determine protocol", status=404) - g.user = protocol.get_by_id(id) - if not g.user: + user = protocol.get_by_id(id) + if not user: error(f'User {id} not found', status=404) if request.method == 'HEAD': return '', {'Content-Type': as2.CONTENT_TYPE} - query = Object.query(Object.users == g.user.key) + query = Object.query(Object.users == user.key) objects, new_before, new_after = fetch_objects(query, by=Object.updated, - user=g.user) + user=user) # page page = { diff --git a/atproto.py b/atproto.py index 76e8bbf..c67bd2c 100644 --- a/atproto.py +++ b/atproto.py @@ -470,9 +470,6 @@ def poll_notifications(): common.create_task(queue='receive', obj=obj.key.urlsafe(), authed_as=notif['author']['did']) - # note that we don't pass a user param above. it's the acting user, - # which is different for every notif, and may not actually have a BF - # User yet. return 'OK' @@ -529,8 +526,5 @@ def poll_posts(): obj.put() common.create_task(queue='receive', obj=obj.key.urlsafe(), authed_as=did) - # note that we don't pass a user param above. it's the acting user, - # which is different for every notif, and may not actually have a BF - # User yet. return 'OK' diff --git a/follow.py b/follow.py index 5b0921d..ee787ef 100644 --- a/follow.py +++ b/follow.py @@ -130,7 +130,6 @@ class FollowCallback(indieauth.Callback): follow_obj = Object(id=follow_id, users=[user.key, followee_user.key], labels=['user'], source_protocol='ui', status='complete', as2=follow_as2) - g.user = user ActivityPub.send(follow_obj, inbox, from_user=user) Follower.get_or_create(from_=user, to=followee_user, status='active', @@ -218,7 +217,6 @@ class UnfollowCallback(indieauth.Callback): # network etiquette.) obj = Object(id=unfollow_id, users=[user.key], labels=['user'], source_protocol='ui', status='complete', as2=unfollow_as2) - g.user = user ActivityPub.send(obj, inbox, from_user=user) follower.status = 'inactive' diff --git a/protocol.py b/protocol.py index 991d645..36bc331 100644 --- a/protocol.py +++ b/protocol.py @@ -600,8 +600,6 @@ class Protocol: from_user = from_cls.get_or_create(id=actor) if from_user.status == 'opt-out': error(r'Actor {actor} is opted out', status=204) - if not g.user: - g.user = from_user # update copy ids to originals obj.resolve_ids() @@ -811,14 +809,7 @@ class Protocol: 'object': obj.as1, }) - # TODO: ugly, brittle. dangerous. remove once postprocess_as2 no - # longer depends on g.user! - # https://github.com/snarfed/bridgy-fed/issues/690 - orig_g_user = g.user - g.user = to_user sent = from_cls.send(accept, from_target, from_user=to_user) - g.user = orig_g_user - if sent: accept.populate( delivered=[Target(protocol=from_cls.LABEL, uri=from_target)], @@ -1165,16 +1156,13 @@ def receive_task(): Parameters: obj (url-safe google.cloud.ndb.key.Key): :class:`models.Object` to handle - user (url-safe google.cloud.ndb.key.Key): :class:`models.User` this - activity is on behalf of. This user will be loaded into ``g.user`` authed_as (str): passed to :meth:`Protocol.receive` TODO: migrate incoming webmentions and AP inbox deliveries to this. The difficulty is that parts of :meth:`protocol.Protocol.receive` depend on setup in :func:`web.webmention` and :func:`activitypub.inbox`, eg - :class:`models.Object` with ``new`` and ``changed``, ``g.user`` (which - :meth:`Protocol.receive` now loads), HTTP request details, etc. See stash - for attempt at this for :class:`web.Web`. + :class:`models.Object` with ``new`` and ``changed``, HTTP request details, + etc. See stash for attempt at this for :class:`web.Web`. """ form = request.form.to_dict() logger.info(f'Params: {list(form.items())}') @@ -1183,10 +1171,6 @@ def receive_task(): assert obj obj.new = True - if user_key := form.get('user'): - g.user = ndb.Key(urlsafe=user_key).get() - logger.info(f'setting g.user to {g.user.key}') - authed_as = form.get('authed_as') try: @@ -1231,7 +1215,7 @@ def send_task(): user = None if user_key := form.get('user'): - g.user = user = ndb.Key(urlsafe=user_key).get() + user = ndb.Key(urlsafe=user_key).get() orig_obj = (ndb.Key(urlsafe=form['orig_obj']).get() if form.get('orig_obj') else None) diff --git a/redirect.py b/redirect.py index 77cef7a..2ce971d 100644 --- a/redirect.py +++ b/redirect.py @@ -100,8 +100,8 @@ def redir(to): if not obj or obj.deleted: return f'Object not found: {to}', 404 - g.user = Web.get_or_create(util.domain_from_link(to), direct=False, obj=obj) - ret = ActivityPub.convert(obj, from_user=g.user) + user = Web.get_or_create(util.domain_from_link(to), direct=False, obj=obj) + ret = ActivityPub.convert(obj, from_user=user) logger.info(f'Returning: {json_dumps(ret, indent=2)}') return ret, { 'Content-Type': accept_type, diff --git a/tests/test_activitypub.py b/tests/test_activitypub.py index 73c52a5..12d00bf 100644 --- a/tests/test_activitypub.py +++ b/tests/test_activitypub.py @@ -1834,7 +1834,6 @@ class ActivityPubUtilsTest(TestCase): # preferredUsername stays y.z despite user's username. since Mastodon # queries Webfinger for preferredUsername@fed.brid.gy # https://github.com/snarfed/bridgy-fed/issues/77#issuecomment-949955109 - g.user = self.user self.assertEqual('user.com', postprocess_as2_actor({ 'type': 'Person', 'url': 'https://user.com/about-me', @@ -2008,7 +2007,6 @@ class ActivityPubUtilsTest(TestCase): 'actor': 'fake:user', 'object': 'https://mas.to/thing', } - g.user = self.user self.assertEqual({ '@context': 'https://www.w3.org/ns/activitystreams', 'id': 'https://fa.brid.gy/convert/ap/fake:like', @@ -2031,8 +2029,6 @@ class ActivityPubUtilsTest(TestCase): }, ActivityPub.convert(obj), ignore=['to']) def test_postprocess_as2_idempotent(self): - g.user = self.user - for obj in (ACTOR, REPLY_OBJECT, REPLY_OBJECT_WRAPPED, REPLY, NOTE_OBJECT, NOTE, MENTION_OBJECT, MENTION, LIKE, LIKE_WRAPPED, REPOST, FOLLOW, FOLLOW_WRAPPED, ACCEPT, @@ -2156,7 +2152,6 @@ class ActivityPubUtilsTest(TestCase): 'author': 'http://the/author', }) # test is that we short circuit out instead of infinite recursion - g.user = self.user self.assertIsNone(ActivityPub.target_for(obj)) @patch('requests.post')