diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index 067904ed..5a8f2e31 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -184,6 +184,21 @@ class Portal: return tgid not in self.filter_list return True + # endregion + # region Permission checks + + async def can_user_perform(self, user: 'u.User', event: str, default: int = 50) -> bool: + if user.is_admin: + return True + try: + await self.main_intent.get_power_levels(self.mxid) + except MatrixRequestError: + return False + return self.main_intent.state_store.has_power_level( + self.mxid, user.mxid, + event=f"net.maunium.telegram.{event}", + default=default) + # endregion # region Deduplication diff --git a/mautrix_telegram/web/provisioning/__init__.py b/mautrix_telegram/web/provisioning/__init__.py index 50795554..1ff81995 100644 --- a/mautrix_telegram/web/provisioning/__init__.py +++ b/mautrix_telegram/web/provisioning/__init__.py @@ -74,6 +74,8 @@ class ProvisioningAPI(AuthAPI): if not portal: return self.get_error_response(404, "portal_not_found", "Portal with given Matrix ID not found.") + user, _ = await self.get_user(request.query.get("user_id", None), expect_logged_in=None, + require_puppeting=False) return web.json_response({ "mxid": portal.mxid, "chat_id": get_peer_id(portal.peer), @@ -82,6 +84,7 @@ class ProvisioningAPI(AuthAPI): "about": portal.about, "username": portal.username, "megagroup": portal.megagroup, + "can_unbridge": (await portal.can_user_perform(user, "unbridge")) if user else False, }) async def get_portal_by_tgid(self, request: web.Request) -> web.Response: @@ -98,6 +101,8 @@ class ProvisioningAPI(AuthAPI): if not portal: return self.get_error_response(404, "portal_not_found", "Portal to given Telegram chat not found.") + user, _ = await self.get_user(request.query.get("user_id", None), expect_logged_in=None, + require_puppeting=False) return web.json_response({ "mxid": portal.mxid, "chat_id": get_peer_id(portal.peer), @@ -106,6 +111,7 @@ class ProvisioningAPI(AuthAPI): "about": portal.about, "username": portal.username, "megagroup": portal.megagroup, + "can_unbridge": (await portal.can_user_perform(user, "unbridge")) if user else False, }) async def connect_chat(self, request: web.Request) -> web.Response: diff --git a/mautrix_telegram/web/provisioning/spec.yaml b/mautrix_telegram/web/provisioning/spec.yaml index ed734bd2..6fe3bcc9 100644 --- a/mautrix_telegram/web/provisioning/spec.yaml +++ b/mautrix_telegram/web/provisioning/spec.yaml @@ -57,6 +57,11 @@ paths: required: true type: string pattern: "![^/]+" + - name: user_id + in: query + description: Optional Matrix user ID to check if the user has permissions to do bridging. + required: false + type: string /portal/{chat_id}: get: operationId: get_portal_by_tgid @@ -102,6 +107,11 @@ paths: required: true type: integer pattern: "-[0-9]+" + - name: user_id + in: query + description: Optional Matrix user ID to check if the user has permissions to do bridging. + required: false + type: string /portal/{room_id}/connect/{chat_id}: post: operationId: connect_portal @@ -829,6 +839,9 @@ definitions: type: string about: type: string + can_unbridge: + type: boolean + description: If a user ID was provided with the request, this will indicate whether or not the user can unbridge the room. AuthSuccess: type: object