Skip to content

Commit

Permalink
Allow enabling sliding sync per-user (#17393)
Browse files Browse the repository at this point in the history
Based on #17392
  • Loading branch information
erikjohnston authored Jul 5, 2024
1 parent 57538eb commit 8e9e6f1
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 6 deletions.
1 change: 1 addition & 0 deletions changelog.d/17393.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow enabling sliding sync per-user.
1 change: 1 addition & 0 deletions docs/admin_api/experimental_features.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This API allows a server administrator to enable or disable some experimental fe
basis. The currently supported features are:
- [MSC3881](https://github.com/matrix-org/matrix-spec-proposals/pull/3881): enable remotely toggling push notifications
for another client
- [MSC3575](https://github.com/matrix-org/matrix-spec-proposals/pull/3575): enable experimental sliding sync support

To use it, you will need to authenticate by providing an `access_token`
for a server admin: see [Admin API](../usage/administration/admin_api/).
Expand Down
18 changes: 17 additions & 1 deletion synapse/api/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# [This file includes modifications made by New Vector Limited]
#
#
from typing import Optional, Tuple
from typing import TYPE_CHECKING, Optional, Tuple

from typing_extensions import Protocol

Expand All @@ -28,6 +28,9 @@
from synapse.http.site import SynapseRequest
from synapse.types import Requester

if TYPE_CHECKING:
from synapse.rest.admin.experimental_features import ExperimentalFeature

# guests always get this device id.
GUEST_DEVICE_ID = "guest_device"

Expand Down Expand Up @@ -87,6 +90,19 @@ async def get_user_by_req(
AuthError if access is denied for the user in the access token
"""

async def get_user_by_req_experimental_feature(
self,
request: SynapseRequest,
feature: "ExperimentalFeature",
allow_guest: bool = False,
allow_expired: bool = False,
allow_locked: bool = False,
) -> Requester:
"""Like `get_user_by_req`, except also checks if the user has access to
the experimental feature. If they don't returns a 404 unrecognized
request.
"""

async def validate_appservice_can_control_user_id(
self, app_service: ApplicationService, user_id: str
) -> None:
Expand Down
29 changes: 29 additions & 0 deletions synapse/api/auth/internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
Codes,
InvalidClientTokenError,
MissingClientTokenError,
UnrecognizedRequestError,
)
from synapse.http.site import SynapseRequest
from synapse.logging.opentracing import active_span, force_tracing, start_active_span
Expand All @@ -38,8 +39,10 @@
from .base import BaseAuth

if TYPE_CHECKING:
from synapse.rest.admin.experimental_features import ExperimentalFeature
from synapse.server import HomeServer


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -106,6 +109,32 @@ async def get_user_by_req(
parent_span.set_tag("appservice_id", requester.app_service.id)
return requester

async def get_user_by_req_experimental_feature(
self,
request: SynapseRequest,
feature: "ExperimentalFeature",
allow_guest: bool = False,
allow_expired: bool = False,
allow_locked: bool = False,
) -> Requester:
try:
requester = await self.get_user_by_req(
request,
allow_guest=allow_guest,
allow_expired=allow_expired,
allow_locked=allow_locked,
)
if await self.store.is_feature_enabled(requester.user.to_string(), feature):
return requester

raise UnrecognizedRequestError(code=404)
except (AuthError, InvalidClientTokenError):
if feature.is_globally_enabled(self.hs.config):
# If its globally enabled then return the auth error
raise

raise UnrecognizedRequestError(code=404)

@cancellable
async def _wrapped_get_user_by_req(
self,
Expand Down
28 changes: 28 additions & 0 deletions synapse/api/auth/msc3861_delegated.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
OAuthInsufficientScopeError,
StoreError,
SynapseError,
UnrecognizedRequestError,
)
from synapse.http.site import SynapseRequest
from synapse.logging.context import make_deferred_yieldable
Expand All @@ -48,6 +49,7 @@
from synapse.util.caches.cached_call import RetryOnExceptionCachedCall

if TYPE_CHECKING:
from synapse.rest.admin.experimental_features import ExperimentalFeature
from synapse.server import HomeServer

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -245,6 +247,32 @@ async def get_user_by_req(

return requester

async def get_user_by_req_experimental_feature(
self,
request: SynapseRequest,
feature: "ExperimentalFeature",
allow_guest: bool = False,
allow_expired: bool = False,
allow_locked: bool = False,
) -> Requester:
try:
requester = await self.get_user_by_req(
request,
allow_guest=allow_guest,
allow_expired=allow_expired,
allow_locked=allow_locked,
)
if await self.store.is_feature_enabled(requester.user.to_string(), feature):
return requester

raise UnrecognizedRequestError(code=404)
except (AuthError, InvalidClientTokenError):
if feature.is_globally_enabled(self.hs.config):
# If its globally enabled then return the auth error
raise

raise UnrecognizedRequestError(code=404)

async def get_user_by_access_token(
self,
token: str,
Expand Down
3 changes: 3 additions & 0 deletions synapse/rest/admin/experimental_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,13 @@ class ExperimentalFeature(str, Enum):
"""

MSC3881 = "msc3881"
MSC3575 = "msc3575"

def is_globally_enabled(self, config: "HomeServerConfig") -> bool:
if self is ExperimentalFeature.MSC3881:
return config.experimental.msc3881_enabled
if self is ExperimentalFeature.MSC3575:
return config.experimental.msc3575_enabled

assert_never(self)

Expand Down
15 changes: 10 additions & 5 deletions synapse/rest/client/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
)
from synapse.http.site import SynapseRequest
from synapse.logging.opentracing import trace_with_opname
from synapse.rest.admin.experimental_features import ExperimentalFeature
from synapse.types import JsonDict, Requester, StreamToken
from synapse.types.rest.client import SlidingSyncBody
from synapse.util import json_decoder
Expand Down Expand Up @@ -673,7 +674,9 @@ def __init__(self, hs: "HomeServer"):
)

async def on_GET(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
requester = await self.auth.get_user_by_req(request, allow_guest=True)
requester = await self.auth.get_user_by_req_experimental_feature(
request, allow_guest=True, feature=ExperimentalFeature.MSC3575
)
user = requester.user
device_id = requester.device_id

Expand Down Expand Up @@ -873,7 +876,10 @@ def __init__(self, hs: "HomeServer"):
self.event_serializer = hs.get_event_client_serializer()

async def on_POST(self, request: SynapseRequest) -> Tuple[int, JsonDict]:
requester = await self.auth.get_user_by_req(request, allow_guest=True)
requester = await self.auth.get_user_by_req_experimental_feature(
request, allow_guest=True, feature=ExperimentalFeature.MSC3575
)

user = requester.user
device_id = requester.device_id

Expand Down Expand Up @@ -1051,6 +1057,5 @@ async def encode_rooms(
def register_servlets(hs: "HomeServer", http_server: HttpServer) -> None:
SyncRestServlet(hs).register(http_server)

if hs.config.experimental.msc3575_enabled:
SlidingSyncRestServlet(hs).register(http_server)
SlidingSyncE2eeRestServlet(hs).register(http_server)
SlidingSyncRestServlet(hs).register(http_server)
SlidingSyncE2eeRestServlet(hs).register(http_server)

0 comments on commit 8e9e6f1

Please sign in to comment.