Skip to content

Commit

Permalink
add support for MSC4190
Browse files Browse the repository at this point in the history
  • Loading branch information
surakin committed Jan 10, 2025
1 parent bba5542 commit 8fe3c9e
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 12 deletions.
3 changes: 2 additions & 1 deletion mautrix/appservice/appservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,13 @@ def __init__(
state_store: ASStateStore = None,
aiohttp_params: dict = None,
ephemeral_events: bool = False,
msc4190: bool = False,
encryption_events: bool = False,
default_ua: str = HTTPAPI.default_ua,
default_http_retry_count: int = 0,
connection_limit: int | None = None,
) -> None:
super().__init__(ephemeral_events=ephemeral_events, encryption_events=encryption_events)
super().__init__(ephemeral_events=ephemeral_events, msc4190=msc4190, encryption_events=encryption_events)
self.server = server
self.domain = domain
self.id = id
Expand Down
3 changes: 3 additions & 0 deletions mautrix/appservice/as_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class AppServiceServerMixin:

hs_token: str
ephemeral_events: bool
msc4190: bool
encryption_events: bool
synchronous_handlers: bool

Expand All @@ -51,6 +52,7 @@ class AppServiceServerMixin:
def __init__(
self,
ephemeral_events: bool = False,
msc4190: bool = False,
encryption_events: bool = False,
log: logging.Logger | None = None,
hs_token: str | None = None,
Expand All @@ -65,6 +67,7 @@ def __init__(
self.otk_handler = None
self.device_list_handler = None
self.ephemeral_events = ephemeral_events
self.msc4190 = msc4190
self.encryption_events = encryption_events
self.synchronous_handlers = False

Expand Down
1 change: 1 addition & 0 deletions mautrix/bridge/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def prepare_appservice(self) -> None:
tls_key=self.config.get("appservice.tls_key", None),
bot_localpart=self.config["appservice.bot_username"],
ephemeral_events=self.config["appservice.ephemeral_events"],
msc4190=self.config["appservice.msc4190"],
encryption_events=self.config["bridge.encryption.appservice"],
default_ua=HTTPAPI.default_ua,
default_http_retry_count=default_http_retry_count,
Expand Down
4 changes: 4 additions & 0 deletions mautrix/bridge/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def do_update(self, helper: ConfigUpdateHelper) -> None:
copy("appservice.hs_token")

copy("appservice.ephemeral_events")
copy("appservice.msc4190")

copy("bridge.management_room_text.welcome")
copy("bridge.management_room_text.welcome_connected")
Expand Down Expand Up @@ -241,3 +242,6 @@ def generate_registration(self) -> None:
if self["appservice.ephemeral_events"]:
self._registration["de.sorunome.msc2409.push_ephemeral"] = True
self._registration["push_ephemeral"] = True

if self["appservice.msc4190"]:
self._registration["io.element.msc4190"] = True
33 changes: 22 additions & 11 deletions mautrix/bridge/e2ee.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ async def decrypt(self, evt: EncryptedEvent, wait_session_timeout: int = 5) -> M

async def start(self) -> None:
flows = await self.client.get_login_flows()
if not flows.supports_type(LoginType.APPSERVICE):
if not self.az.msc4190 and not flows.supports_type(LoginType.APPSERVICE):
self.log.critical(
"Encryption enabled in config, but homeserver does not support appservice login"
)
Expand All @@ -261,16 +261,27 @@ async def start(self) -> None:
device_id = await self.crypto_store.get_device_id()
if device_id:
self.log.debug(f"Found device ID in database: {device_id}")
# We set the API token to the AS token here to authenticate the appservice login
# It'll get overridden after the login
self.client.api.token = self.az.as_token
await self.client.login(
login_type=LoginType.APPSERVICE,
device_name=self.device_name,
device_id=device_id,
store_access_token=True,
update_hs_url=False,
)

if self.az.msc4190:
if not device_id:
self.log.debug("Creating bot device with msc4190")
self.client.api.token = self.az.as_token
await self.client.create_device_msc4190(
device_id=device_id,
initial_display_name=self.device_name
)
else:
# We set the API token to the AS token here to authenticate the appservice login
# It'll get overridden after the login
self.client.api.token = self.az.as_token
await self.client.login(
login_type=LoginType.APPSERVICE,
device_name=self.device_name,
device_id=device_id,
store_access_token=True,
update_hs_url=False,
)

await self.crypto.load()
if not device_id:
await self.crypto_store.put_device_id(self.client.device_id)
Expand Down
17 changes: 17 additions & 0 deletions mautrix/client/api/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from __future__ import annotations

import secrets

from mautrix.api import Method, Path
from mautrix.errors import MatrixResponseError
from mautrix.types import (
Expand Down Expand Up @@ -117,6 +119,21 @@ async def login(
self.api.base_url = base_url.rstrip("/")
return resp_data

async def create_device_msc4190(
self,
device_id: str,
initial_display_name: str
) -> None:
"""
Create a Device for a user of the homeserver using appservice interface defined in MSC4190
"""
if len(device_id) == 0:
device_id = DeviceID(secrets.token_urlsafe(10))
self.api.as_user_id = self.mxid
await self.api.request(Method.PUT, Path.v3.devices[device_id], { "display_name": initial_display_name})
self.api.as_device_id = device_id
self.device_id = device_id

async def logout(self, clear_access_token: bool = True) -> None:
"""
Invalidates an existing access token, so that it can no longer be used for authorization.
Expand Down

0 comments on commit 8fe3c9e

Please sign in to comment.