New permissions API. Deprecated old API until complete removal.

keep-around/a40088ecfe2344580f5e56783d29e1212c0fd597
Pingex aka Raphaël 9 years ago
parent a5938c6c0c
commit d8b76f3d01

@ -8,6 +8,7 @@ import java.util.function.Predicate;
/** /**
* Default behavior when a permissions provider doesn't return `true` or `false` * Default behavior when a permissions provider doesn't return `true` or `false`
*/ */
@Deprecated
public enum DefaultPermission implements Predicate<DefaultPermission.Tuple> public enum DefaultPermission implements Predicate<DefaultPermission.Tuple>
{ {
/** /**

@ -0,0 +1,80 @@
package net.pingex.dcf.permissions;
import net.pingex.dcf.commands.Context;
import net.pingex.dcf.commands.options.ICommandOption;
import net.pingex.dcf.core.Configuration;
import java.util.function.Predicate;
/**
* This class defines the default behavior of a command when checking for permissions.
*/
public class DefaultPermissionOption implements ICommandOption
{
private Value defaultValue;
public DefaultPermissionOption(Value defaultValue)
{
this.defaultValue = defaultValue;
}
public Value getDefaultValue()
{
return defaultValue;
}
@Override
public String getOptionName()
{
return "Default permission";
}
@Override
public String getOptionDescription()
{
return "This option defines the default behavior of a command when checking for permissions.";
}
/**
* Default behavior when a permissions provider doesn't return any value
*/
public enum Value implements Predicate<Context>
{
/**
* Everyone is allowed to run the command.
*/
EVERYONE(context -> true),
/**
* Only the guild owner is allowed to run the command.
*/
GUILD_OWNER(context -> !context.getChannel().isPrivate() && context.getUser().getID().equals(context.getChannel().getGuild().getOwnerID())),
/**
* Only the bot owner is allowed to run the command.
*/
BOT_OWNER(context -> context.getUser().getID().equals(Configuration.BOT_OWNER)),
/**
* Guild Owner x Bot Owner
*/
ANY_OWNER(context -> GUILD_OWNER.test(context) || BOT_OWNER.test(context)),
/**
* Nobody is allowed to run the command
*/
NONE(context -> false);
Value(Predicate<Context> predicate)
{
this.predicate = predicate;
}
private Predicate<Context> predicate;
@Override
public boolean test(Context o)
{
return predicate.test(o);
}
}
}

@ -0,0 +1,86 @@
package net.pingex.dcf.permissions;
import net.pingex.dcf.commands.Context;
import net.pingex.dcf.commands.audit.AuditResult;
import net.pingex.dcf.commands.audit.IAuditComponentProvider;
import net.pingex.dcf.permissions.audit.DefaultPermissionCheck;
import net.pingex.dcf.permissions.audit.UserGlobalCheck;
import net.pingex.dcf.permissions.audit.UserGuildCheck;
import net.pingex.dcf.permissions.audit.UserGuildRoleCheck;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
/**
* This class is used to check whether an user can run a command.
*/
public class PermissionCheck implements IAuditComponentProvider
{
private static final ICommandPermissionsProvider CURRENT_PROVIDER = new DefaultPermissionsProvider();
private static final Set<IAuditComponentProvider> SUB_CHECKS = new TreeSet<>(Comparator.comparingInt(IAuditComponentProvider::priority));
static
{
SUB_CHECKS.addAll(Arrays.asList(
new DefaultPermissionCheck(),
new UserGlobalCheck(getProvider()),
new UserGuildCheck(getProvider()),
new UserGuildRoleCheck(getProvider())
));
}
/**
* Get provider used to check for permissions.
*/
public static ICommandPermissionsProvider getProvider()
{
return CURRENT_PROVIDER;
}
@Override
public AuditResult doAudit(Context context)
{
AuditResult.Builder globalResult = new AuditResult.Builder();
for(IAuditComponentProvider i : SUB_CHECKS)
{
AuditResult interResult = i.doAudit(context);
globalResult.appendAuditResult(i, interResult);
// Check opcode has not been written yet and interResult has opcode either FAIL or PASS.
if(globalResult.getOpcode() == null && (interResult.getOpcode() == AuditResult.ResultCode.FAIL || interResult.getOpcode() == AuditResult.ResultCode.PASS))
{
globalResult.setOpcode(interResult.getOpcode());
globalResult.setMessage(interResult.getMessage());
}
}
if(globalResult.getOpcode() == null)
{
globalResult.setOpcode(globalResult.getSubAuditsResults().get(globalResult.getSubAuditsResults().size()-1).getValue().getOpcode());
globalResult.setMessage(globalResult.getSubAuditsResults().get(globalResult.getSubAuditsResults().size()-1).getValue().getMessage());
}
return globalResult.build();
}
@Override
public String name()
{
return "Permission check";
}
@Override
public String description()
{
return "Checks whether an user can run a command.";
}
@Override
public int priority()
{
return 10;
}
}

@ -9,16 +9,15 @@ import sx.blah.discord.handle.obj.IUser;
/** /**
* Landing class of this package. * Landing class of this package.
*/ */
@Deprecated
public class PermissionsHandler public class PermissionsHandler
{ {
private static final ICommandPermissionsProvider CURRENT_PROVIDER = new DefaultPermissionsProvider();
/** /**
* Get provider used to check permissions. * Get provider used to check permissions.
*/ */
public static ICommandPermissionsProvider getProvider() public static ICommandPermissionsProvider getProvider()
{ {
return CURRENT_PROVIDER; return PermissionCheck.getProvider();
} }
/** /**
@ -40,19 +39,19 @@ public class PermissionsHandler
// First check: user permission for guild, skipped if DM // First check: user permission for guild, skipped if DM
if(targetGuild != null) if(targetGuild != null)
{ {
Boolean canUserGuildRun = CURRENT_PROVIDER.validateUser(targetGuild, targetUser, command); Boolean canUserGuildRun = getProvider().validateUser(targetGuild, targetUser, command);
if(canUserGuildRun != null) return canUserGuildRun; if(canUserGuildRun != null) return canUserGuildRun;
} }
// Second check: user permission globally // Second check: user permission globally
Boolean canUserRun = CURRENT_PROVIDER.validateUser(null, targetUser, command); Boolean canUserRun = getProvider().validateUser(null, targetUser, command);
if(canUserRun != null) return canUserRun; if(canUserRun != null) return canUserRun;
// Third check: user role permissions, skipped if DM // Third check: user role permissions, skipped if DM
if(targetGuild != null && targetGuild.getRolesForUser(targetUser) != null) if(targetGuild != null && targetGuild.getRolesForUser(targetUser) != null)
for(IRole i : targetGuild.getRolesForUser(targetUser)) for(IRole i : targetGuild.getRolesForUser(targetUser))
{ {
Boolean canRoleRun = CURRENT_PROVIDER.validateGroup(i, command); Boolean canRoleRun = getProvider().validateGroup(i, command);
if(canRoleRun != null) return canRoleRun; if(canRoleRun != null) return canRoleRun;
} }

@ -0,0 +1,46 @@
package net.pingex.dcf.permissions.audit;
import net.pingex.dcf.commands.Context;
import net.pingex.dcf.commands.audit.AuditResult;
import net.pingex.dcf.commands.audit.IAuditComponentProvider;
import net.pingex.dcf.commands.options.ICommandOption;
import net.pingex.dcf.permissions.DefaultPermissionOption;
import java.util.Optional;
/**
* This class checks permission against a default behavior defined in a command.
*/
public class DefaultPermissionCheck implements IAuditComponentProvider
{
@Override
public AuditResult doAudit(Context context)
{
Optional<ICommandOption> option = context.getCommand().getOptions().stream().filter(i -> i instanceof DefaultPermissionOption).findFirst();
if(!option.isPresent())
return new AuditResult(AuditResult.ResultCode.NOOP, "No default permission defined.");
if(((DefaultPermissionOption) option.get()).getDefaultValue().test(context))
return new AuditResult(AuditResult.ResultCode.PASS);
else
return new AuditResult(AuditResult.ResultCode.FAIL, "Default policy denied access to command.");
}
@Override
public String name()
{
return "Default permission check";
}
@Override
public String description()
{
return "Checks against a default permission option defined in a command.";
}
@Override
public int priority()
{
return 5;
}
}

@ -0,0 +1,57 @@
package net.pingex.dcf.permissions.audit;
import net.pingex.dcf.commands.Context;
import net.pingex.dcf.commands.audit.AuditResult;
import net.pingex.dcf.commands.audit.IAuditComponentProvider;
import net.pingex.dcf.permissions.ICommandPermissionsProvider;
/**
* This class checks permission against a rule defined for a specific user globally.
*/
public class UserGlobalCheck implements IAuditComponentProvider
{
/**
* Permissions provider to use
*/
private ICommandPermissionsProvider provider;
/**
* Provider for this object to use
* @param provider Permissions provider this object will use
*/
public UserGlobalCheck(ICommandPermissionsProvider provider)
{
this.provider = provider;
}
@Override
public AuditResult doAudit(Context context)
{
Boolean returnedValue = provider.validateUser(null, context.getUser(), context.getCommand());
if(returnedValue == null) // No rule for user
return new AuditResult(AuditResult.ResultCode.NOOP, "No global rule for this user.");
else if(returnedValue) // Rule says yes
return new AuditResult(AuditResult.ResultCode.PASS);
else // Rule says no
return new AuditResult(AuditResult.ResultCode.FAIL, "Global rule denied access for this user.");
}
@Override
public String name()
{
return "User global check";
}
@Override
public String description()
{
return "Checks against a global rule defined for a specific user.";
}
@Override
public int priority()
{
return 2;
}
}

@ -0,0 +1,61 @@
package net.pingex.dcf.permissions.audit;
import net.pingex.dcf.commands.Context;
import net.pingex.dcf.commands.audit.AuditResult;
import net.pingex.dcf.commands.audit.IAuditComponentProvider;
import net.pingex.dcf.permissions.ICommandPermissionsProvider;
/**
* This class checks permission against a rule defined for a specific user in a specific guild.
*/
public class UserGuildCheck implements IAuditComponentProvider
{
/**
* Permissions provider to use
*/
private ICommandPermissionsProvider provider;
/**
* Provider for this object to use
* @param provider Permissions provider this object will use
*/
public UserGuildCheck(ICommandPermissionsProvider provider)
{
this.provider = provider;
}
@Override
public AuditResult doAudit(Context context)
{
// Check for guild
if(context.getChannel().getGuild() == null)
return new AuditResult(AuditResult.ResultCode.NOOP, "This channel is not part of a guild.");
Boolean returnedValue = provider.validateUser(context.getChannel().getGuild(), context.getUser(), context.getCommand());
if(returnedValue == null) // No rule for user in this guild
return new AuditResult(AuditResult.ResultCode.NOOP, "No guild rule for this user.");
else if(returnedValue) // Rule says yes
return new AuditResult(AuditResult.ResultCode.PASS);
else // Rule says no
return new AuditResult(AuditResult.ResultCode.FAIL, "Guild rule denied access for this user.");
}
@Override
public String name()
{
return "User vs guild check";
}
@Override
public String description()
{
return "Checks against a guild rule defined for an user.";
}
@Override
public int priority()
{
return 1;
}
}

@ -0,0 +1,69 @@
package net.pingex.dcf.permissions.audit;
import net.pingex.dcf.commands.Context;
import net.pingex.dcf.commands.audit.AuditResult;
import net.pingex.dcf.commands.audit.IAuditComponentProvider;
import net.pingex.dcf.permissions.ICommandPermissionsProvider;
import sx.blah.discord.handle.obj.IRole;
/**
* This class checks permission against a rule defined for a specific role in a guild.
*/
public class UserGuildRoleCheck implements IAuditComponentProvider
{
/**
* Permissions provider to use
*/
private ICommandPermissionsProvider provider;
/**
* Provider for this object to use
* @param provider Permissions provider this object will use
*/
public UserGuildRoleCheck(ICommandPermissionsProvider provider)
{
this.provider = provider;
}
@Override
public AuditResult doAudit(Context context)
{
// Check for guild
if(context.getChannel().getGuild() == null)
return new AuditResult(AuditResult.ResultCode.NOOP, "This channel is not part of a guild.");
if(context.getChannel().getGuild().getRolesForUser(context.getUser()) != null) // User has roles
for(IRole i : context.getChannel().getGuild().getRolesForUser(context.getUser()))
{
Boolean returnedQuery = provider.validateGroup(i, context.getCommand());
if(returnedQuery != null)
{
if(returnedQuery) return new AuditResult(AuditResult.ResultCode.PASS);
else return new AuditResult(AuditResult.ResultCode.FAIL, "Role rule denied access for this user.");
}
}
else // User has no role
return new AuditResult(AuditResult.ResultCode.NOOP, "No role defined for this user.");
// No rule for any role
return new AuditResult(AuditResult.ResultCode.NOOP, "No rule defined for any role this user has.");
}
@Override
public String name()
{
return "Guild role check";
}
@Override
public String description()
{
return "Checks permission against a rule defined for a specific role in a guild.";
}
@Override
public int priority()
{
return 3;
}
}

@ -0,0 +1,4 @@
/**
* This package contains all sub-checks for PermissionCheck.
*/
package net.pingex.dcf.permissions.audit;