presence.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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. import logging
  24. logger = logging.getLogger(__name__)
  25. class PresenceStatusRestServlet(ClientV1RestServlet):
  26. PATTERNS = client_path_patterns("/presence/(?P<user_id>[^/]*)/status")
  27. def __init__(self, hs):
  28. super(PresenceStatusRestServlet, self).__init__(hs)
  29. self.presence_handler = hs.get_presence_handler()
  30. self.clock = hs.get_clock()
  31. @defer.inlineCallbacks
  32. def on_GET(self, request, user_id):
  33. requester = yield self.auth.get_user_by_req(request)
  34. user = UserID.from_string(user_id)
  35. if requester.user != user:
  36. allowed = yield self.presence_handler.is_visible(
  37. observed_user=user, observer_user=requester.user,
  38. )
  39. if not allowed:
  40. raise AuthError(403, "You are not allowed to see their presence.")
  41. state = yield self.presence_handler.get_state(target_user=user)
  42. state = format_user_presence_state(state, self.clock.time_msec())
  43. defer.returnValue((200, state))
  44. @defer.inlineCallbacks
  45. def on_PUT(self, request, user_id):
  46. requester = yield self.auth.get_user_by_req(request)
  47. user = UserID.from_string(user_id)
  48. if requester.user != user:
  49. raise AuthError(403, "Can only set your own presence state")
  50. state = {}
  51. content = parse_json_object_from_request(request)
  52. try:
  53. state["presence"] = content.pop("presence")
  54. if "status_msg" in content:
  55. state["status_msg"] = content.pop("status_msg")
  56. if not isinstance(state["status_msg"], basestring):
  57. raise SynapseError(400, "status_msg must be a string.")
  58. if content:
  59. raise KeyError()
  60. except SynapseError as e:
  61. raise e
  62. except Exception:
  63. raise SynapseError(400, "Unable to parse state")
  64. yield self.presence_handler.set_state(user, state)
  65. defer.returnValue((200, {}))
  66. def on_OPTIONS(self, request):
  67. return (200, {})
  68. class PresenceListRestServlet(ClientV1RestServlet):
  69. PATTERNS = client_path_patterns("/presence/list/(?P<user_id>[^/]*)")
  70. def __init__(self, hs):
  71. super(PresenceListRestServlet, self).__init__(hs)
  72. self.presence_handler = hs.get_presence_handler()
  73. @defer.inlineCallbacks
  74. def on_GET(self, request, user_id):
  75. requester = yield self.auth.get_user_by_req(request)
  76. user = UserID.from_string(user_id)
  77. if not self.hs.is_mine(user):
  78. raise SynapseError(400, "User not hosted on this Home Server")
  79. if requester.user != user:
  80. raise SynapseError(400, "Cannot get another user's presence list")
  81. presence = yield self.presence_handler.get_presence_list(
  82. observer_user=user, accepted=True
  83. )
  84. defer.returnValue((200, presence))
  85. @defer.inlineCallbacks
  86. def on_POST(self, request, user_id):
  87. requester = yield self.auth.get_user_by_req(request)
  88. user = UserID.from_string(user_id)
  89. if not self.hs.is_mine(user):
  90. raise SynapseError(400, "User not hosted on this Home Server")
  91. if requester.user != user:
  92. raise SynapseError(
  93. 400, "Cannot modify another user's presence list")
  94. content = parse_json_object_from_request(request)
  95. if "invite" in content:
  96. for u in content["invite"]:
  97. if not isinstance(u, basestring):
  98. raise SynapseError(400, "Bad invite value.")
  99. if len(u) == 0:
  100. continue
  101. invited_user = UserID.from_string(u)
  102. yield self.presence_handler.send_presence_invite(
  103. observer_user=user, observed_user=invited_user
  104. )
  105. if "drop" in content:
  106. for u in content["drop"]:
  107. if not isinstance(u, basestring):
  108. raise SynapseError(400, "Bad drop value.")
  109. if len(u) == 0:
  110. continue
  111. dropped_user = UserID.from_string(u)
  112. yield self.presence_handler.drop(
  113. observer_user=user, observed_user=dropped_user
  114. )
  115. defer.returnValue((200, {}))
  116. def on_OPTIONS(self, request):
  117. return (200, {})
  118. def register_servlets(hs, http_server):
  119. PresenceStatusRestServlet(hs).register(http_server)
  120. PresenceListRestServlet(hs).register(http_server)