Implement filtering

This commit is contained in:
Brendan Abolivier 2019-10-30 15:56:33 +00:00
parent fa0dcbc8fa
commit acd16ad86a
No known key found for this signature in database
GPG Key ID: 1E015C145F1916CD
2 changed files with 20 additions and 2 deletions

View File

@ -20,6 +20,7 @@ from jsonschema import FormatChecker
from twisted.internet import defer from twisted.internet import defer
from synapse.api.constants import LabelsField
from synapse.api.errors import SynapseError from synapse.api.errors import SynapseError
from synapse.storage.presence import UserPresenceState from synapse.storage.presence import UserPresenceState
from synapse.types import RoomID, UserID from synapse.types import RoomID, UserID
@ -66,6 +67,8 @@ ROOM_EVENT_FILTER_SCHEMA = {
"contains_url": {"type": "boolean"}, "contains_url": {"type": "boolean"},
"lazy_load_members": {"type": "boolean"}, "lazy_load_members": {"type": "boolean"},
"include_redundant_members": {"type": "boolean"}, "include_redundant_members": {"type": "boolean"},
"org.matrix.labels": {"type": "array", "items": {"type": "string"}},
"org.matrix.not_labels": {"type": "array", "items": {"type": "string"}},
}, },
} }
@ -259,6 +262,9 @@ class Filter(object):
self.contains_url = self.filter_json.get("contains_url", None) self.contains_url = self.filter_json.get("contains_url", None)
self.labels = self.filter_json.get("org.matrix.labels", None)
self.not_labels = self.filter_json.get("org.matrix.not_labels", [])
def filters_all_types(self): def filters_all_types(self):
return "*" in self.not_types return "*" in self.not_types
@ -282,6 +288,7 @@ class Filter(object):
room_id = None room_id = None
ev_type = "m.presence" ev_type = "m.presence"
contains_url = False contains_url = False
labels = []
else: else:
sender = event.get("sender", None) sender = event.get("sender", None)
if not sender: if not sender:
@ -300,10 +307,11 @@ class Filter(object):
content = event.get("content", {}) content = event.get("content", {})
# check if there is a string url field in the content for filtering purposes # check if there is a string url field in the content for filtering purposes
contains_url = isinstance(content.get("url"), text_type) contains_url = isinstance(content.get("url"), text_type)
labels = content.get(LabelsField)
return self.check_fields(room_id, sender, ev_type, contains_url) return self.check_fields(room_id, sender, ev_type, labels, contains_url)
def check_fields(self, room_id, sender, event_type, contains_url): def check_fields(self, room_id, sender, event_type, labels, contains_url):
"""Checks whether the filter matches the given event fields. """Checks whether the filter matches the given event fields.
Returns: Returns:
@ -313,6 +321,7 @@ class Filter(object):
"rooms": lambda v: room_id == v, "rooms": lambda v: room_id == v,
"senders": lambda v: sender == v, "senders": lambda v: sender == v,
"types": lambda v: _matches_wildcard(event_type, v), "types": lambda v: _matches_wildcard(event_type, v),
"labels": lambda v: v in labels,
} }
for name, match_func in literal_keys.items(): for name, match_func in literal_keys.items():

View File

@ -229,6 +229,14 @@ def filter_to_clause(event_filter):
clauses.append("contains_url = ?") clauses.append("contains_url = ?")
args.append(event_filter.contains_url) args.append(event_filter.contains_url)
# We're only applying the "labels" filter on the database query, because applying the
# "not_labels" filter via a SQL query is non-trivial. Instead, we let
# event_filter.check_fields apply it, which is not as efficient but makes the
# implementation simpler.
if event_filter.labels:
clauses.append("(%s)" % " OR ".join("label = ?" for _ in event_filter.labels))
args.extend(event_filter.labels)
return " AND ".join(clauses), args return " AND ".join(clauses), args
@ -866,6 +874,7 @@ class StreamWorkerStore(EventsWorkerStore, SQLBaseStore):
sql = ( sql = (
"SELECT event_id, topological_ordering, stream_ordering" "SELECT event_id, topological_ordering, stream_ordering"
" FROM events" " FROM events"
" LEFT JOIN event_labels USING (event_id)"
" WHERE outlier = ? AND room_id = ? AND %(bounds)s" " WHERE outlier = ? AND room_id = ? AND %(bounds)s"
" ORDER BY topological_ordering %(order)s," " ORDER BY topological_ordering %(order)s,"
" stream_ordering %(order)s LIMIT ?" " stream_ordering %(order)s LIMIT ?"