diff --git a/synapse/app/appservice.py b/synapse/app/appservice.py
index dd9ee406a1..c1379fdd7d 100644
--- a/synapse/app/appservice.py
+++ b/synapse/app/appservice.py
@@ -76,7 +76,8 @@ class AppserviceServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", "")
+ bind_address = listener_config.get("bind_address", None)
+ bind_addresses = listener_config.get("bind_addresses", [])
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -85,16 +86,22 @@ class AppserviceServer(HomeServer):
resources[METRICS_PREFIX] = MetricsResource(self)
root_resource = create_resource_tree(resources, Resource())
- reactor.listenTCP(
- port,
- SynapseSite(
- "synapse.access.http.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- interface=bind_address
- )
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ port,
+ SynapseSite(
+ "synapse.access.http.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ interface=address
+ )
+
logger.info("Synapse appservice now listening on port %d", port)
def start_listening(self, listeners):
@@ -102,15 +109,22 @@ class AppserviceServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- reactor.listenTCP(
- listener["port"],
- manhole(
- username="matrix",
- password="rabbithole",
- globals={"hs": self},
- ),
- interface=listener.get("bind_address", '127.0.0.1')
- )
+ bind_address = listener.get("bind_address", None)
+ bind_addresses = listener.get("bind_addresses", [])
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ listener["port"],
+ manhole(
+ username="matrix",
+ password="rabbithole",
+ globals={"hs": self},
+ ),
+ interface=address
+ )
else:
logger.warn("Unrecognized listener type: %s", listener["type"])
diff --git a/synapse/app/client_reader.py b/synapse/app/client_reader.py
index 0086a2977e..b5e1d659e6 100644
--- a/synapse/app/client_reader.py
+++ b/synapse/app/client_reader.py
@@ -90,7 +90,8 @@ class ClientReaderServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", "")
+ bind_address = listener_config.get("bind_address", None)
+ bind_addresses = listener_config.get("bind_addresses", [])
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -108,16 +109,22 @@ class ClientReaderServer(HomeServer):
})
root_resource = create_resource_tree(resources, Resource())
- reactor.listenTCP(
- port,
- SynapseSite(
- "synapse.access.http.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- interface=bind_address
- )
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ port,
+ SynapseSite(
+ "synapse.access.http.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ interface=address
+ )
+
logger.info("Synapse client reader now listening on port %d", port)
def start_listening(self, listeners):
@@ -125,15 +132,22 @@ class ClientReaderServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- reactor.listenTCP(
- listener["port"],
- manhole(
- username="matrix",
- password="rabbithole",
- globals={"hs": self},
- ),
- interface=listener.get("bind_address", '127.0.0.1')
- )
+ bind_address = listener.get("bind_address", None)
+ bind_addresses = listener.get("bind_addresses", [])
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ listener["port"],
+ manhole(
+ username="matrix",
+ password="rabbithole",
+ globals={"hs": self},
+ ),
+ interface=address
+ )
else:
logger.warn("Unrecognized listener type: %s", listener["type"])
diff --git a/synapse/app/federation_reader.py b/synapse/app/federation_reader.py
index b5f59a9931..c6810b83db 100644
--- a/synapse/app/federation_reader.py
+++ b/synapse/app/federation_reader.py
@@ -86,7 +86,8 @@ class FederationReaderServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", "")
+ bind_address = listener_config.get("bind_address", None)
+ bind_addresses = listener_config.get("bind_addresses", [])
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -99,16 +100,22 @@ class FederationReaderServer(HomeServer):
})
root_resource = create_resource_tree(resources, Resource())
- reactor.listenTCP(
- port,
- SynapseSite(
- "synapse.access.http.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- interface=bind_address
- )
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ port,
+ SynapseSite(
+ "synapse.access.http.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ interface=address
+ )
+
logger.info("Synapse federation reader now listening on port %d", port)
def start_listening(self, listeners):
@@ -116,15 +123,22 @@ class FederationReaderServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- reactor.listenTCP(
- listener["port"],
- manhole(
- username="matrix",
- password="rabbithole",
- globals={"hs": self},
- ),
- interface=listener.get("bind_address", '127.0.0.1')
- )
+ bind_address = listener.get("bind_address", None)
+ bind_addresses = listener.get("bind_addresses", [])
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ listener["port"],
+ manhole(
+ username="matrix",
+ password="rabbithole",
+ globals={"hs": self},
+ ),
+ interface=address
+ )
else:
logger.warn("Unrecognized listener type: %s", listener["type"])
diff --git a/synapse/app/federation_sender.py b/synapse/app/federation_sender.py
index 80ea4c8062..23aae8a09c 100644
--- a/synapse/app/federation_sender.py
+++ b/synapse/app/federation_sender.py
@@ -82,7 +82,8 @@ class FederationSenderServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", "")
+ bind_address = listener_config.get("bind_address", None)
+ bind_addresses = listener_config.get("bind_addresses", [])
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -91,16 +92,22 @@ class FederationSenderServer(HomeServer):
resources[METRICS_PREFIX] = MetricsResource(self)
root_resource = create_resource_tree(resources, Resource())
- reactor.listenTCP(
- port,
- SynapseSite(
- "synapse.access.http.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- interface=bind_address
- )
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ port,
+ SynapseSite(
+ "synapse.access.http.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ interface=address
+ )
+
logger.info("Synapse federation_sender now listening on port %d", port)
def start_listening(self, listeners):
@@ -108,15 +115,22 @@ class FederationSenderServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- reactor.listenTCP(
- listener["port"],
- manhole(
- username="matrix",
- password="rabbithole",
- globals={"hs": self},
- ),
- interface=listener.get("bind_address", '127.0.0.1')
- )
+ bind_address = listener.get("bind_address", None)
+ bind_addresses = listener.get("bind_addresses", [])
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ listener["port"],
+ manhole(
+ username="matrix",
+ password="rabbithole",
+ globals={"hs": self},
+ ),
+ interface=address
+ )
else:
logger.warn("Unrecognized listener type: %s", listener["type"])
diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py
index 54f35900f8..6c69ccd7e2 100755
--- a/synapse/app/homeserver.py
+++ b/synapse/app/homeserver.py
@@ -107,7 +107,8 @@ def build_resource_for_web_client(hs):
class SynapseHomeServer(HomeServer):
def _listener_http(self, config, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", "")
+ bind_address = listener_config.get("bind_address", None)
+ bind_addresses = listener_config.get("bind_addresses", [])
tls = listener_config.get("tls", False)
site_tag = listener_config.get("tag", port)
@@ -173,29 +174,35 @@ class SynapseHomeServer(HomeServer):
root_resource = Resource()
root_resource = create_resource_tree(resources, root_resource)
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
if tls:
- reactor.listenSSL(
- port,
- SynapseSite(
- "synapse.access.https.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- self.tls_server_context_factory,
- interface=bind_address
- )
+ for address in bind_addresses:
+ reactor.listenSSL(
+ port,
+ SynapseSite(
+ "synapse.access.https.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ self.tls_server_context_factory,
+ interface=address
+ )
else:
- reactor.listenTCP(
- port,
- SynapseSite(
- "synapse.access.http.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- interface=bind_address
- )
+ for address in bind_addresses:
+ reactor.listenTCP(
+ port,
+ SynapseSite(
+ "synapse.access.http.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ interface=address
+ )
logger.info("Synapse now listening on port %d", port)
def start_listening(self):
@@ -205,15 +212,22 @@ class SynapseHomeServer(HomeServer):
if listener["type"] == "http":
self._listener_http(config, listener)
elif listener["type"] == "manhole":
- reactor.listenTCP(
- listener["port"],
- manhole(
- username="matrix",
- password="rabbithole",
- globals={"hs": self},
- ),
- interface=listener.get("bind_address", '127.0.0.1')
- )
+ bind_address = listener.get("bind_address", None)
+ bind_addresses = listener.get("bind_addresses", [])
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ listener["port"],
+ manhole(
+ username="matrix",
+ password="rabbithole",
+ globals={"hs": self},
+ ),
+ interface=address
+ )
else:
logger.warn("Unrecognized listener type: %s", listener["type"])
diff --git a/synapse/app/media_repository.py b/synapse/app/media_repository.py
index 44c19a1bef..a47283e520 100644
--- a/synapse/app/media_repository.py
+++ b/synapse/app/media_repository.py
@@ -87,7 +87,8 @@ class MediaRepositoryServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", "")
+ bind_address = listener_config.get("bind_address", None)
+ bind_addresses = listener_config.get("bind_addresses", [])
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -105,16 +106,22 @@ class MediaRepositoryServer(HomeServer):
})
root_resource = create_resource_tree(resources, Resource())
- reactor.listenTCP(
- port,
- SynapseSite(
- "synapse.access.http.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- interface=bind_address
- )
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ port,
+ SynapseSite(
+ "synapse.access.http.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ interface=address
+ )
+
logger.info("Synapse media repository now listening on port %d", port)
def start_listening(self, listeners):
@@ -122,15 +129,22 @@ class MediaRepositoryServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- reactor.listenTCP(
- listener["port"],
- manhole(
- username="matrix",
- password="rabbithole",
- globals={"hs": self},
- ),
- interface=listener.get("bind_address", '127.0.0.1')
- )
+ bind_address = listener.get("bind_address", None)
+ bind_addresses = listener.get("bind_addresses", [])
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ listener["port"],
+ manhole(
+ username="matrix",
+ password="rabbithole",
+ globals={"hs": self},
+ ),
+ interface=address
+ )
else:
logger.warn("Unrecognized listener type: %s", listener["type"])
diff --git a/synapse/app/pusher.py b/synapse/app/pusher.py
index a0e765c54f..a3df375c81 100644
--- a/synapse/app/pusher.py
+++ b/synapse/app/pusher.py
@@ -121,7 +121,8 @@ class PusherServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", "")
+ bind_address = listener_config.get("bind_address", None)
+ bind_addresses = listener_config.get("bind_addresses", [])
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -130,16 +131,33 @@ class PusherServer(HomeServer):
resources[METRICS_PREFIX] = MetricsResource(self)
root_resource = create_resource_tree(resources, Resource())
- reactor.listenTCP(
- port,
- SynapseSite(
- "synapse.access.http.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- interface=bind_address
- )
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ port,
+ SynapseSite(
+ "synapse.access.http.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ interface=address
+ )
+ else:
+ reactor.listenTCP(
+ port,
+ SynapseSite(
+ "synapse.access.http.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ interface=bind_address
+ )
+
logger.info("Synapse pusher now listening on port %d", port)
def start_listening(self, listeners):
@@ -147,15 +165,22 @@ class PusherServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- reactor.listenTCP(
- listener["port"],
- manhole(
- username="matrix",
- password="rabbithole",
- globals={"hs": self},
- ),
- interface=listener.get("bind_address", '127.0.0.1')
- )
+ bind_address = listener.get("bind_address", None)
+ bind_addresses = listener.get("bind_addresses", [])
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ listener["port"],
+ manhole(
+ username="matrix",
+ password="rabbithole",
+ globals={"hs": self},
+ ),
+ interface=address
+ )
else:
logger.warn("Unrecognized listener type: %s", listener["type"])
diff --git a/synapse/app/synchrotron.py b/synapse/app/synchrotron.py
index bf1b995dc2..439daaa60a 100644
--- a/synapse/app/synchrotron.py
+++ b/synapse/app/synchrotron.py
@@ -289,7 +289,8 @@ class SynchrotronServer(HomeServer):
def _listen_http(self, listener_config):
port = listener_config["port"]
- bind_address = listener_config.get("bind_address", "")
+ bind_address = listener_config.get("bind_address", None)
+ bind_addresses = listener_config.get("bind_addresses", [])
site_tag = listener_config.get("tag", port)
resources = {}
for res in listener_config["resources"]:
@@ -310,16 +311,22 @@ class SynchrotronServer(HomeServer):
})
root_resource = create_resource_tree(resources, Resource())
- reactor.listenTCP(
- port,
- SynapseSite(
- "synapse.access.http.%s" % (site_tag,),
- site_tag,
- listener_config,
- root_resource,
- ),
- interface=bind_address
- )
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ port,
+ SynapseSite(
+ "synapse.access.http.%s" % (site_tag,),
+ site_tag,
+ listener_config,
+ root_resource,
+ ),
+ interface=address
+ )
+
logger.info("Synapse synchrotron now listening on port %d", port)
def start_listening(self, listeners):
@@ -327,15 +334,22 @@ class SynchrotronServer(HomeServer):
if listener["type"] == "http":
self._listen_http(listener)
elif listener["type"] == "manhole":
- reactor.listenTCP(
- listener["port"],
- manhole(
- username="matrix",
- password="rabbithole",
- globals={"hs": self},
- ),
- interface=listener.get("bind_address", '127.0.0.1')
- )
+ bind_address = listener.get("bind_address", None)
+ bind_addresses = listener.get("bind_addresses", [])
+
+ if bind_address is not None:
+ bind_addresses.append(bind_address)
+
+ for address in bind_addresses:
+ reactor.listenTCP(
+ listener["port"],
+ manhole(
+ username="matrix",
+ password="rabbithole",
+ globals={"hs": self},
+ ),
+ interface=address
+ )
else:
logger.warn("Unrecognized listener type: %s", listener["type"])
diff --git a/synapse/config/server.py b/synapse/config/server.py
index 634d8e6fe5..5e6b2a68a7 100644
--- a/synapse/config/server.py
+++ b/synapse/config/server.py
@@ -155,9 +155,14 @@ class ServerConfig(Config):
# The port to listen for HTTPS requests on.
port: %(bind_port)s
- # Local interface to listen on.
- # The empty string will cause synapse to listen on all interfaces.
- bind_address: ''
+ # Local addresses to listen on.
+ # This will listen on all IPv4 addresses by default.
+ bind_addresses:
+ - '0.0.0.0'
+ # Uncomment to listen on all IPv6 interfaces
+ # N.B: On at least Linux this will also listen on all IPv4
+ # addresses, so you will need to comment out the line above.
+ # - '::'
# This is a 'http' listener, allows us to specify 'resources'.
type: http
@@ -188,7 +193,7 @@ class ServerConfig(Config):
# For when matrix traffic passes through loadbalancer that unwraps TLS.
- port: %(unsecure_port)s
tls: false
- bind_address: ''
+ bind_addresses: ['0.0.0.0']
type: http
x_forwarded: false
diff --git a/synapse/handlers/auth.py b/synapse/handlers/auth.py
index 3b146f09d6..221d7ea7a2 100644
--- a/synapse/handlers/auth.py
+++ b/synapse/handlers/auth.py
@@ -607,7 +607,7 @@ class AuthHandler(BaseHandler):
# types (mediums) of threepid. For now, we still use the existing
# infrastructure, but this is the start of synapse gaining knowledge
# of specific types of threepid (and fixes the fact that checking
- # for the presenc eof an email address during password reset was
+ # for the presence of an email address during password reset was
# case sensitive).
if medium == 'email':
address = address.lower()
@@ -617,6 +617,17 @@ class AuthHandler(BaseHandler):
self.hs.get_clock().time_msec()
)
+ @defer.inlineCallbacks
+ def delete_threepid(self, user_id, medium, address):
+ # 'Canonicalise' email addresses as per above
+ if medium == 'email':
+ address = address.lower()
+
+ ret = yield self.store.user_delete_threepid(
+ user_id, medium, address,
+ )
+ defer.returnValue(ret)
+
def _save_session(self, session):
# TODO: Persistent storage
logger.debug("Saving session %s", session)
@@ -656,8 +667,8 @@ class AuthHandler(BaseHandler):
Whether self.hash(password) == stored_hash (bool).
"""
if stored_hash:
- return bcrypt.hashpw(password + self.hs.config.password_pepper,
- stored_hash.encode('utf-8')) == stored_hash
+ return bcrypt.hashpw(password.encode('utf8') + self.hs.config.password_pepper,
+ stored_hash.encode('utf8')) == stored_hash
else:
return False
diff --git a/synapse/handlers/room_list.py b/synapse/handlers/room_list.py
index 667223df0c..19eebbd43f 100644
--- a/synapse/handlers/room_list.py
+++ b/synapse/handlers/room_list.py
@@ -62,17 +62,18 @@ class RoomListHandler(BaseHandler):
appservice and network id to use an appservice specific one.
Setting to None returns all public rooms across all lists.
"""
- if search_filter or (network_tuple and network_tuple.appservice_id is not None):
+ if search_filter:
# We explicitly don't bother caching searches or requests for
# appservice specific lists.
return self._get_public_room_list(
limit, since_token, search_filter, network_tuple=network_tuple,
)
- result = self.response_cache.get((limit, since_token))
+ key = (limit, since_token, network_tuple)
+ result = self.response_cache.get(key)
if not result:
result = self.response_cache.set(
- (limit, since_token),
+ key,
self._get_public_room_list(
limit, since_token, network_tuple=network_tuple
)
diff --git a/synapse/http/client.py b/synapse/http/client.py
index 3ec9bc7faf..ca2f770f5d 100644
--- a/synapse/http/client.py
+++ b/synapse/http/client.py
@@ -25,7 +25,7 @@ from synapse.http.endpoint import SpiderEndpoint
from canonicaljson import encode_canonical_json
from twisted.internet import defer, reactor, ssl, protocol, task
-from twisted.internet.endpoints import SSL4ClientEndpoint, TCP4ClientEndpoint
+from twisted.internet.endpoints import HostnameEndpoint, wrapClientTLS
from twisted.web.client import (
BrowserLikeRedirectAgent, ContentDecoderAgent, GzipDecoder, Agent,
readBody, PartialDownloadError,
@@ -386,26 +386,23 @@ class SpiderEndpointFactory(object):
def endpointForURI(self, uri):
logger.info("Getting endpoint for %s", uri.toBytes())
+
if uri.scheme == "http":
- return SpiderEndpoint(
- reactor, uri.host, uri.port, self.blacklist, self.whitelist,
- endpoint=TCP4ClientEndpoint,
- endpoint_kw_args={
- 'timeout': 15
- },
- )
+ endpoint_factory = HostnameEndpoint
elif uri.scheme == "https":
- tlsPolicy = self.policyForHTTPS.creatorForNetloc(uri.host, uri.port)
- return SpiderEndpoint(
- reactor, uri.host, uri.port, self.blacklist, self.whitelist,
- endpoint=SSL4ClientEndpoint,
- endpoint_kw_args={
- 'sslContextFactory': tlsPolicy,
- 'timeout': 15
- },
- )
+ tlsCreator = self.policyForHTTPS.creatorForNetloc(uri.host, uri.port)
+
+ def endpoint_factory(reactor, host, port, **kw):
+ return wrapClientTLS(
+ tlsCreator,
+ HostnameEndpoint(reactor, host, port, **kw))
else:
logger.warn("Can't get endpoint for unrecognised scheme %s", uri.scheme)
+ return None
+ return SpiderEndpoint(
+ reactor, uri.host, uri.port, self.blacklist, self.whitelist,
+ endpoint=endpoint_factory, endpoint_kw_args=dict(timeout=15),
+ )
class SpiderHttpClient(SimpleHttpClient):
diff --git a/synapse/http/endpoint.py b/synapse/http/endpoint.py
index 8c64339a7c..d8923c9abb 100644
--- a/synapse/http/endpoint.py
+++ b/synapse/http/endpoint.py
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-from twisted.internet.endpoints import SSL4ClientEndpoint, TCP4ClientEndpoint
+from twisted.internet.endpoints import HostnameEndpoint, wrapClientTLS
from twisted.internet import defer, reactor
from twisted.internet.error import ConnectError
from twisted.names import client, dns
@@ -58,11 +58,13 @@ def matrix_federation_endpoint(reactor, destination, ssl_context_factory=None,
endpoint_kw_args.update(timeout=timeout)
if ssl_context_factory is None:
- transport_endpoint = TCP4ClientEndpoint
+ transport_endpoint = HostnameEndpoint
default_port = 8008
else:
- transport_endpoint = SSL4ClientEndpoint
- endpoint_kw_args.update(sslContextFactory=ssl_context_factory)
+ def transport_endpoint(reactor, host, port, timeout):
+ return wrapClientTLS(
+ ssl_context_factory,
+ HostnameEndpoint(reactor, host, port, timeout=timeout))
default_port = 8448
if port is None:
@@ -142,7 +144,7 @@ class SpiderEndpoint(object):
Implements twisted.internet.interfaces.IStreamClientEndpoint.
"""
def __init__(self, reactor, host, port, blacklist, whitelist,
- endpoint=TCP4ClientEndpoint, endpoint_kw_args={}):
+ endpoint=HostnameEndpoint, endpoint_kw_args={}):
self.reactor = reactor
self.host = host
self.port = port
@@ -180,7 +182,7 @@ class SRVClientEndpoint(object):
"""
def __init__(self, reactor, service, domain, protocol="tcp",
- default_port=None, endpoint=TCP4ClientEndpoint,
+ default_port=None, endpoint=HostnameEndpoint,
endpoint_kw_args={}):
self.reactor = reactor
self.service_name = "_%s._%s.%s" % (service, protocol, domain)
diff --git a/synapse/python_dependencies.py b/synapse/python_dependencies.py
index 3742a25b37..7817b0cd91 100644
--- a/synapse/python_dependencies.py
+++ b/synapse/python_dependencies.py
@@ -24,7 +24,7 @@ REQUIREMENTS = {
"signedjson>=1.0.0": ["signedjson>=1.0.0"],
"pynacl==0.3.0": ["nacl==0.3.0", "nacl.bindings"],
"service_identity>=1.0.0": ["service_identity>=1.0.0"],
- "Twisted>=15.1.0": ["twisted>=15.1.0"],
+ "Twisted>=16.0.0": ["twisted>=16.0.0"],
"pyopenssl>=0.14": ["OpenSSL>=0.14"],
"pyyaml": ["yaml"],
"pyasn1": ["pyasn1"],
diff --git a/synapse/rest/client/v2_alpha/account.py b/synapse/rest/client/v2_alpha/account.py
index eb49ad62e9..e74e5e0123 100644
--- a/synapse/rest/client/v2_alpha/account.py
+++ b/synapse/rest/client/v2_alpha/account.py
@@ -241,7 +241,7 @@ class ThreepidRestServlet(RestServlet):
for reqd in ['medium', 'address', 'validated_at']:
if reqd not in threepid:
- logger.warn("Couldn't add 3pid: invalid response from ID sevrer")
+ logger.warn("Couldn't add 3pid: invalid response from ID server")
raise SynapseError(500, "Invalid response from ID Server")
yield self.auth_handler.add_threepid(
@@ -263,9 +263,43 @@ class ThreepidRestServlet(RestServlet):
defer.returnValue((200, {}))
+class ThreepidDeleteRestServlet(RestServlet):
+ PATTERNS = client_v2_patterns("/account/3pid/delete$", releases=())
+
+ def __init__(self, hs):
+ super(ThreepidDeleteRestServlet, self).__init__()
+ self.auth = hs.get_auth()
+ self.auth_handler = hs.get_auth_handler()
+
+ @defer.inlineCallbacks
+ def on_POST(self, request):
+ yield run_on_reactor()
+
+ body = parse_json_object_from_request(request)
+
+ required = ['medium', 'address']
+ absent = []
+ for k in required:
+ if k not in body:
+ absent.append(k)
+
+ if absent:
+ raise SynapseError(400, "Missing params: %r" % absent, Codes.MISSING_PARAM)
+
+ requester = yield self.auth.get_user_by_req(request)
+ user_id = requester.user.to_string()
+
+ yield self.auth_handler.delete_threepid(
+ user_id, body['medium'], body['address']
+ )
+
+ defer.returnValue((200, {}))
+
+
def register_servlets(hs, http_server):
PasswordRequestTokenRestServlet(hs).register(http_server)
PasswordRestServlet(hs).register(http_server)
DeactivateAccountRestServlet(hs).register(http_server)
ThreepidRequestTokenRestServlet(hs).register(http_server)
ThreepidRestServlet(hs).register(http_server)
+ ThreepidDeleteRestServlet(hs).register(http_server)
diff --git a/synapse/storage/registration.py b/synapse/storage/registration.py
index 983a8ec52b..26be6060c3 100644
--- a/synapse/storage/registration.py
+++ b/synapse/storage/registration.py
@@ -413,6 +413,17 @@ class RegistrationStore(background_updates.BackgroundUpdateStore):
desc="user_delete_threepids",
)
+ def user_delete_threepid(self, user_id, medium, address):
+ return self._simple_delete(
+ "user_threepids",
+ keyvalues={
+ "user_id": user_id,
+ "medium": medium,
+ "address": address,
+ },
+ desc="user_delete_threepids",
+ )
+
@defer.inlineCallbacks
def count_all_users(self):
"""Counts all users registered on the homeserver."""
|