Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Improve ServerNoticeServlet to avoid duplicate requests #10679

Merged
merged 4 commits into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/10679.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve ServerNoticeServlet to avoid duplicate requests and add unit tests.
17 changes: 11 additions & 6 deletions synapse/rest/admin/server_notice_servlet.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from typing import TYPE_CHECKING, Optional, Tuple

from synapse.api.constants import EventTypes
from synapse.api.errors import SynapseError
from synapse.api.errors import NotFoundError, SynapseError
from synapse.http.server import HttpServer
from synapse.http.servlet import (
RestServlet,
Expand Down Expand Up @@ -53,6 +53,8 @@ class SendServerNoticeServlet(RestServlet):
def __init__(self, hs: "HomeServer"):
self.hs = hs
self.auth = hs.get_auth()
self.server_notices_manager = hs.get_server_notices_manager()
self.admin_handler = hs.get_admin_handler()
self.txns = HttpTransactionCache(hs)

def register(self, json_resource: HttpServer):
Expand All @@ -79,19 +81,22 @@ async def on_POST(
# We grab the server notices manager here as its initialisation has a check for worker processes,
# but worker processes still need to initialise SendServerNoticeServlet (as it is part of the
# admin api).
if not self.hs.get_server_notices_manager().is_enabled():
if not self.server_notices_manager.is_enabled():
raise SynapseError(400, "Server notices are not enabled on this server")

user_id = body["user_id"]
UserID.from_string(user_id)
if not self.hs.is_mine_id(user_id):
user_id = UserID.from_string(body["user_id"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
user_id = UserID.from_string(body["user_id"])
user_id = body["user_id"]
user = UserID.from_string(user_id)

The convention is to use *_id for the string representations of the IDs. We may as well also pull out a user_id since we use it below (I'm not a fan of doing body["user_id"] multiple times as it makes it look like we haven't validated it)

if not self.hs.is_mine(user_id):
raise SynapseError(400, "Server notices can only be sent to local users")

event = await self.hs.get_server_notices_manager().send_notice(
if not await self.admin_handler.get_user(user_id):
raise NotFoundError("User not found")

event = await self.server_notices_manager.send_notice(
user_id=body["user_id"],
type=event_type,
state_key=state_key,
event_content=body["content"],
txn_id=txn_id,
)

return 200, {"event_id": event.event_id}
Expand Down
13 changes: 9 additions & 4 deletions synapse/server_notices/server_notices_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from typing import Optional
from typing import TYPE_CHECKING, Optional

from synapse.api.constants import EventTypes, Membership, RoomCreationPreset
from synapse.events import EventBase
from synapse.types import UserID, create_requester
from synapse.util.caches.descriptors import cached

if TYPE_CHECKING:
from synapse.server import HomeServer

logger = logging.getLogger(__name__)

SERVER_NOTICE_ROOM_TAG = "m.server_notice"


class ServerNoticesManager:
def __init__(self, hs):
def __init__(self, hs: "HomeServer"):
"""

Args:
hs (synapse.server.HomeServer):
hs:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just remove the entire docstring, as its pointless at this point

"""

self._store = hs.get_datastore()
Expand Down Expand Up @@ -58,6 +61,7 @@ async def send_notice(
event_content: dict,
type: str = EventTypes.Message,
state_key: Optional[str] = None,
txn_id: Optional[str] = None,
) -> EventBase:
"""Send a notice to the given user

Expand All @@ -68,6 +72,7 @@ async def send_notice(
event_content: content of event to send
type: type of event
is_state_event: Is the event a state event
txn_id: The transaction ID.
"""
room_id = await self.get_or_create_notice_room_for_user(user_id)
await self.maybe_invite_user_to_room(user_id, room_id)
Expand All @@ -90,7 +95,7 @@ async def send_notice(
event_dict["state_key"] = state_key

event, _ = await self._event_creation_handler.create_and_send_nonmember_event(
requester, event_dict, ratelimit=False
requester, event_dict, ratelimit=False, txn_id=txn_id
)
return event

Expand Down
Loading