1# Copyright 2016 OpenMarket Ltd
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import logging
16from typing import TYPE_CHECKING, Awaitable, Tuple
17
18from synapse.http import servlet
19from synapse.http.server import HttpServer
20from synapse.http.servlet import assert_params_in_dict, parse_json_object_from_request
21from synapse.http.site import SynapseRequest
22from synapse.logging.opentracing import set_tag, trace
23from synapse.rest.client.transactions import HttpTransactionCache
24from synapse.types import JsonDict
25
26from ._base import client_patterns
27
28if TYPE_CHECKING:
29    from synapse.server import HomeServer
30
31logger = logging.getLogger(__name__)
32
33
34class SendToDeviceRestServlet(servlet.RestServlet):
35    PATTERNS = client_patterns(
36        "/sendToDevice/(?P<message_type>[^/]*)/(?P<txn_id>[^/]*)$"
37    )
38
39    def __init__(self, hs: "HomeServer"):
40        super().__init__()
41        self.hs = hs
42        self.auth = hs.get_auth()
43        self.txns = HttpTransactionCache(hs)
44        self.device_message_handler = hs.get_device_message_handler()
45
46    @trace(opname="sendToDevice")
47    def on_PUT(
48        self, request: SynapseRequest, message_type: str, txn_id: str
49    ) -> Awaitable[Tuple[int, JsonDict]]:
50        set_tag("message_type", message_type)
51        set_tag("txn_id", txn_id)
52        return self.txns.fetch_or_execute_request(
53            request, self._put, request, message_type, txn_id
54        )
55
56    async def _put(
57        self, request: SynapseRequest, message_type: str, txn_id: str
58    ) -> Tuple[int, JsonDict]:
59        requester = await self.auth.get_user_by_req(request, allow_guest=True)
60
61        content = parse_json_object_from_request(request)
62        assert_params_in_dict(content, ("messages",))
63
64        await self.device_message_handler.send_device_message(
65            requester, message_type, content["messages"]
66        )
67
68        return 200, {}
69
70
71def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
72    SendToDeviceRestServlet(hs).register(http_server)
73