summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--changelog.d/5383.feature1
-rw-r--r--changelog.d/5507.bugfix1
-rw-r--r--changelog.d/5585.misc1
-rw-r--r--changelog.d/5586.bugfix1
-rw-r--r--changelog.d/5587.feature1
-rw-r--r--docker/Dockerfile1
-rw-r--r--docker/README.md2
-rw-r--r--synapse/handlers/presence.py21
-rw-r--r--synapse/rest/client/v1/login.py9
-rw-r--r--synapse/rest/consent/consent_resource.py4
-rwxr-xr-xsynctl12
11 files changed, 38 insertions, 16 deletions
diff --git a/changelog.d/5383.feature b/changelog.d/5383.feature
new file mode 100644
index 0000000000..5d084cf0b2
--- /dev/null
+++ b/changelog.d/5383.feature
@@ -0,0 +1 @@
+Add ability to change Docker containers [timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) with the `TZ` variable.
diff --git a/changelog.d/5507.bugfix b/changelog.d/5507.bugfix
new file mode 100644
index 0000000000..70452aa146
--- /dev/null
+++ b/changelog.d/5507.bugfix
@@ -0,0 +1 @@
+Fix bug where clients could tight loop calling `/sync` for a period.
diff --git a/changelog.d/5585.misc b/changelog.d/5585.misc
new file mode 100644
index 0000000000..6be06d4d0b
--- /dev/null
+++ b/changelog.d/5585.misc
@@ -0,0 +1 @@
+Synapse can now handle RestServlets that return coroutines.
diff --git a/changelog.d/5586.bugfix b/changelog.d/5586.bugfix
new file mode 100644
index 0000000000..c0b1ecf81a
--- /dev/null
+++ b/changelog.d/5586.bugfix
@@ -0,0 +1 @@
+Fixed m.login.jwt using unregistred user_id and added pyjwt>=1.6.4 as jwt conditional dependencies. Contributed by Pau Rodriguez-Estivill.
diff --git a/changelog.d/5587.feature b/changelog.d/5587.feature
new file mode 100644
index 0000000000..ec1503860a
--- /dev/null
+++ b/changelog.d/5587.feature
@@ -0,0 +1 @@
+Add --no-daemonize option to run synapse in the foreground, per issue #4130. Contributed by Soham Gumaste.
\ No newline at end of file
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 0939cadf39..79276209f6 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -66,6 +66,7 @@ RUN apk add --no-cache --virtual .runtime_deps \
         libpq \
         zlib \
         su-exec \
+        tzdata \
         xmlsec
 
 COPY --from=builder /install /usr/local
diff --git a/docker/README.md b/docker/README.md
index b62417c281..46bb9d2d99 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -63,7 +63,6 @@ The following environment variables are supported in `generate` mode:
 * `UID`, `GID`: the user id and group id to use for creating the data
   directories. Defaults to `991`, `991`.
 
-
 ## Running synapse
 
 Once you have a valid configuration file, you can start synapse as follows:
@@ -91,6 +90,7 @@ The following environment variables are supported in run mode:
 * `SYNAPSE_CONFIG_PATH`: path to the config file. Defaults to
   `<SYNAPSE_CONFIG_DIR>/homeserver.yaml`.
 * `UID`, `GID`: the user and group id to run Synapse as. Defaults to `991`, `991`.
+* `TZ`: the [timezone](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) the container will run with. Defaults to `UTC`.
 
 ## TLS support
 
diff --git a/synapse/handlers/presence.py b/synapse/handlers/presence.py
index 5204073a38..c80dc2eba0 100644
--- a/synapse/handlers/presence.py
+++ b/synapse/handlers/presence.py
@@ -1017,11 +1017,28 @@ class PresenceEventSource(object):
             if from_key is not None:
                 from_key = int(from_key)
 
+            max_token = self.store.get_current_presence_token()
+            if from_key == max_token:
+                # This is necessary as due to the way stream ID generators work
+                # we may get updates that have a stream ID greater than the max
+                # token (e.g. max_token is N but stream generator may return
+                # results for N+2, due to N+1 not having finished being
+                # persisted yet).
+                #
+                # This is usually fine, as it just means that we may send down
+                # some presence updates multiple times. However, we need to be
+                # careful that the sync stream either actually does make some
+                # progress or doesn't return, otherwise clients will end up
+                # tight looping calling /sync due to it immediately returning
+                # the same token repeatedly.
+                #
+                # Hence this guard where we just return nothing so that the sync
+                # doesn't return. C.f. #5503.
+                defer.returnValue(([], max_token))
+
             presence = self.get_presence_handler()
             stream_change_cache = self.store.presence_stream_cache
 
-            max_token = self.store.get_current_presence_token()
-
             users_interested_in = yield self._get_interested_in(user, explicit_room_id)
 
             user_ids_changed = set()
diff --git a/synapse/rest/client/v1/login.py b/synapse/rest/client/v1/login.py
index 3051b2171b..f961178235 100644
--- a/synapse/rest/client/v1/login.py
+++ b/synapse/rest/client/v1/login.py
@@ -323,12 +323,12 @@ class LoginRestServlet(RestServlet):
             raise LoginError(401, "Invalid JWT", errcode=Codes.UNAUTHORIZED)
 
         user_id = UserID(user, self.hs.hostname).to_string()
+        device_id = login_submission.get("device_id")
+        initial_display_name = login_submission.get("initial_device_display_name")
 
         auth_handler = self.auth_handler
         registered_user_id = yield auth_handler.check_user_exists(user_id)
         if registered_user_id:
-            device_id = login_submission.get("device_id")
-            initial_display_name = login_submission.get("initial_device_display_name")
             device_id, access_token = yield self.registration_handler.register_device(
                 registered_user_id, device_id, initial_display_name
             )
@@ -342,11 +342,8 @@ class LoginRestServlet(RestServlet):
             user_id, access_token = (
                 yield self.registration_handler.register(localpart=user)
             )
-
-            device_id = login_submission.get("device_id")
-            initial_display_name = login_submission.get("initial_device_display_name")
             device_id, access_token = yield self.registration_handler.register_device(
-                registered_user_id, device_id, initial_display_name
+                user_id, device_id, initial_display_name
             )
 
             result = {
diff --git a/synapse/rest/consent/consent_resource.py b/synapse/rest/consent/consent_resource.py
index 624c42441e..1ddf9997ff 100644
--- a/synapse/rest/consent/consent_resource.py
+++ b/synapse/rest/consent/consent_resource.py
@@ -23,6 +23,8 @@ from six.moves import http_client
 import jinja2
 from jinja2 import TemplateNotFound
 
+from twisted.internet import defer
+
 from synapse.api.errors import NotFoundError, StoreError, SynapseError
 from synapse.config import ConfigError
 from synapse.http.server import (
@@ -139,7 +141,7 @@ class ConsentResource(DirectServeResource):
             else:
                 qualified_user_id = UserID(username, self.hs.hostname).to_string()
 
-            u = await self.store.get_user_by_id(qualified_user_id)
+            u = await defer.maybeDeferred(self.store.get_user_by_id, qualified_user_id)
             if u is None:
                 raise NotFoundError("Unknown user")
 
diff --git a/synctl b/synctl
index 30d751236f..794de99ea3 100755
--- a/synctl
+++ b/synctl
@@ -150,8 +150,9 @@ def main():
     parser.add_argument(
         "--no-daemonize",
         action="store_false",
+        dest="daemonize",
         help="Run synapse in the foreground for debugging. "
-        "Will work only if the daemonize option is not set in the config."
+        "Will work only if the daemonize option is not set in the config.",
     )
 
     options = parser.parse_args()
@@ -159,7 +160,7 @@ def main():
     if options.worker and options.all_processes:
         write('Cannot use "--worker" with "--all-processes"', stream=sys.stderr)
         sys.exit(1)
-    if options.no_daemonize and options.all_processes:
+    if not options.daemonize and options.all_processes:
         write('Cannot use "--no-daemonize" with "--all-processes"', stream=sys.stderr)
         sys.exit(1)
 
@@ -169,9 +170,8 @@ def main():
         write(
             "No config file found\n"
             "To generate a config file, run '%s -c %s --generate-config"
-            " --server-name=<server name> --report-stats=<yes/no>'\n" % (
-                " ".join(SYNAPSE), options.configfile,
-            ),
+            " --server-name=<server name> --report-stats=<yes/no>'\n"
+            % (" ".join(SYNAPSE), options.configfile),
             stream=sys.stderr,
         )
         sys.exit(1)
@@ -289,7 +289,7 @@ def main():
             # Check if synapse is already running
             if os.path.exists(pidfile) and pid_running(int(open(pidfile).read())):
                 abort("synapse.app.homeserver already running")
-            start(configfile, bool(options.no_daemonize))
+            start(configfile, bool(options.daemonize))
 
         for worker in workers:
             env = os.environ.copy()