Skip to content

Commit

Permalink
Fix mention user url
Browse files Browse the repository at this point in the history
  • Loading branch information
mtomilov committed Feb 12, 2025
1 parent 89c82e5 commit f05b8db
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 22 deletions.
12 changes: 3 additions & 9 deletions h/emails/reply_notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from h.notification.reply import Notification
from h.services import SubscriptionService
from h.services.email import EmailTag
from h.util.user import get_user_url


def generate(request: Request, notification: Notification):
Expand All @@ -28,7 +29,7 @@ def generate(request: Request, notification: Notification):
"parent": notification.parent,
"parent_user_display_name": notification.parent_user.display_name
or notification.parent_user.username,
"parent_user_url": _get_user_url(notification.parent_user, request),
"parent_user_url": get_user_url(notification.parent_user, request),
"unsubscribe_url": request.route_url(
"unsubscribe",
token=unsubscribe_token,
Expand All @@ -39,7 +40,7 @@ def generate(request: Request, notification: Notification):
or request.route_url("annotation", id=notification.reply.id),
"reply_user_display_name": notification.reply_user.display_name
or notification.reply_user.username,
"reply_user_url": _get_user_url(notification.reply_user, request),
"reply_user_url": get_user_url(notification.reply_user, request),
}

subject = f"{context['reply_user_display_name']} has replied to your annotation"
Expand All @@ -57,10 +58,3 @@ def generate(request: Request, notification: Notification):
EmailTag.REPLY_NOTIFICATION,
html,
)


def _get_user_url(user, request):
if user.authority == request.default_authority:
return request.route_url("stream.user_query", user=user.username)

return None
9 changes: 6 additions & 3 deletions h/presenters/mention_json.py
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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),
}
3 changes: 2 additions & 1 deletion h/services/annotation_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__( # noqa: PLR0913
:param flag_service: FlagService instance
:param user_service: UserService instance
:param mention_service: MentionService instance
:param feature_service: FeatureService instance
"""
self._annotation_read_service = annotation_read_service
self._links_service = links_service
Expand Down Expand Up @@ -83,7 +84,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
]

Expand Down
10 changes: 8 additions & 2 deletions h/services/mention.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
from collections import OrderedDict

from pyramid.request import Request
from sqlalchemy import delete
from sqlalchemy.orm import Session

Expand All @@ -18,9 +19,12 @@
class MentionService:
"""A service for managing user mentions."""

def __init__(self, session: Session, user_service: UserService):
def __init__(
self, session: Session, user_service: UserService, request: Request
) -> None:
self._session = session
self._user_service = user_service
self._request = request

def update_mentions(self, annotation: Annotation) -> None:
self._session.flush()
Expand Down Expand Up @@ -75,5 +79,7 @@ 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"),
request=request,
)
9 changes: 9 additions & 0 deletions h/util/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import re

from pyramid.request import Request

from h.exceptions import InvalidUserId


Expand All @@ -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("stream.user_query", user=user.username)

return None
14 changes: 9 additions & 5 deletions tests/unit/h/presenters/mention_json_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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("stream.user_query", "/users/{user}")
3 changes: 3 additions & 0 deletions tests/unit/h/services/annotation_json_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ def service(
user_service,
mention_service,
feature_service,
pyramid_request,
):
return AnnotationJSONService(
annotation_read_service=annotation_read_service,
Expand All @@ -222,6 +223,7 @@ def service(
user_service=user_service,
mention_service=mention_service,
feature_service=feature_service,
request=pyramid_request,
)

@pytest.fixture
Expand Down Expand Up @@ -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

Expand Down
5 changes: 3 additions & 2 deletions tests/unit/h/services/mention_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ def user_service(self, user_service, annotation_slim, mentioned_user):
return user_service

@pytest.fixture
def service(self, db_session, user_service):
return MentionService(db_session, user_service)
def service(self, db_session, user_service, pyramid_request):
return MentionService(db_session, user_service, pyramid_request)


class TestFactory:
Expand All @@ -103,6 +103,7 @@ def test_it(self, pyramid_request, user_service, MentionService):
MentionService.assert_called_once_with(
session=pyramid_request.db,
user_service=user_service,
request=pyramid_request,
)

assert service == MentionService.return_value
Expand Down
16 changes: 16 additions & 0 deletions tests/unit/h/util/user_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,19 @@ def test_split_user():
def test_split_user_no_match():
with pytest.raises(InvalidUserId):
user_util.split_user("donkeys")


class TestGetUser:
def test_it(self, pyramid_request, user):
assert (
user_util.get_user_url(user, pyramid_request)
== f"http://example.com/users/{user.username}"
)

@pytest.fixture
def user(self, factories):
return factories.User.build()

@pytest.fixture(autouse=True)
def routes(self, pyramid_config):
pyramid_config.add_route("stream.user_query", "/users/{user}")

0 comments on commit f05b8db

Please sign in to comment.