Repository: matrix-org/synapse

Issue:
[20200921] Expose forced-on E2EE through a /versions flag or something
Capabilities are probably wrong for this, and we don't yet have an info API. For speed, I'd recommend a `/versions` flag of `io.element.e2ee_forced` for clients to check.



Discussion:
Release blocker tag because it needs to make it into a release before the end of September, though ideally the implementation would be done much sooner to unblock @turt2live 
From discussions elsewhere, this seems related to the [`encryption_enabled_by_default_for_room_type` flag](https://github.com/matrix-org/synapse/blob/837293c314b47e988fe9532115476a6536cd6406/docs/sample_config.yaml#L2176-L2191), which controls whether newly created local rooms use E2EE by default or not.

This essentially has three values:
* All rooms get created with E2EE by default.
* All private rooms get created with E2EE by default.
* The defaults are unmodified.

We could expose that in the configuration, but unfortunately it seems more than just a True/False value.
this is where I wish we had an info endpoint :( 

Can we do two flags to represent all and private? If both are false/not present then it's safe to assume the server won't manipulate the behaviour.

Something like:

```
{
  "io.element.forced_e2e.everywhere": true,
  "io.element.forced_e2e.private_only": true
}
```

`io.element.forced_e2e.everywhere` when true implicitly means `io.element.forced_e2e.private_only` is enabled. Similarly, when `io.element.forced_e2e.everywhere` is missing then it is implied false, which forces the client to look at `io.element.forced_e2e.private_only`

This should make the server implementation something along the lines of (I don't know python well):
```
if config['encryption_enabled_by_default_for_room_type'] != 'off':
    unstable_features["io.element.forced_e2e.everywhere" if config['encryption_enabled_by_default_for_room_type'] == 'all' else "io.element.forced_e2e.private_only"] = True
```
@turt2live Yes, we can do that -- would it make more sense to have a separate flag for private and public? Something like:

```json
{
    "io.element.forced_e2e.public": true,
    "io.element.forced_e2e.private": true,
}
```

It is a bit less implicit.
yea, that should be fine. The client will know what presets its about to use anyways :D 

Resolving patch:
diff --git a/synapse/rest/client/versions.py b/synapse/rest/client/versions.py
--- a/synapse/rest/client/versions.py
+++ b/synapse/rest/client/versions.py
@@ -19,6 +19,7 @@
 import logging
 import re
 
+from synapse.api.constants import RoomCreationPreset
 from synapse.http.servlet import RestServlet
 
 logger = logging.getLogger(__name__)
@@ -31,6 +32,20 @@ def __init__(self, hs):
         super(VersionsRestServlet, self).__init__()
         self.config = hs.config
 
+        # Calculate these once since they shouldn't change after start-up.
+        self.e2ee_forced_public = (
+            RoomCreationPreset.PUBLIC_CHAT
+            in self.config.encryption_enabled_by_default_for_room_presets
+        )
+        self.e2ee_forced_private = (
+            RoomCreationPreset.PRIVATE_CHAT
+            in self.config.encryption_enabled_by_default_for_room_presets
+        )
+        self.e2ee_forced_trusted_private = (
+            RoomCreationPreset.TRUSTED_PRIVATE_CHAT
+            in self.config.encryption_enabled_by_default_for_room_presets
+        )
+
     def on_GET(self, request):
         return (
             200,
@@ -62,6 +77,10 @@ def on_GET(self, request):
                     "org.matrix.msc2432": True,
                     # Implements additional endpoints as described in MSC2666
                     "uk.half-shot.msc2666": True,
+                    # Whether new rooms will be set to encrypted or not (based on presets).
+                    "io.element.e2ee_forced.public": self.e2ee_forced_public,
+                    "io.element.e2ee_forced.private": self.e2ee_forced_private,
+                    "io.element.e2ee_forced.trusted_private": self.e2ee_forced_trusted_private,
                 },
             },
         )


Test patch: