Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Make the spam checker a module #2474

Merged
merged 5 commits into from
Sep 27, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion synapse/config/homeserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@
from .emailconfig import EmailConfig
from .workers import WorkerConfig
from .push import PushConfig
from .spam_checker import SpamCheckerConfig


class HomeServerConfig(TlsConfig, ServerConfig, DatabaseConfig, LoggingConfig,
RatelimitConfig, ContentRepositoryConfig, CaptchaConfig,
VoipConfig, RegistrationConfig, MetricsConfig, ApiConfig,
AppServiceConfig, KeyConfig, SAML2Config, CasConfig,
JWTConfig, PasswordConfig, EmailConfig,
WorkerConfig, PasswordAuthProviderConfig, PushConfig,):
WorkerConfig, PasswordAuthProviderConfig, PushConfig,
SpamCheckerConfig,):
pass


Expand Down
37 changes: 20 additions & 17 deletions synapse/events/spamcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,29 @@
# See the License for the specific language governing permissions and
# limitations under the License.

class SpamChecker(object):
def __init__(self, hs):
self.spam_checker = None

def check_event_for_spam(event):
"""Checks if a given event is considered "spammy" by this server.
if hs.config.spam_checker is not None:
module, config = hs.config.spam_checker
print("cfg %r", config)
self.spam_checker = module(config=config)

If the server considers an event spammy, then it will be rejected if
sent by a local user. If it is sent by a user on another server, then
users receive a blank event.
def check_event_for_spam(self, event):
"""Checks if a given event is considered "spammy" by this server.

Args:
event (synapse.events.EventBase): the event to be checked
If the server considers an event spammy, then it will be rejected if
sent by a local user. If it is sent by a user on another server, then
users receive a blank event.

Returns:
bool: True if the event is spammy.
"""
if not hasattr(event, "content") or "body" not in event.content:
return False
Args:
event (synapse.events.EventBase): the event to be checked

# for example:
#
# if "the third flower is green" in event.content["body"]:
# return True
Returns:
bool: True if the event is spammy.
"""
if self.spam_checker is None:
return False

return False
return self.spam_checker.check_event_for_spam(event)
5 changes: 2 additions & 3 deletions synapse/federation/federation_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

from synapse.api.errors import SynapseError
from synapse.crypto.event_signing import check_event_content_hash
from synapse.events import spamcheck
from synapse.events.utils import prune_event
from synapse.util import unwrapFirstError, logcontext
from twisted.internet import defer
Expand All @@ -26,7 +25,7 @@

class FederationBase(object):
def __init__(self, hs):
pass
self.spam_checker = hs.get_spam_checker()

@defer.inlineCallbacks
def _check_sigs_and_hash_and_fetch(self, origin, pdus, outlier=False,
Expand Down Expand Up @@ -144,7 +143,7 @@ def callback(_, pdu, redacted):
)
return redacted

if spamcheck.check_event_for_spam(pdu):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we're requiring this to be run synchronously? I.e., no IO while checking?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, same as before basically (it doesn't yield on the function call)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more wondering whether we really want to preclude the spam checkers from e.g. accessing the DB, but ok.

if self.spam_checker.check_event_for_spam(pdu):
logger.warn(
"Event contains spam, redacting %s: %s",
pdu.event_id, pdu.get_pdu_json()
Expand Down
5 changes: 3 additions & 2 deletions synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from synapse.events import spamcheck
from twisted.internet import defer

from synapse.api.constants import EventTypes, Membership
Expand Down Expand Up @@ -58,6 +57,8 @@ def __init__(self, hs):

self.action_generator = hs.get_action_generator()

self.spam_checker = hs.get_spam_checker()

@defer.inlineCallbacks
def purge_history(self, room_id, event_id):
event = yield self.store.get_event(event_id)
Expand Down Expand Up @@ -322,7 +323,7 @@ def create_and_send_nonmember_event(
txn_id=txn_id
)

if spamcheck.check_event_for_spam(event):
if self.spam_checker.check_event_for_spam(event):
raise SynapseError(
403, "Spam is not permitted here", Codes.FORBIDDEN
)
Expand Down
5 changes: 5 additions & 0 deletions synapse/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from synapse.appservice.scheduler import ApplicationServiceScheduler
from synapse.crypto.keyring import Keyring
from synapse.events.builder import EventBuilderFactory
from synapse.events.spamcheck import SpamChecker
from synapse.federation import initialize_http_replication
from synapse.federation.send_queue import FederationRemoteSendQueue
from synapse.federation.transport.client import TransportLayerClient
Expand Down Expand Up @@ -139,6 +140,7 @@ def build_DEPENDENCY(self)
'read_marker_handler',
'action_generator',
'user_directory_handler',
'spam_checker',
]

def __init__(self, hostname, **kwargs):
Expand Down Expand Up @@ -309,6 +311,9 @@ def build_action_generator(self):
def build_user_directory_handler(self):
return UserDirectoyHandler(self)

def build_spam_checker(self):
return SpamChecker(self)

def remove_pusher(self, app_id, push_key, user_id):
return self.get_pusherpool().remove_pusher(app_id, push_key, user_id)

Expand Down