Merge remote-tracking branch 'origin/develop' into matrix-org-hotfixes
This commit is contained in:
commit
82781f5838
|
@ -0,0 +1 @@
|
|||
Synapse now uses the best performing JSON encoder/decoder according to your runtime (simplejson on CPython, stdlib json on PyPy).
|
|
@ -0,0 +1 @@
|
|||
Add optional ip_range_whitelist param to AS registration files to lock AS IP access
|
|
@ -19,6 +19,7 @@ from six import itervalues
|
|||
|
||||
import pymacaroons
|
||||
from twisted.internet import defer
|
||||
from netaddr import IPAddress
|
||||
|
||||
import synapse.types
|
||||
from synapse import event_auth
|
||||
|
@ -244,6 +245,11 @@ class Auth(object):
|
|||
if app_service is None:
|
||||
defer.returnValue((None, None))
|
||||
|
||||
if app_service.ip_range_whitelist:
|
||||
ip_address = IPAddress(self.hs.get_ip_from_request(request))
|
||||
if ip_address not in app_service.ip_range_whitelist:
|
||||
defer.returnValue((None, None))
|
||||
|
||||
if "user_id" not in request.args:
|
||||
defer.returnValue((app_service.sender, app_service))
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
|
||||
import logging
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
from six import iteritems
|
||||
from six.moves import http_client
|
||||
|
||||
|
|
|
@ -17,7 +17,8 @@ from synapse.storage.presence import UserPresenceState
|
|||
from synapse.types import UserID, RoomID
|
||||
from twisted.internet import defer
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
import jsonschema
|
||||
from jsonschema import FormatChecker
|
||||
|
||||
|
|
|
@ -85,7 +85,8 @@ class ApplicationService(object):
|
|||
NS_LIST = [NS_USERS, NS_ALIASES, NS_ROOMS]
|
||||
|
||||
def __init__(self, token, hostname, url=None, namespaces=None, hs_token=None,
|
||||
sender=None, id=None, protocols=None, rate_limited=True):
|
||||
sender=None, id=None, protocols=None, rate_limited=True,
|
||||
ip_range_whitelist=None):
|
||||
self.token = token
|
||||
self.url = url
|
||||
self.hs_token = hs_token
|
||||
|
@ -93,6 +94,7 @@ class ApplicationService(object):
|
|||
self.server_name = hostname
|
||||
self.namespaces = self._check_namespaces(namespaces)
|
||||
self.id = id
|
||||
self.ip_range_whitelist = ip_range_whitelist
|
||||
|
||||
if "|" in self.id:
|
||||
raise Exception("application service ID cannot contain '|' character")
|
||||
|
|
|
@ -17,6 +17,8 @@ from ._base import Config, ConfigError
|
|||
from synapse.appservice import ApplicationService
|
||||
from synapse.types import UserID
|
||||
|
||||
from netaddr import IPSet
|
||||
|
||||
import yaml
|
||||
import logging
|
||||
|
||||
|
@ -154,6 +156,13 @@ def _load_appservice(hostname, as_info, config_filename):
|
|||
" will not receive events or queries.",
|
||||
config_filename,
|
||||
)
|
||||
|
||||
ip_range_whitelist = None
|
||||
if as_info.get('ip_range_whitelist'):
|
||||
ip_range_whitelist = IPSet(
|
||||
as_info.get('ip_range_whitelist')
|
||||
)
|
||||
|
||||
return ApplicationService(
|
||||
token=as_info["as_token"],
|
||||
hostname=hostname,
|
||||
|
@ -163,5 +172,6 @@ def _load_appservice(hostname, as_info, config_filename):
|
|||
sender=user_id,
|
||||
id=as_info["id"],
|
||||
protocols=protocols,
|
||||
rate_limited=rate_limited
|
||||
rate_limited=rate_limited,
|
||||
ip_range_whitelist=ip_range_whitelist,
|
||||
)
|
||||
|
|
|
@ -18,7 +18,7 @@ from twisted.web.http import HTTPClient
|
|||
from twisted.internet.protocol import Factory
|
||||
from twisted.internet import defer, reactor
|
||||
from synapse.http.endpoint import matrix_federation_endpoint
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
import logging
|
||||
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
# limitations under the License.
|
||||
import logging
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
from twisted.internet import defer
|
||||
|
||||
from synapse.api.errors import AuthError, FederationError, SynapseError, NotFoundError
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
from twisted.internet import defer, threads
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
from ._base import BaseHandler
|
||||
from synapse.api.constants import LoginType
|
||||
from synapse.api.errors import (
|
||||
|
@ -32,7 +34,6 @@ from twisted.web.client import PartialDownloadError
|
|||
import logging
|
||||
import bcrypt
|
||||
import pymacaroons
|
||||
import simplejson
|
||||
import attr
|
||||
|
||||
import synapse.util.stringutils as stringutils
|
||||
|
@ -403,7 +404,7 @@ class AuthHandler(BaseHandler):
|
|||
except PartialDownloadError as pde:
|
||||
# Twisted is silly
|
||||
data = pde.response
|
||||
resp_body = simplejson.loads(data)
|
||||
resp_body = json.loads(data)
|
||||
|
||||
if 'success' in resp_body:
|
||||
# Note that we do NOT check the hostname here: we explicitly
|
||||
|
|
|
@ -14,10 +14,9 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import simplejson as json
|
||||
import logging
|
||||
|
||||
from canonicaljson import encode_canonical_json
|
||||
from canonicaljson import encode_canonical_json, json
|
||||
from twisted.internet import defer
|
||||
from six import iteritems
|
||||
|
||||
|
@ -357,7 +356,7 @@ def _exception_to_failure(e):
|
|||
# include ConnectionRefused and other errors
|
||||
#
|
||||
# Note that some Exceptions (notably twisted's ResponseFailed etc) don't
|
||||
# give a string for e.message, which simplejson then fails to serialize.
|
||||
# give a string for e.message, which json then fails to serialize.
|
||||
return {
|
||||
"status": 503, "message": str(e.message),
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import logging
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
|
|
|
@ -14,10 +14,9 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import logging
|
||||
import simplejson
|
||||
import sys
|
||||
|
||||
from canonicaljson import encode_canonical_json
|
||||
from canonicaljson import encode_canonical_json, json
|
||||
import six
|
||||
from six import string_types, itervalues, iteritems
|
||||
from twisted.internet import defer
|
||||
|
@ -797,7 +796,7 @@ class EventCreationHandler(object):
|
|||
# Ensure that we can round trip before trying to persist in db
|
||||
try:
|
||||
dump = frozendict_json_encoder.encode(event.content)
|
||||
simplejson.loads(dump)
|
||||
json.loads(dump)
|
||||
except Exception:
|
||||
logger.exception("Failed to encode content: %r", event.content)
|
||||
raise
|
||||
|
|
|
@ -42,7 +42,7 @@ from twisted.web._newclient import ResponseDone
|
|||
from six import StringIO
|
||||
|
||||
from prometheus_client import Counter
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
import logging
|
||||
import urllib
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ from synapse.util import logcontext
|
|||
from synapse.util.logcontext import make_deferred_yieldable
|
||||
import synapse.util.retryutils
|
||||
|
||||
from canonicaljson import encode_canonical_json
|
||||
from canonicaljson import encode_canonical_json, json
|
||||
|
||||
from synapse.api.errors import (
|
||||
SynapseError, Codes, HttpResponseException, FederationDeniedError,
|
||||
|
@ -36,7 +36,6 @@ from synapse.api.errors import (
|
|||
from signedjson.sign import sign_json
|
||||
|
||||
import cgi
|
||||
import simplejson as json
|
||||
import logging
|
||||
import random
|
||||
import sys
|
||||
|
|
|
@ -29,7 +29,7 @@ import synapse.metrics
|
|||
import synapse.events
|
||||
|
||||
from canonicaljson import (
|
||||
encode_canonical_json, encode_pretty_printed_json
|
||||
encode_canonical_json, encode_pretty_printed_json, json
|
||||
)
|
||||
|
||||
from twisted.internet import defer
|
||||
|
@ -41,7 +41,6 @@ from twisted.web.util import redirectTo
|
|||
import collections
|
||||
import logging
|
||||
import urllib
|
||||
import simplejson
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -410,7 +409,7 @@ def respond_with_json(request, code, json_object, send_cors=False,
|
|||
if canonical_json or synapse.events.USE_FROZEN_DICTS:
|
||||
json_bytes = encode_canonical_json(json_object)
|
||||
else:
|
||||
json_bytes = simplejson.dumps(json_object)
|
||||
json_bytes = json.dumps(json_object)
|
||||
|
||||
return respond_with_json_bytes(
|
||||
request, code, json_bytes,
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
from synapse.api.errors import SynapseError, Codes
|
||||
|
||||
import logging
|
||||
import simplejson
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -171,7 +173,7 @@ def parse_json_value_from_request(request, allow_empty_body=False):
|
|||
return None
|
||||
|
||||
try:
|
||||
content = simplejson.loads(content_bytes)
|
||||
content = json.loads(content_bytes)
|
||||
except Exception as e:
|
||||
logger.warn("Unable to parse JSON: %s", e)
|
||||
raise SynapseError(400, "Content not JSON.", errcode=Codes.NOT_JSON)
|
||||
|
|
|
@ -147,7 +147,8 @@ class GCCounts(object):
|
|||
yield cm
|
||||
|
||||
|
||||
REGISTRY.register(GCCounts())
|
||||
if not running_on_pypy:
|
||||
REGISTRY.register(GCCounts())
|
||||
|
||||
#
|
||||
# Twisted reactor metrics
|
||||
|
|
|
@ -19,13 +19,17 @@ allowed to be sent by which side.
|
|||
"""
|
||||
|
||||
import logging
|
||||
import simplejson
|
||||
import platform
|
||||
|
||||
if platform.python_implementation() == "PyPy":
|
||||
import json
|
||||
_json_encoder = json.JSONEncoder()
|
||||
else:
|
||||
import simplejson as json
|
||||
_json_encoder = json.JSONEncoder(namedtuple_as_object=False)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_json_encoder = simplejson.JSONEncoder(namedtuple_as_object=False)
|
||||
|
||||
|
||||
class Command(object):
|
||||
"""The base command class.
|
||||
|
@ -102,7 +106,7 @@ class RdataCommand(Command):
|
|||
return cls(
|
||||
stream_name,
|
||||
None if token == "batch" else int(token),
|
||||
simplejson.loads(row_json)
|
||||
json.loads(row_json)
|
||||
)
|
||||
|
||||
def to_line(self):
|
||||
|
@ -300,7 +304,7 @@ class InvalidateCacheCommand(Command):
|
|||
def from_line(cls, line):
|
||||
cache_func, keys_json = line.split(" ", 1)
|
||||
|
||||
return cls(cache_func, simplejson.loads(keys_json))
|
||||
return cls(cache_func, json.loads(keys_json))
|
||||
|
||||
def to_line(self):
|
||||
return " ".join((
|
||||
|
@ -329,7 +333,7 @@ class UserIpCommand(Command):
|
|||
def from_line(cls, line):
|
||||
user_id, jsn = line.split(" ", 1)
|
||||
|
||||
access_token, ip, user_agent, device_id, last_seen = simplejson.loads(jsn)
|
||||
access_token, ip, user_agent, device_id, last_seen = json.loads(jsn)
|
||||
|
||||
return cls(
|
||||
user_id, access_token, ip, user_agent, device_id, last_seen
|
||||
|
|
|
@ -23,7 +23,8 @@ from synapse.util.msisdn import phone_number_to_msisdn
|
|||
|
||||
from .base import ClientV1RestServlet, client_path_patterns
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
import urllib
|
||||
from six.moves.urllib import parse as urlparse
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ from synapse.http.servlet import (
|
|||
from six.moves.urllib import parse as urlparse
|
||||
|
||||
import logging
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ from ._base import set_timeline_upper_limit
|
|||
import itertools
|
||||
import logging
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -22,8 +22,9 @@ from synapse.api.errors import (
|
|||
from twisted.protocols.basic import FileSender
|
||||
from twisted.web import server, resource
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
import base64
|
||||
import simplejson as json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
|
|
|
@ -23,7 +23,8 @@ import re
|
|||
import shutil
|
||||
import sys
|
||||
import traceback
|
||||
import simplejson as json
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
from six.moves import urllib_parse as urlparse
|
||||
from six import string_types
|
||||
|
|
|
@ -22,8 +22,9 @@ from synapse.storage.util.id_generators import StreamIdGenerator
|
|||
from synapse.util.caches.stream_change_cache import StreamChangeCache
|
||||
from synapse.util.caches.descriptors import cached, cachedInlineCallbacks
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
import abc
|
||||
import simplejson as json
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
# limitations under the License.
|
||||
import logging
|
||||
import re
|
||||
import simplejson as json
|
||||
from twisted.internet import defer
|
||||
from canonicaljson import json
|
||||
|
||||
from synapse.appservice import AppServiceTransaction
|
||||
from synapse.config.appservice import load_appservices
|
||||
|
|
|
@ -18,7 +18,8 @@ from . import engines
|
|||
|
||||
from twisted.internet import defer
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
# limitations under the License.
|
||||
|
||||
import logging
|
||||
import simplejson
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
|
@ -85,7 +86,7 @@ class DeviceInboxStore(BackgroundUpdateStore):
|
|||
)
|
||||
rows = []
|
||||
for destination, edu in remote_messages_by_destination.items():
|
||||
edu_json = simplejson.dumps(edu)
|
||||
edu_json = json.dumps(edu)
|
||||
rows.append((destination, stream_id, now_ms, edu_json))
|
||||
txn.executemany(sql, rows)
|
||||
|
||||
|
@ -177,7 +178,7 @@ class DeviceInboxStore(BackgroundUpdateStore):
|
|||
" WHERE user_id = ?"
|
||||
)
|
||||
txn.execute(sql, (user_id,))
|
||||
message_json = simplejson.dumps(messages_by_device["*"])
|
||||
message_json = json.dumps(messages_by_device["*"])
|
||||
for row in txn:
|
||||
# Add the message for all devices for this user on this
|
||||
# server.
|
||||
|
@ -199,7 +200,7 @@ class DeviceInboxStore(BackgroundUpdateStore):
|
|||
# Only insert into the local inbox if the device exists on
|
||||
# this server
|
||||
device = row[0]
|
||||
message_json = simplejson.dumps(messages_by_device[device])
|
||||
message_json = json.dumps(messages_by_device[device])
|
||||
messages_json_for_user[device] = message_json
|
||||
|
||||
if messages_json_for_user:
|
||||
|
@ -253,7 +254,7 @@ class DeviceInboxStore(BackgroundUpdateStore):
|
|||
messages = []
|
||||
for row in txn:
|
||||
stream_pos = row[0]
|
||||
messages.append(simplejson.loads(row[1]))
|
||||
messages.append(json.loads(row[1]))
|
||||
if len(messages) < limit:
|
||||
stream_pos = current_stream_id
|
||||
return (messages, stream_pos)
|
||||
|
@ -389,7 +390,7 @@ class DeviceInboxStore(BackgroundUpdateStore):
|
|||
messages = []
|
||||
for row in txn:
|
||||
stream_pos = row[0]
|
||||
messages.append(simplejson.loads(row[1]))
|
||||
messages.append(json.loads(row[1]))
|
||||
if len(messages) < limit:
|
||||
stream_pos = current_stream_id
|
||||
return (messages, stream_pos)
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import logging
|
||||
import simplejson as json
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
|
@ -21,6 +20,8 @@ from synapse.api.errors import StoreError
|
|||
from ._base import SQLBaseStore, Cache
|
||||
from synapse.util.caches.descriptors import cached, cachedList, cachedInlineCallbacks
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
from six import itervalues, iteritems
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -16,8 +16,7 @@ from twisted.internet import defer
|
|||
|
||||
from synapse.util.caches.descriptors import cached
|
||||
|
||||
from canonicaljson import encode_canonical_json
|
||||
import simplejson as json
|
||||
from canonicaljson import encode_canonical_json, json
|
||||
|
||||
from ._base import SQLBaseStore
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@ from twisted.internet import defer
|
|||
from synapse.util.caches.descriptors import cachedInlineCallbacks
|
||||
|
||||
import logging
|
||||
import simplejson as json
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
from six import iteritems
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@ from functools import wraps
|
|||
import itertools
|
||||
import logging
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
from twisted.internet import defer
|
||||
|
||||
from synapse.storage.events_worker import EventsWorkerStore
|
||||
|
|
|
@ -29,7 +29,8 @@ from synapse.api.errors import SynapseError
|
|||
from collections import namedtuple
|
||||
|
||||
import logging
|
||||
import simplejson as json
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
# these are only included to make the type annotations work
|
||||
from synapse.events import EventBase # noqa: F401
|
||||
|
|
|
@ -19,8 +19,7 @@ from ._base import SQLBaseStore
|
|||
from synapse.api.errors import SynapseError, Codes
|
||||
from synapse.util.caches.descriptors import cachedInlineCallbacks
|
||||
|
||||
from canonicaljson import encode_canonical_json
|
||||
import simplejson as json
|
||||
from canonicaljson import encode_canonical_json, json
|
||||
|
||||
|
||||
class FilteringStore(SQLBaseStore):
|
||||
|
|
|
@ -20,7 +20,7 @@ from synapse.api.errors import SynapseError
|
|||
|
||||
from ._base import SQLBaseStore
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
|
||||
# The category ID for the "default" category. We don't store as null in the
|
||||
|
|
|
@ -25,9 +25,10 @@ from synapse.push.baserules import list_with_base_rules
|
|||
from synapse.api.constants import EventTypes
|
||||
from twisted.internet import defer
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
import abc
|
||||
import logging
|
||||
import simplejson as json
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -17,12 +17,11 @@
|
|||
from ._base import SQLBaseStore
|
||||
from twisted.internet import defer
|
||||
|
||||
from canonicaljson import encode_canonical_json
|
||||
from canonicaljson import encode_canonical_json, json
|
||||
|
||||
from synapse.util.caches.descriptors import cachedInlineCallbacks, cachedList
|
||||
|
||||
import logging
|
||||
import simplejson as json
|
||||
import types
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -21,9 +21,10 @@ from synapse.util.caches.stream_change_cache import StreamChangeCache
|
|||
|
||||
from twisted.internet import defer
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
import abc
|
||||
import logging
|
||||
import simplejson as json
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -20,9 +20,10 @@ from synapse.storage._base import SQLBaseStore
|
|||
from synapse.storage.search import SearchStore
|
||||
from synapse.util.caches.descriptors import cached, cachedInlineCallbacks
|
||||
|
||||
from canonicaljson import json
|
||||
|
||||
import collections
|
||||
import logging
|
||||
import simplejson as json
|
||||
import re
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
|
@ -28,7 +28,7 @@ from synapse.api.constants import Membership, EventTypes
|
|||
from synapse.types import get_domain_from_id
|
||||
|
||||
import logging
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
from six import itervalues, iteritems
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
from collections import namedtuple
|
||||
import logging
|
||||
import re
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
from six import string_types
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@ from synapse.storage.account_data import AccountDataWorkerStore
|
|||
from synapse.util.caches.descriptors import cached
|
||||
from twisted.internet import defer
|
||||
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
import logging
|
||||
|
||||
from six.moves import range
|
||||
|
|
|
@ -19,12 +19,11 @@ from synapse.util.caches.descriptors import cached
|
|||
from twisted.internet import defer
|
||||
import six
|
||||
|
||||
from canonicaljson import encode_canonical_json
|
||||
from canonicaljson import encode_canonical_json, json
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
import logging
|
||||
import simplejson as json
|
||||
|
||||
# py2 sqlite has buffer hardcoded as only binary type, so we must use it,
|
||||
# despite being deprecated and removed in favor of memoryview
|
||||
|
|
|
@ -78,7 +78,8 @@ class StreamChangeCache(object):
|
|||
not_known_entities = set(entities) - set(self._entity_to_key)
|
||||
|
||||
result = (
|
||||
set(self._cache.values()[self._cache.bisect_right(stream_pos) :])
|
||||
{self._cache[k] for k in self._cache.islice(
|
||||
start=self._cache.bisect_right(stream_pos))}
|
||||
.intersection(entities)
|
||||
.union(not_known_entities)
|
||||
)
|
||||
|
@ -113,7 +114,8 @@ class StreamChangeCache(object):
|
|||
assert type(stream_pos) is int
|
||||
|
||||
if stream_pos >= self._earliest_known_stream_pos:
|
||||
return self._cache.values()[self._cache.bisect_right(stream_pos) :]
|
||||
return [self._cache[k] for k in self._cache.islice(
|
||||
start=self._cache.bisect_right(stream_pos))]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
# limitations under the License.
|
||||
|
||||
from frozendict import frozendict
|
||||
import simplejson as json
|
||||
from canonicaljson import json
|
||||
|
||||
from six import string_types
|
||||
|
||||
|
|
|
@ -86,16 +86,53 @@ class AuthTestCase(unittest.TestCase):
|
|||
|
||||
@defer.inlineCallbacks
|
||||
def test_get_user_by_req_appservice_valid_token(self):
|
||||
app_service = Mock(token="foobar", url="a_url", sender=self.test_user)
|
||||
app_service = Mock(
|
||||
token="foobar", url="a_url", sender=self.test_user,
|
||||
ip_range_whitelist=None,
|
||||
)
|
||||
self.store.get_app_service_by_token = Mock(return_value=app_service)
|
||||
self.store.get_user_by_access_token = Mock(return_value=None)
|
||||
|
||||
request = Mock(args={})
|
||||
request.getClientIP.return_value = "127.0.0.1"
|
||||
request.args["access_token"] = [self.test_token]
|
||||
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
|
||||
requester = yield self.auth.get_user_by_req(request)
|
||||
self.assertEquals(requester.user.to_string(), self.test_user)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def test_get_user_by_req_appservice_valid_token_good_ip(self):
|
||||
from netaddr import IPSet
|
||||
app_service = Mock(
|
||||
token="foobar", url="a_url", sender=self.test_user,
|
||||
ip_range_whitelist=IPSet(["192.168/16"]),
|
||||
)
|
||||
self.store.get_app_service_by_token = Mock(return_value=app_service)
|
||||
self.store.get_user_by_access_token = Mock(return_value=None)
|
||||
|
||||
request = Mock(args={})
|
||||
request.getClientIP.return_value = "192.168.10.10"
|
||||
request.args["access_token"] = [self.test_token]
|
||||
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
|
||||
requester = yield self.auth.get_user_by_req(request)
|
||||
self.assertEquals(requester.user.to_string(), self.test_user)
|
||||
|
||||
def test_get_user_by_req_appservice_valid_token_bad_ip(self):
|
||||
from netaddr import IPSet
|
||||
app_service = Mock(
|
||||
token="foobar", url="a_url", sender=self.test_user,
|
||||
ip_range_whitelist=IPSet(["192.168/16"]),
|
||||
)
|
||||
self.store.get_app_service_by_token = Mock(return_value=app_service)
|
||||
self.store.get_user_by_access_token = Mock(return_value=None)
|
||||
|
||||
request = Mock(args={})
|
||||
request.getClientIP.return_value = "131.111.8.42"
|
||||
request.args["access_token"] = [self.test_token]
|
||||
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
|
||||
d = self.auth.get_user_by_req(request)
|
||||
self.failureResultOf(d, AuthError)
|
||||
|
||||
def test_get_user_by_req_appservice_bad_token(self):
|
||||
self.store.get_app_service_by_token = Mock(return_value=None)
|
||||
self.store.get_user_by_access_token = Mock(return_value=None)
|
||||
|
@ -119,12 +156,16 @@ class AuthTestCase(unittest.TestCase):
|
|||
@defer.inlineCallbacks
|
||||
def test_get_user_by_req_appservice_valid_token_valid_user_id(self):
|
||||
masquerading_user_id = "@doppelganger:matrix.org"
|
||||
app_service = Mock(token="foobar", url="a_url", sender=self.test_user)
|
||||
app_service = Mock(
|
||||
token="foobar", url="a_url", sender=self.test_user,
|
||||
ip_range_whitelist=None,
|
||||
)
|
||||
app_service.is_interested_in_user = Mock(return_value=True)
|
||||
self.store.get_app_service_by_token = Mock(return_value=app_service)
|
||||
self.store.get_user_by_access_token = Mock(return_value=None)
|
||||
|
||||
request = Mock(args={})
|
||||
request.getClientIP.return_value = "127.0.0.1"
|
||||
request.args["access_token"] = [self.test_token]
|
||||
request.args["user_id"] = [masquerading_user_id]
|
||||
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
|
||||
|
@ -133,12 +174,16 @@ class AuthTestCase(unittest.TestCase):
|
|||
|
||||
def test_get_user_by_req_appservice_valid_token_bad_user_id(self):
|
||||
masquerading_user_id = "@doppelganger:matrix.org"
|
||||
app_service = Mock(token="foobar", url="a_url", sender=self.test_user)
|
||||
app_service = Mock(
|
||||
token="foobar", url="a_url", sender=self.test_user,
|
||||
ip_range_whitelist=None,
|
||||
)
|
||||
app_service.is_interested_in_user = Mock(return_value=False)
|
||||
self.store.get_app_service_by_token = Mock(return_value=app_service)
|
||||
self.store.get_user_by_access_token = Mock(return_value=None)
|
||||
|
||||
request = Mock(args={})
|
||||
request.getClientIP.return_value = "127.0.0.1"
|
||||
request.args["access_token"] = [self.test_token]
|
||||
request.args["user_id"] = [masquerading_user_id]
|
||||
request.requestHeaders.getRawHeaders = mock_getRawHeaders()
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
from io import BytesIO
|
||||
|
||||
import attr
|
||||
import json
|
||||
from six import text_type
|
||||
|
||||
from twisted.python.failure import Failure
|
||||
from twisted.internet.defer import Deferred
|
||||
from twisted.test.proto_helpers import MemoryReactorClock
|
||||
|
||||
from synapse.http.site import SynapseRequest
|
||||
from twisted.internet import threads
|
||||
from tests.utils import setup_test_homeserver as _sth
|
||||
|
||||
|
||||
@attr.s
|
||||
class FakeChannel(object):
|
||||
"""
|
||||
A fake Twisted Web Channel (the part that interfaces with the
|
||||
wire).
|
||||
"""
|
||||
|
||||
result = attr.ib(factory=dict)
|
||||
|
||||
@property
|
||||
def json_body(self):
|
||||
if not self.result:
|
||||
raise Exception("No result yet.")
|
||||
return json.loads(self.result["body"])
|
||||
|
||||
def writeHeaders(self, version, code, reason, headers):
|
||||
self.result["version"] = version
|
||||
self.result["code"] = code
|
||||
self.result["reason"] = reason
|
||||
self.result["headers"] = headers
|
||||
|
||||
def write(self, content):
|
||||
if "body" not in self.result:
|
||||
self.result["body"] = b""
|
||||
|
||||
self.result["body"] += content
|
||||
|
||||
def requestDone(self, _self):
|
||||
self.result["done"] = True
|
||||
|
||||
def getPeer(self):
|
||||
return None
|
||||
|
||||
def getHost(self):
|
||||
return None
|
||||
|
||||
@property
|
||||
def transport(self):
|
||||
return self
|
||||
|
||||
|
||||
class FakeSite:
|
||||
"""
|
||||
A fake Twisted Web Site, with mocks of the extra things that
|
||||
Synapse adds.
|
||||
"""
|
||||
|
||||
server_version_string = b"1"
|
||||
site_tag = "test"
|
||||
|
||||
@property
|
||||
def access_logger(self):
|
||||
class FakeLogger:
|
||||
def info(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
return FakeLogger()
|
||||
|
||||
|
||||
def make_request(method, path, content=b""):
|
||||
"""
|
||||
Make a web request using the given method and path, feed it the
|
||||
content, and return the Request and the Channel underneath.
|
||||
"""
|
||||
|
||||
if isinstance(content, text_type):
|
||||
content = content.encode('utf8')
|
||||
|
||||
site = FakeSite()
|
||||
channel = FakeChannel()
|
||||
|
||||
req = SynapseRequest(site, channel)
|
||||
req.process = lambda: b""
|
||||
req.content = BytesIO(content)
|
||||
req.requestReceived(method, path, b"1.1")
|
||||
|
||||
return req, channel
|
||||
|
||||
|
||||
def wait_until_result(clock, channel, timeout=100):
|
||||
"""
|
||||
Wait until the channel has a result.
|
||||
"""
|
||||
clock.run()
|
||||
x = 0
|
||||
|
||||
while not channel.result:
|
||||
x += 1
|
||||
|
||||
if x > timeout:
|
||||
raise Exception("Timed out waiting for request to finish.")
|
||||
|
||||
clock.advance(0.1)
|
||||
|
||||
|
||||
class ThreadedMemoryReactorClock(MemoryReactorClock):
|
||||
"""
|
||||
A MemoryReactorClock that supports callFromThread.
|
||||
"""
|
||||
def callFromThread(self, callback, *args, **kwargs):
|
||||
"""
|
||||
Make the callback fire in the next reactor iteration.
|
||||
"""
|
||||
d = Deferred()
|
||||
d.addCallback(lambda x: callback(*args, **kwargs))
|
||||
self.callLater(0, d.callback, True)
|
||||
return d
|
||||
|
||||
|
||||
def setup_test_homeserver(*args, **kwargs):
|
||||
"""
|
||||
Set up a synchronous test server, driven by the reactor used by
|
||||
the homeserver.
|
||||
"""
|
||||
d = _sth(*args, **kwargs).result
|
||||
|
||||
# Make the thread pool synchronous.
|
||||
clock = d.get_clock()
|
||||
pool = d.get_db_pool()
|
||||
|
||||
def runWithConnection(func, *args, **kwargs):
|
||||
return threads.deferToThreadPool(
|
||||
pool._reactor,
|
||||
pool.threadpool,
|
||||
pool._runWithConnection,
|
||||
func,
|
||||
*args,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def runInteraction(interaction, *args, **kwargs):
|
||||
return threads.deferToThreadPool(
|
||||
pool._reactor,
|
||||
pool.threadpool,
|
||||
pool._runInteraction,
|
||||
interaction,
|
||||
*args,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
pool.runWithConnection = runWithConnection
|
||||
pool.runInteraction = runInteraction
|
||||
|
||||
class ThreadPool:
|
||||
"""
|
||||
Threadless thread pool.
|
||||
"""
|
||||
def start(self):
|
||||
pass
|
||||
|
||||
def callInThreadWithCallback(self, onResult, function, *args, **kwargs):
|
||||
def _(res):
|
||||
if isinstance(res, Failure):
|
||||
onResult(False, res)
|
||||
else:
|
||||
onResult(True, res)
|
||||
|
||||
d = Deferred()
|
||||
d.addCallback(lambda x: function(*args, **kwargs))
|
||||
d.addBoth(_)
|
||||
clock._reactor.callLater(0, d.callback, True)
|
||||
return d
|
||||
|
||||
clock.threadpool = ThreadPool()
|
||||
pool.threadpool = ThreadPool()
|
||||
return d
|
|
@ -0,0 +1,128 @@
|
|||
import json
|
||||
import re
|
||||
|
||||
from twisted.internet.defer import Deferred
|
||||
from twisted.test.proto_helpers import MemoryReactorClock
|
||||
|
||||
from synapse.util import Clock
|
||||
from synapse.api.errors import Codes, SynapseError
|
||||
from synapse.http.server import JsonResource
|
||||
from tests import unittest
|
||||
from tests.server import make_request, setup_test_homeserver
|
||||
|
||||
|
||||
class JsonResourceTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.reactor = MemoryReactorClock()
|
||||
self.hs_clock = Clock(self.reactor)
|
||||
self.homeserver = setup_test_homeserver(
|
||||
http_client=None, clock=self.hs_clock, reactor=self.reactor
|
||||
)
|
||||
|
||||
def test_handler_for_request(self):
|
||||
"""
|
||||
JsonResource.handler_for_request gives correctly decoded URL args to
|
||||
the callback, while Twisted will give the raw bytes of URL query
|
||||
arguments.
|
||||
"""
|
||||
got_kwargs = {}
|
||||
|
||||
def _callback(request, **kwargs):
|
||||
got_kwargs.update(kwargs)
|
||||
return (200, kwargs)
|
||||
|
||||
res = JsonResource(self.homeserver)
|
||||
res.register_paths("GET", [re.compile("^/foo/(?P<room_id>[^/]*)$")], _callback)
|
||||
|
||||
request, channel = make_request(b"GET", b"/foo/%E2%98%83?a=%E2%98%83")
|
||||
request.render(res)
|
||||
|
||||
self.assertEqual(request.args, {b'a': [u"\N{SNOWMAN}".encode('utf8')]})
|
||||
self.assertEqual(got_kwargs, {u"room_id": u"\N{SNOWMAN}"})
|
||||
|
||||
def test_callback_direct_exception(self):
|
||||
"""
|
||||
If the web callback raises an uncaught exception, it will be translated
|
||||
into a 500.
|
||||
"""
|
||||
|
||||
def _callback(request, **kwargs):
|
||||
raise Exception("boo")
|
||||
|
||||
res = JsonResource(self.homeserver)
|
||||
res.register_paths("GET", [re.compile("^/foo$")], _callback)
|
||||
|
||||
request, channel = make_request(b"GET", b"/foo")
|
||||
request.render(res)
|
||||
|
||||
self.assertEqual(channel.result["code"], b'500')
|
||||
|
||||
def test_callback_indirect_exception(self):
|
||||
"""
|
||||
If the web callback raises an uncaught exception in a Deferred, it will
|
||||
be translated into a 500.
|
||||
"""
|
||||
|
||||
def _throw(*args):
|
||||
raise Exception("boo")
|
||||
|
||||
def _callback(request, **kwargs):
|
||||
d = Deferred()
|
||||
d.addCallback(_throw)
|
||||
self.reactor.callLater(1, d.callback, True)
|
||||
return d
|
||||
|
||||
res = JsonResource(self.homeserver)
|
||||
res.register_paths("GET", [re.compile("^/foo$")], _callback)
|
||||
|
||||
request, channel = make_request(b"GET", b"/foo")
|
||||
request.render(res)
|
||||
|
||||
# No error has been raised yet
|
||||
self.assertTrue("code" not in channel.result)
|
||||
|
||||
# Advance time, now there's an error
|
||||
self.reactor.advance(1)
|
||||
self.assertEqual(channel.result["code"], b'500')
|
||||
|
||||
def test_callback_synapseerror(self):
|
||||
"""
|
||||
If the web callback raises a SynapseError, it returns the appropriate
|
||||
status code and message set in it.
|
||||
"""
|
||||
|
||||
def _callback(request, **kwargs):
|
||||
raise SynapseError(403, "Forbidden!!one!", Codes.FORBIDDEN)
|
||||
|
||||
res = JsonResource(self.homeserver)
|
||||
res.register_paths("GET", [re.compile("^/foo$")], _callback)
|
||||
|
||||
request, channel = make_request(b"GET", b"/foo")
|
||||
request.render(res)
|
||||
|
||||
self.assertEqual(channel.result["code"], b'403')
|
||||
reply_body = json.loads(channel.result["body"])
|
||||
self.assertEqual(reply_body["error"], "Forbidden!!one!")
|
||||
self.assertEqual(reply_body["errcode"], "M_FORBIDDEN")
|
||||
|
||||
def test_no_handler(self):
|
||||
"""
|
||||
If there is no handler to process the request, Synapse will return 400.
|
||||
"""
|
||||
|
||||
def _callback(request, **kwargs):
|
||||
"""
|
||||
Not ever actually called!
|
||||
"""
|
||||
self.fail("shouldn't ever get here")
|
||||
|
||||
res = JsonResource(self.homeserver)
|
||||
res.register_paths("GET", [re.compile("^/foo$")], _callback)
|
||||
|
||||
request, channel = make_request(b"GET", b"/foobar")
|
||||
request.render(res)
|
||||
|
||||
self.assertEqual(channel.result["code"], b'400')
|
||||
reply_body = json.loads(channel.result["body"])
|
||||
self.assertEqual(reply_body["error"], "Unrecognized request")
|
||||
self.assertEqual(reply_body["errcode"], "M_UNRECOGNIZED")
|
Loading…
Reference in New Issue