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

Commit

Permalink
Merge pull request #2474 from matrix-org/dbkr/spam_check_module
Browse files Browse the repository at this point in the history
Make the spam checker a module
  • Loading branch information
dbkr authored Sep 27, 2017
2 parents 8ad5f34 + ef3a5ae commit 74e494b
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 23 deletions.
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
35 changes: 35 additions & 0 deletions synapse/config/spam_checker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Copyright 2017 New Vector Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# 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.util.module_loader import load_module

from ._base import Config


class SpamCheckerConfig(Config):
def read_config(self, config):
self.spam_checker = None

provider = config.get("spam_checker", None)
if provider is not None:
self.spam_checker = load_module(provider)

def default_config(self, **kwargs):
return """\
# spam_checker:
# module: "my_custom_project.SuperSpamChecker"
# config:
# example_option: 'things'
"""
43 changes: 26 additions & 17 deletions synapse/events/spamcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,34 @@
# limitations under the License.


def check_event_for_spam(event):
"""Checks if a given event is considered "spammy" by this server.
class SpamChecker(object):
def __init__(self, hs):
self.spam_checker = None

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.
module = None
config = None
try:
module, config = hs.config.spam_checker
except:
pass

Args:
event (synapse.events.EventBase): the event to be checked
if module is not None:
self.spam_checker = module(config=config)

Returns:
bool: True if the event is spammy.
"""
if not hasattr(event, "content") or "body" not in event.content:
return False
def check_event_for_spam(self, event):
"""Checks if a given event is considered "spammy" by this server.
# for example:
#
# if "the third flower is green" in event.content["body"]:
# return True
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.
return False
Args:
event (synapse.events.EventBase): the event to be checked
Returns:
bool: True if the event is spammy.
"""
if self.spam_checker is None:
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):
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

0 comments on commit 74e494b

Please sign in to comment.