Effective removal of the old permissions system.
parent
b505e79d2a
commit
6d4ac31d79
@ -1,63 +0,0 @@
|
||||
package net.pingex.dcf.permissions;
|
||||
|
||||
import net.pingex.dcf.core.Configuration;
|
||||
import sx.blah.discord.handle.obj.IGuild;
|
||||
import sx.blah.discord.handle.obj.IUser;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Default behavior when a permissions provider doesn't return `true` or `false`
|
||||
*/
|
||||
@Deprecated
|
||||
public enum DefaultPermission implements Predicate<DefaultPermission.Tuple>
|
||||
{
|
||||
/**
|
||||
* Everyone is allowed to run the command.
|
||||
*/
|
||||
EVERYONE(tuple -> true),
|
||||
|
||||
/**
|
||||
* Only the guild owner is allowed to run the command.
|
||||
*/
|
||||
GUILD_OWNER(tuple -> tuple.guild != null && tuple.user.getID().equals(tuple.guild.getOwnerID())),
|
||||
|
||||
/**
|
||||
* Only the bot owner is allowed to run the command.
|
||||
*/
|
||||
BOT_OWNER(tuple -> tuple.user.getID().equals(Configuration.BOT_OWNER)),
|
||||
|
||||
/**
|
||||
* Guild Owner x Bot Owner
|
||||
*/
|
||||
ANY_OWNER(tuple -> GUILD_OWNER.test(tuple) || BOT_OWNER.test(tuple)),
|
||||
|
||||
/**
|
||||
* Nobody is allowed to run the command
|
||||
*/
|
||||
NONE(tuple -> false);
|
||||
|
||||
DefaultPermission(Predicate<Tuple> predicate)
|
||||
{
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
private Predicate<Tuple> predicate;
|
||||
|
||||
@Override
|
||||
public boolean test(Tuple o)
|
||||
{
|
||||
return predicate.test(o);
|
||||
}
|
||||
|
||||
public static class Tuple
|
||||
{
|
||||
IUser user;
|
||||
IGuild guild;
|
||||
|
||||
public Tuple(IUser user, IGuild guild)
|
||||
{
|
||||
this.user = user;
|
||||
this.guild = guild;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,269 +0,0 @@
|
||||
package net.pingex.dcf.permissions;
|
||||
|
||||
import net.pingex.dcf.commands.Command;
|
||||
import net.pingex.dcf.commands.CommandRegistry;
|
||||
import net.pingex.dcf.commands.IWithCommands;
|
||||
import net.pingex.dcf.util.ArgumentParser;
|
||||
import net.pingex.dcf.util.DiscordInteractionsUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import sx.blah.discord.handle.impl.events.MessageReceivedEvent;
|
||||
import sx.blah.discord.handle.obj.IGuild;
|
||||
import sx.blah.discord.handle.obj.IRole;
|
||||
import sx.blah.discord.handle.obj.IUser;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Commands for the permissions package.
|
||||
*/
|
||||
public class PermissionsCommands implements IWithCommands
|
||||
{
|
||||
@Override
|
||||
public Set<Command> getCommands()
|
||||
{
|
||||
return new HashSet<>(Arrays.asList(
|
||||
isAllowedCommand, setUser
|
||||
));
|
||||
}
|
||||
|
||||
private static final Command isAllowedCommand =
|
||||
new Command.Builder("perm:canRun")
|
||||
.description("Tells whether target user is allowed to run the command.")
|
||||
.enabled(true)
|
||||
.usage("Command <User#Disc|ID|me> <Guild|ID|this|*> [verbose]")
|
||||
.defaultPermission(DefaultPermission.BOT_OWNER)
|
||||
.build(PermissionsCommands::isAllowedImpl);
|
||||
|
||||
private static void isAllowedImpl(MessageReceivedEvent event, List<String> arguments)
|
||||
{
|
||||
// Parameters
|
||||
Command target = null;
|
||||
IUser userToLookup = null;
|
||||
boolean verbose = false;
|
||||
IGuild targetGuild = null;
|
||||
ICommandPermissionsProvider provider = PermissionsHandler.getProvider();
|
||||
|
||||
// Argchk size
|
||||
if(arguments.size() != 3 && arguments.size() != 4)
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "Invalid arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Argchk#1 - valid command
|
||||
Optional<Command> uncheckedTarget = CommandRegistry.getCommandOrAliasByName(arguments.get(0));
|
||||
if(!uncheckedTarget.isPresent()) // Command existence
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "Target command not found.");
|
||||
return;
|
||||
}
|
||||
else target = uncheckedTarget.get();
|
||||
|
||||
// Argchk#2 - uid OR username#1234 OR "me"
|
||||
if(arguments.get(1).equalsIgnoreCase("me")) userToLookup = event.getMessage().getAuthor(); // me
|
||||
else // Anything else
|
||||
try
|
||||
{
|
||||
Optional<IUser> uncheckedUser = ArgumentParser.checkParseUsernameOrID(arguments.get(1), event.getClient());
|
||||
|
||||
if(uncheckedUser.isPresent()) userToLookup = uncheckedUser.get();
|
||||
else
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "User not found.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch(ArgumentParser.ParserException e)
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "Invalid arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Argchk#3 - Guild
|
||||
if(arguments.get(2).equalsIgnoreCase("this"))
|
||||
try
|
||||
{
|
||||
targetGuild = event.getMessage().getGuild(); // this
|
||||
}
|
||||
catch(UnsupportedOperationException ignored) // DM
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "`this` is not supported outside a guild.");
|
||||
return;
|
||||
}
|
||||
else if(arguments.get(2).equals("*")) targetGuild = null; // Global - ~NOP
|
||||
else // Parse Name/ID
|
||||
{
|
||||
Optional<IGuild> uncheckedGuild = ArgumentParser.checkParseGuildOrID(arguments.get(2), event.getClient());
|
||||
if(uncheckedGuild.isPresent()) targetGuild = uncheckedGuild.get();
|
||||
else
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "Guild not found.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Argchk#4 - verbosity
|
||||
if(arguments.size() == 4) verbose = true;
|
||||
|
||||
// ========================================
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder()
|
||||
.append("**Permission walkthrough**\n")
|
||||
.append("```\n");
|
||||
|
||||
builder.append("User: ").append(userToLookup.getName()).append("#").append(userToLookup.getDiscriminator()).append("\n");
|
||||
builder.append("UID: ").append(userToLookup.getID()).append("\n");
|
||||
if(targetGuild != null)
|
||||
{
|
||||
builder.append("Guild: ").append(targetGuild.getName()).append("\n");
|
||||
builder.append("Guild ID: ").append(targetGuild.getID()).append("\n");
|
||||
}
|
||||
builder.append("Command: ").append(target.getName()).append("\n");
|
||||
|
||||
builder.append("\n");
|
||||
|
||||
if(targetGuild != null)
|
||||
builder.append("UID Guild check: ").append(booleanToString(provider.validateUser(targetGuild, userToLookup, target))).append("\n");
|
||||
builder.append("UID Global check: ").append(booleanToString(provider.validateUser(null, userToLookup, target))).append("\n");
|
||||
|
||||
if(targetGuild != null)
|
||||
{
|
||||
builder.append("Role check:\n");
|
||||
for(IRole i : targetGuild.getRolesForUser(userToLookup))
|
||||
builder.append("> ").append(StringUtils.rightPad(i.getName() + ":", 16))
|
||||
.append(booleanToString(provider.validateGroup(i, target))).append("\n");
|
||||
}
|
||||
|
||||
builder.append("Default behavior: ")
|
||||
.append(booleanToString(target.getDefaultPermission().test(new DefaultPermission.Tuple(userToLookup, targetGuild))))
|
||||
.append(" (").append(target.getDefaultPermission().toString()).append(")").append("\n");
|
||||
|
||||
builder.append("```");
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), builder.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
StringBuilder builder = new StringBuilder()
|
||||
.append("**Permission summary**\n")
|
||||
.append("```\n");
|
||||
|
||||
builder.append("User: ").append(userToLookup.getName()).append("#").append(userToLookup.getDiscriminator()).append("\n");
|
||||
builder.append("UID: ").append(userToLookup.getID()).append("\n");
|
||||
if(targetGuild != null)
|
||||
{
|
||||
builder.append("Guild: ").append(targetGuild.getName()).append("\n");
|
||||
builder.append("Guild ID: ").append(targetGuild.getID()).append("\n");
|
||||
}
|
||||
builder.append("Command: ").append(target.getName()).append("\n");
|
||||
builder.append("Has Access: ").append(PermissionsHandler.canRunCommand(userToLookup, targetGuild, target) ? "Yes" : "No").append("\n");
|
||||
|
||||
builder.append("```");
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), builder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quick helper function to convert a bool to a String.
|
||||
* @param input Input boolean, can be `null`
|
||||
* @return "Grant" => `true`, "Deny" => `false`, "N/A" => `null`
|
||||
*/
|
||||
private static String booleanToString(Boolean input)
|
||||
{
|
||||
return input != null ? (input ? "Grant" : "Deny") : "N/A";
|
||||
}
|
||||
|
||||
private static final Command setUser =
|
||||
new Command.Builder("perm:setUser")
|
||||
.description("Overrides an user's permission to run a command.")
|
||||
.enabled(true)
|
||||
.usage("Command <User#Disc|ID> <Guild|ID|this|*> <true|false|null>")
|
||||
.defaultPermission(DefaultPermission.BOT_OWNER)
|
||||
.build(PermissionsCommands::setUserImpl);
|
||||
|
||||
private static void setUserImpl(MessageReceivedEvent event, List<String> arguments)
|
||||
{
|
||||
// Parameters
|
||||
IUser targetUser;
|
||||
IGuild targetGuild = null;
|
||||
Command targetCommand;
|
||||
Boolean action;
|
||||
ICommandPermissionsProvider provider = PermissionsHandler.getProvider();
|
||||
|
||||
// Argchk size
|
||||
if(arguments.size() != 3 && arguments.size() != 4)
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "Invalid arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Argchk#1 Command
|
||||
Optional<Command> uncheckedCommand = CommandRegistry.getCommandOrAliasByName(arguments.get(0));
|
||||
if(!uncheckedCommand.isPresent()) // Command existence
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "Target command not found.");
|
||||
return;
|
||||
}
|
||||
else targetCommand = uncheckedCommand.get();
|
||||
|
||||
// Argchk#2 User#Disc/UID
|
||||
try
|
||||
{
|
||||
Optional<IUser> uncheckedUser = ArgumentParser.checkParseUsernameOrID(arguments.get(1), event.getClient());
|
||||
|
||||
if(uncheckedUser.isPresent()) targetUser = uncheckedUser.get();
|
||||
else
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "User not found.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch(ArgumentParser.ParserException e)
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "Invalid arguments.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Argchk#3 Guild
|
||||
if(arguments.get(2).equalsIgnoreCase("this"))
|
||||
try
|
||||
{
|
||||
targetGuild = event.getMessage().getGuild(); // this
|
||||
}
|
||||
catch(UnsupportedOperationException ignored) // DM
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "`this` is not supported outside a guild.");
|
||||
return;
|
||||
}
|
||||
else if(arguments.get(2).equals("*")) targetGuild = null; // Global - ~NOP
|
||||
else // Parse Name/ID
|
||||
{
|
||||
Optional<IGuild> uncheckedGuild = ArgumentParser.checkParseGuildOrID(arguments.get(2), event.getClient());
|
||||
if(uncheckedGuild.isPresent()) targetGuild = uncheckedGuild.get();
|
||||
else
|
||||
{
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), "Guild not found.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Argchk#4 true/false/null
|
||||
action = (Boolean) ArgumentParser.parse(Boolean.class, arguments.size() > 3 ? arguments.get(3) : null);
|
||||
|
||||
// ========================================
|
||||
|
||||
StringBuilder builder = new StringBuilder("**Changes summary**\n");
|
||||
builder.append("```\n");
|
||||
builder.append("User: ").append(targetUser.getName()).append("#").append(targetUser.getDiscriminator()).append("\n");
|
||||
builder.append("UID: ").append(targetUser.getID()).append("\n");
|
||||
builder.append("Guild: ").append(targetGuild != null ? targetGuild.getName() : "[GLOBAL]").append("\n");
|
||||
builder.append("Guild ID: ").append(targetGuild != null ? targetGuild.getID() : "N/A").append("\n");
|
||||
builder.append("Command: ").append(targetCommand.getName()).append("\n");
|
||||
builder.append("New perm: ").append(booleanToString(action)).append("\n");
|
||||
builder.append("```\n");
|
||||
|
||||
provider.setUserPermission(targetGuild, targetUser, targetCommand, action);
|
||||
builder.append("Changes OK");
|
||||
DiscordInteractionsUtil.sendMessage(event.getMessage().getChannel(), builder.toString());
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
package net.pingex.dcf.permissions;
|
||||
|
||||
import net.pingex.dcf.commands.Command;
|
||||
import sx.blah.discord.handle.obj.IGuild;
|
||||
import sx.blah.discord.handle.obj.IMessage;
|
||||
import sx.blah.discord.handle.obj.IRole;
|
||||
import sx.blah.discord.handle.obj.IUser;
|
||||
|
||||
/**
|
||||
* Landing class of this package.
|
||||
*/
|
||||
@Deprecated
|
||||
public class PermissionsHandler
|
||||
{
|
||||
/**
|
||||
* Get provider used to check permissions.
|
||||
*/
|
||||
public static ICommandPermissionsProvider getProvider()
|
||||
{
|
||||
return PermissionCheck.getProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether someone can run requested command.
|
||||
*
|
||||
* The validator will successively test the following until something other than `null` is returned.
|
||||
* - Individual user permission on the guild using {@code ICommandPermissionsProvider.validateUser()}
|
||||
* - Individual user permission globally using {@code ICommandPermissionsProvider.validateUser()}
|
||||
* - The user's role list using {@code ICommandPermissionsProvider.validateGroup()}
|
||||
* - Default behavior included in a Command object
|
||||
*
|
||||
* @param targetUser User to check against
|
||||
* @param targetGuild Guild to check against
|
||||
* @param command Requested command, as parsed by {@code CommandHandler}
|
||||
* @return `true` if request is granted, `false` if denied.
|
||||
*/
|
||||
public static boolean canRunCommand(IUser targetUser, IGuild targetGuild, Command command)
|
||||
{
|
||||
// First check: user permission for guild, skipped if DM
|
||||
if(targetGuild != null)
|
||||
{
|
||||
Boolean canUserGuildRun = getProvider().validateUser(targetGuild, targetUser, command);
|
||||
if(canUserGuildRun != null) return canUserGuildRun;
|
||||
}
|
||||
|
||||
// Second check: user permission globally
|
||||
Boolean canUserRun = getProvider().validateUser(null, targetUser, command);
|
||||
if(canUserRun != null) return canUserRun;
|
||||
|
||||
// Third check: user role permissions, skipped if DM
|
||||
if(targetGuild != null && targetGuild.getRolesForUser(targetUser) != null)
|
||||
for(IRole i : targetGuild.getRolesForUser(targetUser))
|
||||
{
|
||||
Boolean canRoleRun = getProvider().validateGroup(i, command);
|
||||
if(canRoleRun != null) return canRoleRun;
|
||||
}
|
||||
|
||||
// Fourth check: default behavior
|
||||
return command.getDefaultPermission().test(new DefaultPermission.Tuple(targetUser, targetGuild));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to the other {@code canRunCommand()} method.
|
||||
* @param request Incoming message
|
||||
* @param command Command to check against
|
||||
* @return `true` if request is granted, `false` if denied.
|
||||
*/
|
||||
public static boolean canRunCommand(IMessage request, Command command)
|
||||
{
|
||||
IUser requestAuthor = request.getAuthor();
|
||||
IGuild originatedGuild;
|
||||
try
|
||||
{
|
||||
originatedGuild = request.getGuild();
|
||||
}
|
||||
catch(UnsupportedOperationException uoe) // DM
|
||||
{
|
||||
originatedGuild = null;
|
||||
}
|
||||
return canRunCommand(requestAuthor, originatedGuild, command);
|
||||
}
|
||||
}
|
Reference in New Issue