From 8002f937a474f2ba9a16897c2ad1a1ba2aaed345 Mon Sep 17 00:00:00 2001 From: Misha Tomilov Date: Wed, 12 Feb 2025 13:01:39 +0100 Subject: [PATCH] Fix mention user url --- h/presenters/mention_json.py | 9 ++++++--- h/services/annotation_json.py | 9 ++++++++- h/services/mention.py | 5 +++-- h/util/user.py | 9 +++++++++ tests/unit/h/presenters/mention_json_test.py | 14 ++++++++----- tests/unit/h/services/annotation_json_test.py | 3 +++ tests/unit/h/util/user_test.py | 20 +++++++++++++++++++ 7 files changed, 58 insertions(+), 11 deletions(-) diff --git a/h/presenters/mention_json.py b/h/presenters/mention_json.py index b0098f37f53..492a9efa602 100644 --- a/h/presenters/mention_json.py +++ b/h/presenters/mention_json.py @@ -1,14 +1,17 @@ from typing import Any +from pyramid.request import Request + from h.models import Mention -from h.util.user import format_userid +from h.util.user import format_userid, get_user_url class MentionJSONPresenter: """Present a mention in the JSON format returned by API requests.""" - def __init__(self, mention: Mention): + def __init__(self, mention: Mention, request: Request): self._mention = mention + self._request = request def asdict(self) -> dict[str, Any]: return { @@ -18,5 +21,5 @@ def asdict(self) -> dict[str, Any]: ), "username": self._mention.user.username, "display_name": self._mention.user.display_name, - "link": self._mention.user.uri, + "link": get_user_url(self._mention.user, self._request), } diff --git a/h/services/annotation_json.py b/h/services/annotation_json.py index 4014f3fdde4..053a770b732 100644 --- a/h/services/annotation_json.py +++ b/h/services/annotation_json.py @@ -1,5 +1,7 @@ from copy import deepcopy +from pyramid.request import Request + from h.models import Annotation, User from h.presenters import DocumentJSONPresenter from h.presenters.mention_json import MentionJSONPresenter @@ -27,6 +29,7 @@ def __init__( # noqa: PLR0913 user_service: UserService, mention_service: MentionService, feature_service: FeatureService, + request: Request, ): """ Instantiate the service. @@ -36,6 +39,8 @@ def __init__( # noqa: PLR0913 :param flag_service: FlagService instance :param user_service: UserService instance :param mention_service: MentionService instance + :param feature_service: FeatureService instance + :param request: The current request """ self._annotation_read_service = annotation_read_service self._links_service = links_service @@ -43,6 +48,7 @@ def __init__( # noqa: PLR0913 self._user_service = user_service self._mention_service = mention_service self._feature_service = feature_service + self._request = request def present(self, annotation: Annotation): """ @@ -83,7 +89,7 @@ def present(self, annotation: Annotation): ) if self._feature_service.enabled("at_mentions"): # pragma: no cover model["mentions"] = [ - MentionJSONPresenter(mention).asdict() + MentionJSONPresenter(mention, self._request).asdict() for mention in annotation.mentions ] @@ -201,4 +207,5 @@ def factory(_context, request): user_service=request.find_service(name="user"), mention_service=request.find_service(MentionService), feature_service=request.find_service(name="feature"), + request=request, ) diff --git a/h/services/mention.py b/h/services/mention.py index e7a7abf7eba..5398cbc06cb 100644 --- a/h/services/mention.py +++ b/h/services/mention.py @@ -18,7 +18,7 @@ class MentionService: """A service for managing user mentions.""" - def __init__(self, session: Session, user_service: UserService): + def __init__(self, session: Session, user_service: UserService) -> None: self._session = session self._user_service = user_service @@ -75,5 +75,6 @@ def _parse_userids(text: str) -> list[str]: def factory(_context, request) -> MentionService: """Return a MentionService instance for the passed context and request.""" return MentionService( - session=request.db, user_service=request.find_service(name="user") + session=request.db, + user_service=request.find_service(name="user"), ) diff --git a/h/util/user.py b/h/util/user.py index 27df745608c..27552f45e62 100644 --- a/h/util/user.py +++ b/h/util/user.py @@ -2,6 +2,8 @@ import re +from pyramid.request import Request + from h.exceptions import InvalidUserId @@ -23,3 +25,10 @@ def split_user(userid): def format_userid(username, authority): return f"acct:{username}@{authority}" + + +def get_user_url(user, request: Request) -> str | None: + if user.authority == request.default_authority: + return request.route_url("activity.user_search", username=user.username) + + return None diff --git a/tests/unit/h/presenters/mention_json_test.py b/tests/unit/h/presenters/mention_json_test.py index b5251c9f914..8857c2f7ceb 100644 --- a/tests/unit/h/presenters/mention_json_test.py +++ b/tests/unit/h/presenters/mention_json_test.py @@ -6,24 +6,24 @@ class TestMentionJSONPresenter: - def test_as_dict(self, user, annotation): + def test_as_dict(self, user, annotation, pyramid_request): mention = Mention(annotation=annotation, user=user, username=user.username) - data = MentionJSONPresenter(mention).asdict() + data = MentionJSONPresenter(mention, pyramid_request).asdict() assert data == { "userid": user.userid, "original_userid": user.userid, "username": user.username, "display_name": user.display_name, - "link": user.uri, + "link": f"http://example.com/users/{user.username}", } - def test_as_dict_with_different_username(self, user, annotation): + def test_as_dict_with_different_username(self, user, annotation, pyramid_request): new_username = "new_username" mention = Mention(annotation=annotation, user=user, username=new_username) - data = MentionJSONPresenter(mention).asdict() + data = MentionJSONPresenter(mention, pyramid_request).asdict() assert data["original_userid"] == format_userid(new_username, user.authority) @@ -34,3 +34,7 @@ def user(self, factories): @pytest.fixture def annotation(self, factories): return factories.Annotation.build() + + @pytest.fixture(autouse=True) + def routes(self, pyramid_config): + pyramid_config.add_route("activity.user_search", "/users/{username}") diff --git a/tests/unit/h/services/annotation_json_test.py b/tests/unit/h/services/annotation_json_test.py index 6c66e7aec15..82e904a0cf6 100644 --- a/tests/unit/h/services/annotation_json_test.py +++ b/tests/unit/h/services/annotation_json_test.py @@ -214,6 +214,7 @@ def service( user_service, mention_service, feature_service, + pyramid_request, ): return AnnotationJSONService( annotation_read_service=annotation_read_service, @@ -222,6 +223,7 @@ def service( user_service=user_service, mention_service=mention_service, feature_service=feature_service, + request=pyramid_request, ) @pytest.fixture @@ -272,6 +274,7 @@ def test_it( user_service=user_service, mention_service=mention_service, feature_service=feature_service, + request=pyramid_request, ) assert service == AnnotationJSONService.return_value diff --git a/tests/unit/h/util/user_test.py b/tests/unit/h/util/user_test.py index 8e0402ffb84..2f37de10e58 100644 --- a/tests/unit/h/util/user_test.py +++ b/tests/unit/h/util/user_test.py @@ -12,3 +12,23 @@ def test_split_user(): def test_split_user_no_match(): with pytest.raises(InvalidUserId): user_util.split_user("donkeys") + + +class TestGetUserURL: + def test_it(self, pyramid_request, user): + assert ( + user_util.get_user_url(user, pyramid_request) + == f"http://example.com/users/{user.username}" + ) + + def test_it_returns_none_if_authority_does_not_match(self, pyramid_request, user): + pyramid_request.default_authority = "foo.org" + assert user_util.get_user_url(user, pyramid_request) is None + + @pytest.fixture + def user(self, factories): + return factories.User.build() + + @pytest.fixture(autouse=True) + def routes(self, pyramid_config): + pyramid_config.add_route("activity.user_search", "/users/{username}")