diff --git a/redbot/cogs/reports/reports.py b/redbot/cogs/reports/reports.py index 61b000897..7a1d4bdc6 100644 --- a/redbot/cogs/reports/reports.py +++ b/redbot/cogs/reports/reports.py @@ -316,7 +316,7 @@ class Reports(commands.Cog): self.tunnel_store[k]["msgs"] = msgs @commands.guild_only() - @checks.mod_or_permissions(manage_members=True) + @checks.mod_or_permissions(manage_roles=True) @report.command(name="interact") async def response(self, ctx, ticket_number: int): """Open a message tunnel. diff --git a/redbot/core/commands/requires.py b/redbot/core/commands/requires.py index b5b4b8859..ab5dca108 100644 --- a/redbot/core/commands/requires.py +++ b/redbot/core/commands/requires.py @@ -281,12 +281,14 @@ class Requires: if isinstance(user_perms, dict): self.user_perms: Optional[discord.Permissions] = discord.Permissions.none() + _validate_perms_dict(user_perms) self.user_perms.update(**user_perms) else: self.user_perms = user_perms if isinstance(bot_perms, dict): self.bot_perms: discord.Permissions = discord.Permissions.none() + _validate_perms_dict(bot_perms) self.bot_perms.update(**bot_perms) else: self.bot_perms = bot_perms @@ -311,6 +313,7 @@ class Requires: if user_perms is None: func.requires.user_perms = None else: + _validate_perms_dict(user_perms) func.requires.user_perms.update(**user_perms) return func @@ -584,6 +587,7 @@ def bot_has_permissions(**perms: bool): if asyncio.iscoroutinefunction(func): func.__requires_bot_perms__ = perms else: + _validate_perms_dict(perms) func.requires.bot_perms.update(**perms) return func @@ -595,6 +599,8 @@ def has_permissions(**perms: bool): This check can be overridden by rules. """ + if perms is None: + raise TypeError("Must provide at least one keyword argument to has_permissions") return Requires.get_decorator(None, perms) @@ -666,3 +672,20 @@ class _IntKeyDict(Dict[int, _T]): if not isinstance(key, int): raise TypeError("Keys must be of type `int`") return super().__setitem__(key, value) + + +def _validate_perms_dict(perms: Dict[str, bool]) -> None: + for perm, value in perms.items(): + try: + attr = getattr(discord.Permissions, perm) + except AttributeError: + attr = None + + if attr is None or not isinstance(attr, property): + # We reject invalid permissions + raise TypeError(f"Unknown permission name '{perm}'") + + if value is not True: + # We reject any permission not specified as 'True', since this is the only value which + # makes practical sense. + raise TypeError(f"Permission {perm} may only be specified as 'True', not {value}")