From 449b1bfe9ec7edd3b28f522437ca1de94294be29 Mon Sep 17 00:00:00 2001 From: Michael H Date: Sun, 13 May 2018 20:13:16 -0400 Subject: [PATCH] Make checks.py manageable from a permissions cog (#1547) * This starts setting up checks.py to handle managed permission overrides * missing else fix * don't bypass is_owner, ever * Modifies the predicates so that their inner functions are accesible from cogs without being a check * Update checks.py Safety for existing permissions.py cogs * block permissions cog from being unblocked by the permissions cog as a safety feature (really, co-owner exists at this point) * un mix the 2 PRs (*sigh*) * Update checks.py remove debug prints that got lost inshuffle --- redbot/core/checks.py | 92 ++++++++++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/redbot/core/checks.py b/redbot/core/checks.py index c5664ae0a..7dd1a3255 100644 --- a/redbot/core/checks.py +++ b/redbot/core/checks.py @@ -2,9 +2,26 @@ import discord from discord.ext import commands +async def check_overrides(ctx, *, level): + if await ctx.bot.is_owner(ctx.author): + return True + perm_cog = ctx.bot.get_cog('Permissions') + if not perm_cog or ctx.cog == perm_cog: + return None + # don't break if someone loaded a cog named + # permissions that doesn't implement this + func = getattr(perm_cog, 'check_overrides', None) + val = None if func is None else await func(ctx, level) + return val + + def is_owner(**kwargs): async def check(ctx): - return await ctx.bot.is_owner(ctx.author, **kwargs) + override = await check_overrides(ctx, level='owner') + return ( + override if override is not None + else await ctx.bot.is_owner(ctx.author, **kwargs) + ) return commands.check(check) @@ -15,14 +32,16 @@ async def check_permissions(ctx, perms): return False resolved = ctx.channel.permissions_for(ctx.author) - return all(getattr(resolved, name, None) == value for name, value in perms.items()) + return all( + getattr(resolved, name, None) == value + for name, value in perms.items() + ) -def mod_or_permissions(**perms): - async def predicate(ctx): - has_perms_or_is_owner = await check_permissions(ctx, perms) - if ctx.guild is None: - return has_perms_or_is_owner +async def is_mod_or_superior(ctx): + if ctx.guild is None: + return await ctx.bot.is_owner(ctx.author) + else: author = ctx.author settings = ctx.bot.db.guild(ctx.guild) mod_role_id = await settings.mod_role() @@ -31,25 +50,50 @@ def mod_or_permissions(**perms): mod_role = discord.utils.get(ctx.guild.roles, id=mod_role_id) admin_role = discord.utils.get(ctx.guild.roles, id=admin_role_id) - is_staff = mod_role in author.roles or admin_role in author.roles - is_guild_owner = author == ctx.guild.owner + return ( + await ctx.bot.is_owner(ctx.author) + or mod_role in author.roles + or admin_role in author.roles + or author == ctx.guild.owner + ) - return is_staff or has_perms_or_is_owner or is_guild_owner + +async def is_admin_or_superior(ctx): + if ctx.guild is None: + return await ctx.bot.is_owner(ctx.author) + else: + author = ctx.author + settings = ctx.bot.db.guild(ctx.guild) + admin_role_id = await settings.admin_role() + admin_role = discord.utils.get(ctx.guild.roles, id=admin_role_id) + + return ( + await ctx.bot.is_owner(ctx.author) + or admin_role in author.roles + or author == ctx.guild.owner + ) + + +def mod_or_permissions(**perms): + async def predicate(ctx): + override = await check_overrides(ctx, level='mod') + return ( + override if override is not None + else await check_permissions(ctx, perms) + or await is_mod_or_superior(ctx) + ) return commands.check(predicate) def admin_or_permissions(**perms): async def predicate(ctx): - has_perms_or_is_owner = await check_permissions(ctx, perms) - if ctx.guild is None: - return has_perms_or_is_owner - author = ctx.author - is_guild_owner = author == ctx.guild.owner - admin_role_id = await ctx.bot.db.guild(ctx.guild).admin_role() - admin_role = discord.utils.get(ctx.guild.roles, id=admin_role_id) - - return admin_role in author.roles or has_perms_or_is_owner or is_guild_owner + override = await check_overrides(ctx, level='admin') + return ( + override if override is not None + else await check_permissions(ctx, perms) + or await is_admin_or_superior(ctx) + ) return commands.check(predicate) @@ -58,7 +102,7 @@ def bot_in_a_guild(**kwargs): async def predicate(ctx): return len(ctx.bot.guilds) > 0 return commands.check(predicate) - + def guildowner_or_permissions(**perms): async def predicate(ctx): @@ -67,7 +111,11 @@ def guildowner_or_permissions(**perms): return has_perms_or_is_owner is_guild_owner = ctx.author == ctx.guild.owner - return is_guild_owner or has_perms_or_is_owner + override = await check_overrides(ctx, level='guildowner') + return ( + override if override is not None + else is_guild_owner or has_perms_or_is_owner + ) return commands.check(predicate) @@ -81,4 +129,4 @@ def admin(): def mod(): - return mod_or_permissions() \ No newline at end of file + return mod_or_permissions()