presence.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2014-2016 OpenMarket Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. """ This module contains REST servlets to do with presence: /presence/<paths>
  16. """
  17. from twisted.internet import defer
  18. from synapse.api.errors import SynapseError, AuthError
  19. from synapse.types import UserID
  20. from synapse.handlers.presence import format_user_presence_state
  21. from synapse.http.servlet import parse_json_object_from_request
  22. from .base import ClientV1RestServlet, client_path_patterns
  23. from six import string_types
  24. import logging
  25. logger = logging.getLogger(__name__)
  26. class PresenceStatusRestServlet(ClientV1RestServlet):
  27. PATTERNS = client_path_patterns("/presence/(?P<user_id>[^/]*)/status")
  28. def __init__(self, hs):
  29. super(PresenceStatusRestServlet, self).__init__(hs)
  30. self.presence_handler = hs.get_presence_handler()
  31. self.clock = hs.get_clock()
  32. @defer.inlineCallbacks
  33. def on_GET(self, request, user_id):
  34. requester = yield self.auth.get_user_by_req(request)
  35. user = UserID.from_string(user_id)
  36. if requester.user != user:
  37. allowed = yield self.presence_handler.is_visible(
  38. observed_user=user, observer_user=requester.user,
  39. )
  40. if not allowed:
  41. raise AuthError(403, "You are not allowed to see their presence.")
  42. state = yield self.presence_handler.get_state(target_user=user)
  43. state = format_user_presence_state(state, self.clock.time_msec())
  44. defer.returnValue((200, state))
  45. @defer.inlineCallbacks
  46. def on_PUT(self, request, user_id):
  47. requester = yield self.auth.get_user_by_req(request)
  48. user = UserID.from_string(user_id)
  49. if requester.user != user:
  50. raise AuthError(403, "Can only set your own presence state")
  51. state = {}
  52. content = parse_json_object_from_request(request)
  53. try:
  54. state["presence"] = content.pop("presence")
  55. if "status_msg" in content:
  56. state["status_msg"] = content.pop("status_msg")
  57. if not isinstance(state["status_msg"], string_types):
  58. raise SynapseError(400, "status_msg must be a string.")
  59. if content:
  60. raise KeyError()
  61. except SynapseError as e:
  62. raise e
  63. except Exception:
  64. raise SynapseError(400, "Unable to parse state")
  65. yield self.presence_handler.set_state(user, state)
  66. defer.returnValue((200, {}))
  67. def on_OPTIONS(self, request):
  68. return (200, {})
  69. class PresenceListRestServlet(ClientV1RestServlet):
  70. PATTERNS = client_path_patterns("/presence/list/(?P<user_id>[^/]*)")
  71. def __init__(self, hs):
  72. super(PresenceListRestServlet, self).__init__(hs)
  73. self.presence_handler = hs.get_presence_handler()
  74. @defer.inlineCallbacks
  75. def on_GET(self, request, user_id):
  76. requester = yield self.auth.get_user_by_req(request)
  77. user = UserID.from_string(user_id)
  78. if not self.hs.is_mine(user):
  79. raise SynapseError(400, "User not hosted on this Home Server")
  80. if requester.user != user:
  81. raise SynapseError(400, "Cannot get another user's presence list")
  82. presence = yield self.presence_handler.get_presence_list(
  83. observer_user=user, accepted=True
  84. )
  85. defer.returnValue((200, presence))
  86. @defer.inlineCallbacks
  87. def on_POST(self, request, user_id):
  88. requester = yield self.auth.get_user_by_req(request)
  89. user = UserID.from_string(user_id)
  90. if not self.hs.is_mine(user):
  91. raise SynapseError(400, "User not hosted on this Home Server")
  92. if requester.user != user:
  93. raise SynapseError(
  94. 400, "Cannot modify another user's presence list")
  95. content = parse_json_object_from_request(request)
  96. if "invite" in content:
  97. for u in content["invite"]:
  98. if not isinstance(u, string_types):
  99. raise SynapseError(400, "Bad invite value.")
  100. if len(u) == 0:
  101. continue
  102. invited_user = UserID.from_string(u)
  103. yield self.presence_handler.send_presence_invite(
  104. observer_user=user, observed_user=invited_user
  105. )
  106. if "drop" in content:
  107. for u in content["drop"]:
  108. if not isinstance(u, string_types):
  109. raise SynapseError(400, "Bad drop value.")
  110. if len(u) == 0:
  111. continue
  112. dropped_user = UserID.from_string(u)
  113. yield self.presence_handler.drop(
  114. observer_user=user, observed_user=dropped_user
  115. )
  116. defer.returnValue((200, {}))
  117. def on_OPTIONS(self, request):
  118. return (200, {})
  119. def register_servlets(hs, http_server):
  120. PresenceStatusRestServlet(hs).register(http_server)
  121. PresenceListRestServlet(hs).register(http_server)