Even more migrations to mautrix-python

This commit is contained in:
Tulir Asokan
2019-07-19 21:36:21 +03:00
parent eef498d47a
commit d4e3956941
20 changed files with 215 additions and 337 deletions
+13 -11
View File
@@ -13,27 +13,30 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from abc import abstractmethod
from typing import Optional
from aiohttp import web
from abc import abstractmethod
import abc
import asyncio
import logging
from aiohttp import web
from telethon.errors import *
from mautrix.bridge import OnlyLoginSelf, InvalidAccessToken
from ...commands.telegram.auth import enter_password
from ...util import format_duration, ignore_coro
from ...puppet import Puppet, PuppetError
from ...puppet import Puppet
from ...user import User
class AuthAPI(abc.ABC):
log = logging.getLogger("mau.web.auth") # type: logging.Logger
log: logging.Logger = logging.getLogger("mau.web.auth")
loop: asyncio.AbstractEventLoop
def __init__(self, loop: asyncio.AbstractEventLoop):
self.loop = loop # type: asyncio.AbstractEventLoop
self.loop = loop
@abstractmethod
def get_login_response(self, status: int = 200, state: str = "", username: str = "",
@@ -55,15 +58,14 @@ class AuthAPI(abc.ABC):
error="You have already logged in with your Matrix "
"account.", errcode="already-logged-in")
resp = await puppet.switch_mxid(token.strip(), user.mxid)
if resp == PuppetError.OnlyLoginSelf:
try:
await puppet.switch_mxid(token.strip(), user.mxid)
except OnlyLoginSelf:
return self.get_mx_login_response(status=403, errcode="only-login-self",
error="You can only log in as your own Matrix user.")
elif resp == PuppetError.InvalidAccessToken:
except InvalidAccessToken:
return self.get_mx_login_response(status=401, errcode="invalid-access-token",
error="Failed to verify access token.")
assert resp == PuppetError.Success, "Encountered an unhandled PuppetError."
return self.get_mx_login_response(mxid=user.mxid, status=200, state="logged-in")
async def post_matrix_password(self, user: User, password: str) -> web.Response:
+25 -27
View File
@@ -13,17 +13,21 @@
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from aiohttp import web
from typing import Awaitable, Callable, Dict, Optional, Tuple, TYPE_CHECKING
import asyncio
import logging
import json
from aiohttp import web
from telethon.utils import get_peer_id, resolve_id
from telethon.tl.types import ChatForbidden, ChannelForbidden, TypeChat
from mautrix_appservice import AppService, MatrixRequestError, IntentError
from ...types import MatrixUserID, TelegramID
from mautrix.appservice import AppService
from mautrix.errors import MatrixRequestError, IntentError
from mautrix.types import UserID
from ...types import TelegramID
from ...user import User
from ...portal import Portal
from ...util import ignore_coro
@@ -35,16 +39,19 @@ if TYPE_CHECKING:
class ProvisioningAPI(AuthAPI):
log = logging.getLogger("mau.web.provisioning") # type: logging.Logger
log: logging.Logger = logging.getLogger("mau.web.provisioning")
secret: str
az: AppService
context: 'Context'
app: web.Application
def __init__(self, context: "Context") -> None:
super().__init__(context.loop)
self.secret = context.config["appservice.provisioning.shared_secret"] # type: str
self.az = context.az # type: AppService
self.context = context # type: Context
self.secret = context.config["appservice.provisioning.shared_secret"]
self.az = context.az
self.context = context
self.app = web.Application(loop=context.loop, middlewares=[self.error_middleware]
) # type: web.Application
self.app = web.Application(loop=context.loop, middlewares=[self.error_middleware])
portal_prefix = "/portal/{mxid:![^/]+}"
self.app.router.add_route("GET", f"{portal_prefix}", self.get_portal_by_mxid)
@@ -76,18 +83,7 @@ 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),
"peer_type": portal.peer_type,
"title": portal.title,
"about": portal.about,
"username": portal.username,
"megagroup": portal.megagroup,
"can_unbridge": (await portal.can_user_perform(user, "unbridge")) if user else False,
})
return await self._get_portal_response(UserID(request.query.get("user_id", "")), portal)
async def get_portal_by_tgid(self, request: web.Request) -> web.Response:
err = self.check_authorization(request)
@@ -103,8 +99,10 @@ 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 await self._get_portal_response(UserID(request.query.get("user_id", "")), portal)
async def _get_portal_response(self, user_id: UserID, portal: Portal) -> web.Response:
user, _ = await self.get_user(user_id, expect_logged_in=None, require_puppeting=False)
return web.json_response({
"mxid": portal.mxid,
"chat_id": get_peer_id(portal.peer),
@@ -364,7 +362,8 @@ class ProvisioningAPI(AuthAPI):
async def bridge_info(self, request: web.Request) -> web.Response:
return web.json_response({
"relaybot_username": self.context.bot.username if self.context.bot is not None else None,
"relaybot_username": (self.context.bot.username
if self.context.bot is not None else None),
}, status=200)
@staticmethod
@@ -430,7 +429,7 @@ class ProvisioningAPI(AuthAPI):
except json.JSONDecodeError:
return None
async def get_user(self, mxid: MatrixUserID, expect_logged_in: Optional[bool] = False,
async def get_user(self, mxid: Optional[UserID], expect_logged_in: Optional[bool] = False,
require_puppeting: bool = True, require_user: bool = True
) -> Tuple[Optional[User], Optional[web.Response]]:
if not mxid:
@@ -459,8 +458,7 @@ class ProvisioningAPI(AuthAPI):
expect_logged_in: Optional[bool] = False,
require_puppeting: bool = False,
want_data: bool = True,
) -> (Tuple[Optional[Dict],
Optional[User],
) -> (Tuple[Optional[Dict], Optional[User],
Optional[web.Response]]):
err = self.check_authorization(request)
if err is not None:
+17 -12
View File
@@ -14,16 +14,18 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
from typing import Optional
from aiohttp import web
from mako.template import Template
import pkg_resources
import asyncio
import logging
import random
import string
import time
from ...types import MatrixUserID
from mako.template import Template
from aiohttp import web
import pkg_resources
from mautrix.types import UserID
from ...util import sign_token, verify_token
from ...user import User
from ...puppet import Puppet
@@ -31,20 +33,23 @@ from ..common import AuthAPI
class PublicBridgeWebsite(AuthAPI):
log = logging.getLogger("mau.web.public") # type: logging.Logger
log: logging.Logger = logging.getLogger("mau.web.public")
secret_key: str
login: Template
mx_login: Template
app: web.Application
def __init__(self, loop: asyncio.AbstractEventLoop):
super().__init__(loop)
self.secret_key = "".join(
random.choice(string.ascii_lowercase + string.digits) for _ in range(64)) # type: str
self.secret_key = "".join(random.choices(string.ascii_lowercase + string.digits, k=64))
self.login = Template(pkg_resources.resource_string(
"mautrix_telegram", "web/public/login.html.mako")) # type: Template
"mautrix_telegram", "web/public/login.html.mako"))
self.mx_login = Template(pkg_resources.resource_string(
"mautrix_telegram", "web/public/matrix-login.html.mako")) # type: Template
"mautrix_telegram", "web/public/matrix-login.html.mako"))
self.app = web.Application(loop=loop) # type: web.Application
self.app = web.Application(loop=loop)
self.app.router.add_route("GET", "/login", self.get_login)
self.app.router.add_route("POST", "/login", self.post_login)
self.app.router.add_route("GET", "/matrix-login", self.get_matrix_login)
@@ -59,11 +64,11 @@ class PublicBridgeWebsite(AuthAPI):
"expiry": int(time.time()) + expires_in,
})
def verify_token(self, token: str, endpoint: str = "/login") -> Optional[MatrixUserID]:
def verify_token(self, token: str, endpoint: str = "/login") -> Optional[UserID]:
token = verify_token(self.secret_key, token)
if token and (token.get("expiry", 0) > int(time.time()) and
token.get("endpoint", None) == endpoint):
return MatrixUserID(token.get("mxid", None))
return UserID(token.get("mxid", None))
return None
async def get_login(self, request: web.Request) -> web.Response: