Skip to content

add support for MSC4190 #175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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