diff --git a/common.py b/common.py index 8b46046..8a0775e 100644 --- a/common.py +++ b/common.py @@ -111,7 +111,7 @@ def error(msg, status=400, exc_info=None, **kwargs): abort(status, response=make_response({'error': msg}, status), **kwargs) -def pretty_link(url, text=None, **kwargs): +def pretty_link(url, text=None, user=None, **kwargs): """Wrapper around :func:`oauth_dropins.webutil.util.pretty_link` that converts Mastodon user URLs to @-@ handles. Eg for URLs like https://mastodon.social/@foo and @@ -121,10 +121,11 @@ def pretty_link(url, text=None, **kwargs): Args: url (str) text (str) + user (models.User): current user kwargs: passed through to :func:`oauth_dropins.webutil.util.pretty_link` """ - if g.user and g.user.is_web_url(url): - return g.user.user_link() + if user and user.is_web_url(url): + return user.user_link() if text is None: match = re.match(r'https?://([^/]+)/(@|users/)([^/]+)$', url) diff --git a/flask_app.py b/flask_app.py index 62967f7..8f6c41c 100644 --- a/flask_app.py +++ b/flask_app.py @@ -37,15 +37,6 @@ if (appengine_info.LOCAL_SERVER flask_gae_static.init_app(app) -@app.before_request -def init_globals(): - """Set request globals. - - * g.user: current *actor* internal user we're operating on behalf of - """ - g.user = None - - # don't redirect API requests with blank path elements app.url_map.merge_slashes = False app.url_map.redirect_defaults = False diff --git a/models.py b/models.py index 0295585..75b94a2 100644 --- a/models.py +++ b/models.py @@ -816,23 +816,24 @@ class Object(StringIdModel): if self.as1 and other_as1 else bool(self.as1) != bool(other_as1)) - def actor_link(self, image=True, sized=False): + def actor_link(self, image=True, sized=False, user=None): """Returns a pretty HTML link with the actor's name and picture. Args: image (bool): whether to include an ``img`` tag with the actor's picture sized (bool): whether to set an explicit (``width=32``) size on the profile picture ``img` tag + user (User): current user Returns: str: """ attrs = {'class': 'h-card u-author'} - if (self.source_protocol in ('web', 'webmention', 'ui') and g.user - and (g.user.key in self.users or g.user.key.id() in self.domains)): + if (self.source_protocol in ('web', 'webmention', 'ui') + and (user.key in self.users or user.key.id() in self.domains)): # outbound; show a nice link to the user - return g.user.user_link() + return user.user_link() actor = None if self.as1: @@ -849,13 +850,13 @@ class Object(StringIdModel): if not actor: return '' elif set(actor.keys()) == {'id'}: - return common.pretty_link(actor['id'], attrs=attrs) + return common.pretty_link(actor['id'], attrs=attrs, user=user) url = as1.get_url(actor) name = actor.get('displayName') or actor.get('username') or '' img_url = util.get_url(actor, 'image') if not image or not img_url: - return common.pretty_link(url, text=name, attrs=attrs) + return common.pretty_link(url, text=name, attrs=attrs, user=user) return f"""\ @@ -1175,7 +1176,7 @@ def fetch_objects(query, by=None, user=None): content = '@' + fedi_url.group(2) if fedi_url.group(4): content += "'s post" - content = common.pretty_link(url, text=content) + content = common.pretty_link(url, text=content, user=user) obj.content = (obj_as1.get('content') or obj_as1.get('displayName') @@ -1184,8 +1185,8 @@ def fetch_objects(query, by=None, user=None): if type in ('like', 'follow', 'repost', 'share') or not obj.content: if obj.url: - obj.phrase = common.pretty_link(obj.url, text=obj.phrase, - attrs={'class': 'u-url'}) + obj.phrase = common.pretty_link( + obj.url, text=obj.phrase, attrs={'class': 'u-url'}, user=user) if content: obj.content = content obj.url = url diff --git a/pages.py b/pages.py index 766c2dd..caeab2d 100644 --- a/pages.py +++ b/pages.py @@ -212,7 +212,7 @@ def serve_feed(*, objects, format, user, title, as_snippets=False, quiet=False): activities = [{ 'objectType': 'note', 'id': obj.key.id(), - 'content': f'{obj.actor_link(image=False)} {obj.phrase} {obj.content}', + 'content': f'{obj.actor_link(image=False, user=user)} {obj.phrase} {obj.content}', 'content_is_html': True, 'updated': obj.updated.isoformat(), 'url': as1.get_url(obj.as1) or as1.get_url(as1.get_object(obj.as1)), diff --git a/templates/activities.html b/templates/activities.html index 6941dbe..136e592 100644 --- a/templates/activities.html +++ b/templates/activities.html @@ -4,7 +4,7 @@ {% for obj in objects %}
  • - {{ obj.actor_link()|safe }} + {{ obj.actor_link(user=user)|safe }} {{ obj.phrase|safe }} {{ obj.content|default('--', true)|striptags|truncate(50) }} diff --git a/tests/test_common.py b/tests/test_common.py index 6834f20..046d802 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -11,8 +11,6 @@ from web import Web class CommonTest(TestCase): - def setUp(self): - super().setUp() def test_pretty_link(self): for expected, url, text in ( @@ -26,15 +24,13 @@ class CommonTest(TestCase): self.assertIn(expected, common.pretty_link(url, text=text)) self.assertEqual('foo', - common.pretty_link('http://foo')) # current user's homepage gets converted to BF user page - g.user = Web(id='user.com') self.assert_multiline_equals("""\ - user.com""", common.pretty_link('https://user.com/')) + user.com""", common.pretty_link('https://user.com/', user=Web(id='user.com'))) def test_redirect_wrap_empty(self): self.assertIsNone(common.redirect_wrap(None)) diff --git a/tests/test_models.py b/tests/test_models.py index 5f96466..77d373e 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -468,8 +468,7 @@ class ObjectTest(TestCase): self.user = Fake(id='fake:user', obj=Object(id='a', as2={"name": "Alice"})) obj = Object(id='x', source_protocol='ui', users=[self.user.key]) - g.user = self.user - got = obj.actor_link() + got = obj.actor_link(user=self.user) self.assertIn('href="fake:user">', got) self.assertIn('Alice', got) diff --git a/tests/testutil.py b/tests/testutil.py index 952b0f1..67b2db8 100644 --- a/tests/testutil.py +++ b/tests/testutil.py @@ -170,7 +170,7 @@ from activitypub import ActivityPub, CONNEG_HEADERS_AS2_HTML from atproto import ATProto import common from web import Web -from flask_app import app, cache, init_globals +from flask_app import app, cache # used in TestCase.make_user() to reuse keys across Users since they're @@ -227,7 +227,6 @@ class TestCase(unittest.TestCase, testutil.Asserts): self.app_context = app.app_context() self.app_context.push() - init_globals() self.request_context = app.test_request_context('/') self.request_context.push()