From 2d2fe86757896ef3c18ba7f2ed288e58504e7043 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Fri, 23 Feb 2018 12:07:42 +0200 Subject: [PATCH] Move all permissions to single object in config --- example-config.yaml | 28 ++++++++++------ mautrix_telegram/__main__.py | 1 + mautrix_telegram/config.py | 62 ++++++++++++++++++++++++++++++++++++ mautrix_telegram/matrix.py | 6 ++-- mautrix_telegram/portal.py | 2 +- mautrix_telegram/user.py | 10 ++---- 6 files changed, 88 insertions(+), 21 deletions(-) diff --git a/example-config.yaml b/example-config.yaml index ee68b25d..7ad0c7a6 100644 --- a/example-config.yaml +++ b/example-config.yaml @@ -87,20 +87,26 @@ bridge: # Allow logging in within Matrix. If false, the only way to log in is using the out-of-Matrix # login website (see appservice.public config section) allow_matrix_login: true + # Whether or not to allow creating portals from Telegram. + authless_relaybot_portals: true # The prefix for commands. Only required in non-management rooms. command_prefix: "!tg" - # Whitelist of user IDs that are allowed to use this bridge. Leave empty to disable. - # You can enter a domain without the localpart to allow all users from that homeserver to use the bridge. - whitelist: - - "internal.example.com" - - "@user:public.example.com" - - # Admins can do things like delete portal rooms. Here you must specify the exact MXID, domains - # are not accepted. - admins: - - "@admin:internal.example.com" + # Permissions for using the bridge. + # Permitted values: + # relaybot - Only use the bridge via the relaybot, no access to commands. + # full - Full access to use the bridge via relaybot or logging in with Telegram account. + # admin - Full access to use the bridge and some extra administration commands. + # Permitted keys: + # * - All Matrix users + # domain - All users on that homeserver + # mxid - Specific user + permissions: + "*": "relaybot" + "example.com": "full" + "public.example.com": "full" + "@admin:example.com": "admin" # Telegram config telegram: @@ -109,3 +115,5 @@ telegram: api_hash: tjyd5yge35lbodk1xwzw2jstp90k55qz # (Optional) Create your own bot at https://t.me/BotFather #bot_token: 123456789:ABCD-QBPd3VrWRhg623xYh07WUWErYA9eMI + +version: 1 diff --git a/mautrix_telegram/__main__.py b/mautrix_telegram/__main__.py index 2f01e1ac..9761db8c 100644 --- a/mautrix_telegram/__main__.py +++ b/mautrix_telegram/__main__.py @@ -56,6 +56,7 @@ args = parser.parse_args() config = Config(args.config, args.registration) config.load() +config.check_updates() if args.generate_registration: config.generate_registration() diff --git a/mautrix_telegram/config.py b/mautrix_telegram/config.py index ef93094e..6e2e8f8e 100644 --- a/mautrix_telegram/config.py +++ b/mautrix_telegram/config.py @@ -19,6 +19,7 @@ import random import string yaml = YAML() +yaml.indent(4) class DictWithRecursion: @@ -59,6 +60,31 @@ class DictWithRecursion: def __setitem__(self, key, value): self.set(key, value) + def _recursive_del(self, data, key): + if '.' in key: + key, next_key = key.split('.', 1) + if key not in data: + return + next_data = data[key] + self._recursive_del(next_data, next_key) + return + try: + del data[key] + except KeyError: + pass + + def delete(self, key, allow_recursion=True): + if allow_recursion and '.' in key: + self._recursive_del(self._data, key) + return + try: + del self._data[key] + except KeyError: + pass + + def __delitem__(self, key): + self.delete(key) + class Config(DictWithRecursion): def __init__(self, path, registration_path): @@ -82,6 +108,42 @@ class Config(DictWithRecursion): def _new_token(): return "".join(random.choice(string.ascii_lowercase + string.digits) for _ in range(64)) + def update_0_1(self): + permissions = self["bridge.permissions"] or {} + for entry in self["bridge.whitelist"] or []: + permissions[entry] = "full" + for entry in self["bridge.admins"] or []: + permissions[entry] = "admin" + self["bridge.permissions"] = permissions + del self["bridge.whitelist"] + del self["bridge.admins"] + self["version"] = 1 + + def check_updates(self): + if self.get("version", 0) == 0: + self.update_0_1() + else: + return + self.save() + + def _get_permissions(self, key): + level = self["bridge.permissions"].get(key, "") + admin = level == "admin" + whitelisted = level == "full" or admin + relaybot = level == "relaybot" or whitelisted + return relaybot, whitelisted, admin + + def get_permissions(self, mxid): + permissions = self["bridge.permissions"] or {} + if mxid in permissions: + return self._get_permissions(mxid) + + homeserver = mxid[mxid.index(":") + 1:] + if homeserver in permissions: + return self._get_permissions(homeserver) + + return self._get_permissions("*") + def generate_registration(self): homeserver = self["homeserver.domain"] diff --git a/mautrix_telegram/matrix.py b/mautrix_telegram/matrix.py index 25b2eb97..88c19c2f 100644 --- a/mautrix_telegram/matrix.py +++ b/mautrix_telegram/matrix.py @@ -119,7 +119,7 @@ class MatrixHandler: if not portal: return - if not user.whitelisted: + if not user.relaybot_whitelisted: await portal.main_intent.kick(room, user.mxid, "You are not whitelisted on this Telegram bridge.") return @@ -169,7 +169,7 @@ class MatrixHandler: is_command, text = self.is_command(message) sender = await User.get_by_mxid(sender).ensure_started() - if not sender.whitelisted: + if not sender.relaybot_whitelisted: return portal = Portal.get_by_mxid(room) @@ -177,7 +177,7 @@ class MatrixHandler: await portal.handle_matrix_message(sender, message, event_id) return - if message["msgtype"] != "m.text": + if not sender.whitelisted or message["msgtype"] != "m.text": return try: diff --git a/mautrix_telegram/portal.py b/mautrix_telegram/portal.py index c5bafc7c..deda5c78 100644 --- a/mautrix_telegram/portal.py +++ b/mautrix_telegram/portal.py @@ -462,7 +462,7 @@ class Portal: if p.Puppet.get_id_from_mxid(member) or member == self.main_intent.mxid: continue user = await u.User.get_by_mxid(member).ensure_started() - if (has_bot and user.whitelisted) or user.has_full_access: + if (has_bot and user.relaybot_whitelisted) or user.has_full_access: authenticated.append(user) return authenticated diff --git a/mautrix_telegram/user.py b/mautrix_telegram/user.py index 576108f2..605543b7 100644 --- a/mautrix_telegram/user.py +++ b/mautrix_telegram/user.py @@ -50,13 +50,9 @@ class User(AbstractUser): self.command_status = None - self.is_admin = self.mxid in config.get("bridge.admins", []) - - whitelist = config.get("bridge.whitelist", None) or [self.mxid] - self.whitelisted = not whitelist or self.mxid in whitelist - if not self.whitelisted: - homeserver = self.mxid[self.mxid.index(":") + 1:] - self.whitelisted = homeserver in whitelist + (self.relaybot_whitelisted, + self.whitelisted, + self.is_admin) = config.get_permissions(self.mxid) self.by_mxid[mxid] = self if tgid: