Skip to content
Snippets Groups Projects
Commit 3c1080b6 authored by Neil Johnson's avatar Neil Johnson
Browse files

refactor for readability, and reuse caching for setting tags

parent eff3ae3b
No related branches found
No related tags found
No related merge requests found
...@@ -18,6 +18,7 @@ from twisted.internet import defer ...@@ -18,6 +18,7 @@ from twisted.internet import defer
from synapse.api.constants import EventTypes from synapse.api.constants import EventTypes
from synapse.api.errors import AuthError, SynapseError from synapse.api.errors import AuthError, SynapseError
from synapse.server_notices.server_notices_manager import SERVER_NOTICE_ROOM_TAG
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -57,80 +58,121 @@ class ResourceLimitsServerNotices(object): ...@@ -57,80 +58,121 @@ class ResourceLimitsServerNotices(object):
if self._hs_disabled is True: if self._hs_disabled is True:
return return
if self._limit_usage_by_mau is True: if self._limit_usage_by_mau is False:
timestamp = yield self._store.user_last_seen_monthly_active(user_id) return
if timestamp is None:
# This user will be blocked from receiving the notice anyway.
# In practice, not sure we can ever get here
return
room_id = yield self._server_notices_manager.get_notice_room_for_user(user_id)
# Need to set tag here because room may have been created prior to timestamp = yield self._store.user_last_seen_monthly_active(user_id)
# tagging being set on creation. Ideally would set something to read if timestamp is None:
# room tags first, and cache that aggressively/ # This user will be blocked from receiving the notice anyway.
yield self._store.add_tag_to_room(user_id, room_id, 'm.server_notice', None) # In practice, not sure we can ever get here
return
currently_blocked = False # Determine current state of room
pinned_state_event = None
try: room_id = yield self._server_notices_manager.get_notice_room_for_user(user_id)
pinned_state_event = yield self._state.get_current_state(
room_id, event_type=EventTypes.Pinned yield self._check_and_set_tags(user_id, room_id)
currently_blocked, ref_events = yield self._is_room_currently_blocked(room_id)
try:
# Normally should always pass in user_id if you have it, but in
# this case are checking what would happen to other users if they
# were to arrive.
yield self.auth.check_auth_blocking()
if currently_blocked:
# Room is notifying of a block, when it ought not to be.
# Remove block notification
content = {
"pinned": ref_events
}
yield self._server_notices_manager.send_notice(
user_id, content, EventTypes.Pinned, '',
) )
except AuthError as e:
# The user has yet to join the server notices room except AuthError as e:
pass
referenced_events = []
if pinned_state_event is not None:
referenced_events = pinned_state_event.content.get('pinned')
events = yield self._store.get_events(referenced_events)
for event_id, event in events.items():
if event.type == EventTypes.ServerNoticeLimitReached:
currently_blocked = True
try: try:
# Normally should always pass in user_id if you have it, but in if not currently_blocked:
# this case are checking what would happen to other users if they # Room is not notifying of a block, when it ought to be.
# were to arrive. # Add block notification
yield self.auth.check_auth_blocking()
# Need to start removing notices
# if user_id in self._notified_of_blocking:
if currently_blocked:
# Send message to remove warning
# send state event here
# How do I do this? if drop the id, how to refer to it?
content = { content = {
"pinned": [] 'body': e.msg,
'admin_uri': self._admin_uri,
}
event = yield self._server_notices_manager.send_notice(
user_id, content, EventTypes.ServerNoticeLimitReached
)
content = {
"pinned": [
event.event_id,
]
} }
yield self._server_notices_manager.send_notice( yield self._server_notices_manager.send_notice(
user_id, content, EventTypes.Pinned, '', user_id, content, EventTypes.Pinned, '',
) )
except AuthError as e: except SynapseError as e:
# Need to start notifying of blocking logger.error("Error sending resource limits server notice: %s", e)
try:
if not currently_blocked: @defer.inlineCallbacks
# TODO use admin email contained in error once PR lands def _check_and_set_tags(self, user_id, room_id):
content = { """
'body': e.msg, Since server notices rooms were originally not with tags,
'admin_uri': self._admin_uri, important to check that tags have been set correctly
} Args:
event = yield self._server_notices_manager.send_notice( user_id(str): the user in question
user_id, content, EventTypes.ServerNoticeLimitReached room_id(str): the server notices room for that user
) """
tags = yield self._store.get_tags_for_user(user_id)
# send server notices state event here server_notices_tags = tags.get(room_id)
# TODO Over writing pinned events need_to_set_tag = True
content = { if server_notices_tags:
"pinned": [ if server_notice_tags.get(SERVER_NOTICE_ROOM_TAG):
event.event_id, # tag already present, nothing to do here
] need_to_set_tag = False
} if need_to_set_tag:
yield self._server_notices_manager.send_notice( yield self._store.add_tag_to_room(
user_id, content, EventTypes.Pinned, '', user_id, room_id, SERVER_NOTICE_ROOM_TAG, None
) )
except SynapseError as e: @defer.inlineCallbacks
logger.error("Error sending resource limits server notice: %s", e) def _is_room_currently_blocked(self, room_id):
"""
Determines if the room is currently blocked
Args:
room_id(str): The room id of the server notices room
Returns:
bool: Is the room currently blocked
list: The list of pinned events that are unrelated to limit blocking
This list can be used as a convenience in the case where the block
is to be lifted and the remaining pinned event references need to be
preserved
"""
currently_blocked = False
pinned_state_event = None
try:
pinned_state_event = yield self._state.get_current_state(
room_id, event_type=EventTypes.Pinned
)
except AuthError as e:
# The user has yet to join the server notices room
pass
referenced_events = []
if pinned_state_event is not None:
referenced_events = pinned_state_event.content.get('pinned')
events = yield self._store.get_events(referenced_events)
event_to_remove = None
for event_id, event in events.items():
if event.type == EventTypes.ServerNoticeLimitReached:
currently_blocked = True
# remove event in case we need to disable blocking later on.
if event_id in referenced_events:
referenced_events.remove(event.event_id)
defer.returnValue((currently_blocked, referenced_events))
...@@ -22,6 +22,8 @@ from synapse.util.caches.descriptors import cachedInlineCallbacks ...@@ -22,6 +22,8 @@ from synapse.util.caches.descriptors import cachedInlineCallbacks
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
SERVER_NOTICE_ROOM_TAG = "m.server_notice"
class ServerNoticesManager(object): class ServerNoticesManager(object):
def __init__(self, hs): def __init__(self, hs):
...@@ -151,7 +153,9 @@ class ServerNoticesManager(object): ...@@ -151,7 +153,9 @@ class ServerNoticesManager(object):
creator_join_profile=join_profile, creator_join_profile=join_profile,
) )
room_id = info['room_id'] room_id = info['room_id']
yield self._store.add_tag_to_room(user_id, room_id, 'm.server_notice', None) yield self._store.add_tag_to_room(
user_id, room_id, SERVER_NOTICE_ROOM_TAG, None
)
logger.info("Created server notices room %s for %s", room_id, user_id) logger.info("Created server notices room %s for %s", room_id, user_id)
defer.returnValue(room_id) defer.returnValue(room_id)
...@@ -54,6 +54,7 @@ class TestResourceLimitsServerNotices(unittest.TestCase): ...@@ -54,6 +54,7 @@ class TestResourceLimitsServerNotices(unittest.TestCase):
self._rlsn._server_notices_manager.get_notice_room_for_user = Mock( self._rlsn._server_notices_manager.get_notice_room_for_user = Mock(
returnValue="" returnValue=""
) )
self._rlsn._store.add_tag_to_room = Mock()
self.hs.config.admin_uri = "mailto:user@test.com" self.hs.config.admin_uri = "mailto:user@test.com"
@defer.inlineCallbacks @defer.inlineCallbacks
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment