Improve parameter permissions and fix RC permission check

This commit is contained in:
Aikar
2019-03-09 11:27:58 -05:00
parent d2754b99c9
commit 23dd046b8e
7 changed files with 112 additions and 66 deletions
@@ -788,7 +788,7 @@ public abstract class BaseCommand {
}
public boolean hasPermission(CommandIssuer issuer) {
return getRequiredPermissions().isEmpty() || getRequiredPermissions().stream().allMatch(permission -> manager.hasPermission(issuer, permission));
return this.manager.hasPermission(issuer, getRequiredPermissions());
}
public Set<String> getRequiredPermissions() {
@@ -29,7 +29,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
@SuppressWarnings({"WeakerAccess"})
@SuppressWarnings({"WeakerAccess", "unchecked"})
public class CommandExecutionContext<CEC extends CommandExecutionContext, I extends CommandIssuer> {
private final RegisteredCommand cmd;
private final CommandParameter param;
@@ -101,7 +101,6 @@ public class CommandExecutionContext<CEC extends CommandExecutionContext, I exte
final Object o = passedArgs.get(key);
for (Class<?> clazz : classes) {
if (clazz.isInstance(o)) {
//noinspection unchecked
return (T) o;
}
}
@@ -109,8 +108,8 @@ public class CommandExecutionContext<CEC extends CommandExecutionContext, I exte
return null;
}
public Set<String> getPermissions() {
return param.getPermissions();
public Set<String> getParameterPermissions() {
return param.getRequiredPermissions();
}
public boolean isOptional() {
@@ -48,14 +48,14 @@ import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("WeakerAccess")
public abstract class CommandManager <
public abstract class CommandManager<
IT,
I extends CommandIssuer,
FT,
MF extends MessageFormatter<FT>,
CEC extends CommandExecutionContext<CEC, I>,
CC extends ConditionContext<I>
> {
> {
/**
* This is a stack incase a command calls a command
@@ -113,7 +113,7 @@ public abstract class CommandManager <
public void setFormat(MessageType type, FT... colors) {
MF format = getFormat(type);
for (int i = 1; i <= colors.length; i++) {
format.setColor(i, colors[i-1]);
format.setColor(i, colors[i - 1]);
}
}
@@ -136,17 +136,23 @@ public abstract class CommandManager <
/**
* Gets the command contexts manager
*
* @return Command Contexts
*/
public abstract CommandContexts<?> getCommandContexts();
/**
* Gets the command completions manager
*
* @return Command Completions
*/
public abstract CommandCompletions<?> getCommandCompletions();
/** @deprecated Unstable API */ @Deprecated @UnstableAPI
/**
* @deprecated Unstable API
*/
@Deprecated
@UnstableAPI
public CommandHelp generateCommandHelp(@NotNull String command) {
verifyUnstableAPI("help");
CommandOperationContext context = getCurrentCommandOperationContext();
@@ -156,13 +162,21 @@ public abstract class CommandManager <
return generateCommandHelp(context.getCommandIssuer(), command);
}
/** @deprecated Unstable API */ @Deprecated @UnstableAPI
/**
* @deprecated Unstable API
*/
@Deprecated
@UnstableAPI
public CommandHelp generateCommandHelp(CommandIssuer issuer, @NotNull String command) {
verifyUnstableAPI("help");
return generateCommandHelp(issuer, obtainRootCommand(command));
}
/** @deprecated Unstable API */ @Deprecated @UnstableAPI
/**
* @deprecated Unstable API
*/
@Deprecated
@UnstableAPI
public CommandHelp generateCommandHelp() {
verifyUnstableAPI("help");
CommandOperationContext context = getCurrentCommandOperationContext();
@@ -173,29 +187,50 @@ public abstract class CommandManager <
return generateCommandHelp(context.getCommandIssuer(), this.obtainRootCommand(commandLabel));
}
/** @deprecated Unstable API */ @Deprecated @UnstableAPI
/**
* @deprecated Unstable API
*/
@Deprecated
@UnstableAPI
public CommandHelp generateCommandHelp(CommandIssuer issuer, RootCommand rootCommand) {
verifyUnstableAPI("help");
return new CommandHelp(this, rootCommand, issuer);
}
/** @deprecated Unstable API */ @Deprecated @UnstableAPI
/**
* @deprecated Unstable API
*/
@Deprecated
@UnstableAPI
public int getDefaultHelpPerPage() {
verifyUnstableAPI("help");
return defaultHelpPerPage;
}
/** @deprecated Unstable API */ @Deprecated @UnstableAPI
/**
* @deprecated Unstable API
*/
@Deprecated
@UnstableAPI
public void setDefaultHelpPerPage(int defaultHelpPerPage) {
verifyUnstableAPI("help");
this.defaultHelpPerPage = defaultHelpPerPage;
}
/** @deprecated Unstable API */ @Deprecated @UnstableAPI
/**
* @deprecated Unstable API
*/
@Deprecated
@UnstableAPI
public void setHelpFormatter(CommandHelpFormatter helpFormatter) {
this.helpFormatter = helpFormatter;
}
/** @deprecated Unstable API */ @Deprecated @UnstableAPI
/**
* @deprecated Unstable API
*/
@Deprecated
@UnstableAPI
public CommandHelpFormatter getHelpFormatter() {
return helpFormatter;
}
@@ -211,7 +246,9 @@ public abstract class CommandManager <
* @return boolean
*/
public abstract void registerCommand(BaseCommand command);
public abstract boolean hasRegisteredCommands();
public abstract boolean isCommandIssuer(Class<?> type);
// TODO: Change this to IT if we make a breaking change
@@ -221,6 +258,7 @@ public abstract class CommandManager <
/**
* Returns a Locales Manager to add and modify language tables for your commands.
*
* @return
*/
public abstract Locales getLocales();
@@ -253,16 +291,26 @@ public abstract class CommandManager <
/**
* Lets you add custom string replacements that can be applied to annotation values,
* to reduce duplication/repetition of common values such as permission nodes and command prefixes.
*
* <p>
* Any replacement registered starts with a %
*
* <p>
* So for ex @CommandPermission("%staff")
*
* @return Replacements Manager
*/
public CommandReplacements getCommandReplacements() {
return replacements;
}
public boolean hasPermission(CommandIssuer issuer, Set<String> permissions) {
for (String permission : permissions) {
if (!hasPermission(issuer, permission)) {
return false;
}
}
return true;
}
public boolean hasPermission(CommandIssuer issuer, String permission) {
if (permission == null || permission.isEmpty()) {
return true;
@@ -422,6 +470,7 @@ public abstract class CommandManager <
/**
* Gets a list of all currently supported languages for this manager.
* These locales will be automatically loaded from
*
* @return
*/
public Set<Locale> getSupportedLanguages() {
@@ -444,11 +493,11 @@ public abstract class CommandManager <
* The command manager will attempt to inject all fields in a command class that are annotated with
* {@link co.aikar.commands.annotation.Dependency} with the provided instance.
*
* @param clazz the class the injector should look for when injecting
* @param clazz the class the injector should look for when injecting
* @param instance the instance of the class that should be injected
* @throws IllegalStateException when there is already an instance for the provided class registered
*/
public <T> void registerDependency(Class<? extends T> clazz, T instance){
public <T> void registerDependency(Class<? extends T> clazz, T instance) {
registerDependency(clazz, clazz.getName(), instance);
}
@@ -457,12 +506,12 @@ public abstract class CommandManager <
* The command manager will attempt to inject all fields in a command class that are annotated with
* {@link co.aikar.commands.annotation.Dependency} with the provided instance.
*
* @param clazz the class the injector should look for when injecting
* @param key the key which needs to be present if that
* @param clazz the class the injector should look for when injecting
* @param key the key which needs to be present if that
* @param instance the instance of the class that should be injected
* @throws IllegalStateException when there is already an instance for the provided class registered
*/
public <T> void registerDependency(Class<? extends T> clazz, String key, T instance){
public <T> void registerDependency(Class<? extends T> clazz, String key, T instance) {
if (dependencies.containsKey(clazz, key)) {
throw new IllegalStateException("There is already an instance of " + clazz.getName() + " with the key " + key + " registered!");
}
@@ -514,6 +563,7 @@ public abstract class CommandManager <
public void enableUnstableAPI(String api) {
unstableAPIs.add(api);
}
void verifyUnstableAPI(String api) {
if (!unstableAPIs.contains(api)) {
throw new IllegalStateException("Using an unstable API that has not been enabled ( " + api + "). See https://acfunstable.emc.gs");
@@ -272,7 +272,7 @@ public class CommandParameter<CEC extends CommandExecutionContext<CEC, ? extends
this.conditions = conditions;
}
public Set<String> getPermissions() {
public Set<String> getRequiredPermissions() {
return permissions;
}
}
@@ -32,6 +32,7 @@ import co.aikar.locales.MessageKeyProvider;
@SuppressWarnings("WeakerAccess")
public enum MessageKeys implements MessageKeyProvider {
PERMISSION_DENIED,
PERMISSION_DENIED_PARAMETER,
ERROR_GENERIC_LOGGED,
UNKNOWN_COMMAND,
INVALID_SYNTAX,
@@ -58,6 +59,7 @@ public enum MessageKeys implements MessageKeyProvider {
;
private final MessageKey key = MessageKey.of("acf-core." + this.name().toLowerCase());
public MessageKey getMessageKey() {
return key;
}
@@ -227,10 +227,15 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
remainingRequired--;
}
Set<String> parameterPermissions = parameter.getRequiredPermissions();
if (args.isEmpty() && !(isLast && type == String[].class)) {
if (allowOptional && parameter.getDefaultValue() != null) {
args.add(parameter.getDefaultValue());
} else if (allowOptional && parameter.isOptional()) {
if (!this.manager.hasPermission(sender, parameterPermissions)) {
sender.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED_PARAMETER, "{param}", parameterName);
throw new InvalidCommandArgument(false);
}
Object value = parameter.isOptionalResolver() ? resolver.getContext(context) : null;
if (value == null && parameter.getClass().isPrimitive()) {
@@ -239,12 +244,16 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
//noinspection unchecked
this.manager.conditions.validateConditions(context, value);
passedArgs.put(parameterName, value);
//noinspection UnnecessaryContinue
continue;
} else if (requiresInput) {
scope.showSyntax(sender, this);
return null;
}
} else {
if (!this.manager.hasPermission(sender, parameterPermissions)) {
sender.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED_PARAMETER, "{param}", parameterName);
throw new InvalidCommandArgument(false);
}
}
if (parameter.getValues() != null) {
@@ -266,21 +275,8 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
"{valid}", ACFUtil.join(possible, ", "));
}
}
Object paramValue = resolver.getContext(context);
Set<String> parameterPermissions = parameter.getPermissions();
if (!parameter.isOptionalResolver() && parameterPermissions != null && !parameterPermissions.isEmpty()) {
if (allowOptional && parameter.isOptional()) {
for (String perm : parameterPermissions) {
if (!perm.isEmpty() && !sender.hasPermission(perm)) {
sender.sendMessage(MessageType.ERROR, MessageKeys.PERMISSION_DENIED);
return null;
}
}
} else {
throw new IllegalStateException("Using CommandPermission annotation on parameter that is not optional is useless and you should not do it.");
}
}
Object paramValue = resolver.getContext(context);
//noinspection unchecked
this.manager.conditions.validateConditions(context, paramValue);
@@ -290,10 +286,9 @@ public class RegisteredCommand<CEC extends CommandExecutionContext<CEC, ? extend
}
boolean hasPermission(CommandIssuer issuer) {
return (permission == null || permission.isEmpty() || scope.manager.hasPermission(issuer, permission)) && scope.hasPermission(issuer);
return this.manager.hasPermission(issuer, getRequiredPermissions());
}
/**
* @see #getRequiredPermissions()
* @deprecated
+25 -25
View File
@@ -19,28 +19,28 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
acf-core.permission_denied = I'm sorry, but you do not have permission to perform this command.
acf-core.error_generic_logged = An error occurred. This problem has been logged. Sorry for the inconvenience.
acf-core.unknown_command = Unknown Command, please type <c2>/help</c2>
acf-core.invalid_syntax = Usage: <c2>{command}</c2> <c3>{syntax}</c3>
acf-core.error_prefix = Error: {message}
acf-core.error_performing_command = I'm sorry, but there was an error performing this command.
acf-core.info_message = {message}
acf-core.please_specify_one_of = Error: Please specify one of (<c2>{valid}</c2>).
acf-core.must_be_a_number = Error: {num} must be a number.
acf-core.must_be_min_length = Error: Must be at least {min} characters long.
acf-core.must_be_max_length = Error: Must be at most {max} characters long.
acf-core.please_specify_at_most = Error: Please specify a value at most {max}.
acf-core.please_specify_at_least = Error: Please specify a value at least {min}.
acf-core.not_allowed_on_console = Error: Console may not execute this command.
acf-core.could_not_find_player = Error: Could not find a player by the name: <c2>{search}</c2>
acf-core.no_command_matched_search = No command matched <c2>{search}</c2>.
acf-core.help_page_information = - Showing page <c2>{page}</c2> of <c2>{totalpages}</c2> (<c3>{results}</c3> results).
acf-core.help_no_results = Error: No more results.
acf-core.help_header = <c3>=== </c3><c1>Showing help for </c1><c2>{commandprefix}{command}</c2><c3> ===</c3>
acf-core.help_format = <c1>{command}</c1> <c2>{parameters}</c2> <c3>{separator} {description}</c3>
acf-core.help_detailed_header = <c3>=== </c3><c1>Showing detailed help for </c1><c2>{commandprefix}{command}</c2><c3> ===</c3>
acf-core.help_detailed_command_format = <c1>{command}</c1> <c2>{parameters}</c2> <c3>{separator} {description}</c3>
acf-core.help_detailed_parameter_format = <c2>{name}</c2>: <c3>{description}</c3>
acf-core.help_search_header = <c3>=== </c3><c1>Search results for </c1><c2>{commandprefix}{command} {search}</c2><c3> ===</c3>
acf-core.permission_denied=I'm sorry, but you do not have permission to perform this command.
acf-core.permission_denied_parameter=I'm sorry, but you do not have permission to perform this command.
acf-core.error_generic_logged=An error occurred. This problem has been logged. Sorry for the inconvenience.
acf-core.unknown_command=Unknown Command, please type <c2>/help</c2>
acf-core.invalid_syntax=Usage: <c2>{command}</c2> <c3>{syntax}</c3>
acf-core.error_prefix=Error: {message}
acf-core.error_performing_command=I'm sorry, but there was an error performing this command.
acf-core.info_message={message}
acf-core.please_specify_one_of=Error: Please specify one of (<c2>{valid}</c2>).
acf-core.must_be_a_number=Error: {num} must be a number.
acf-core.must_be_min_length=Error: Must be at least {min} characters long.
acf-core.must_be_max_length=Error: Must be at most {max} characters long.
acf-core.please_specify_at_most=Error: Please specify a value at most {max}.
acf-core.please_specify_at_least=Error: Please specify a value at least {min}.
acf-core.not_allowed_on_console=Error: Console may not execute this command.
acf-core.could_not_find_player=Error: Could not find a player by the name: <c2>{search}</c2>
acf-core.no_command_matched_search=No command matched <c2>{search}</c2>.
acf-core.help_page_information=- Showing page <c2>{page}</c2> of <c2>{totalpages}</c2> (<c3>{results}</c3> results).
acf-core.help_no_results=Error: No more results.
acf-core.help_header=<c3>=== </c3><c1>Showing help for </c1><c2>{commandprefix}{command}</c2><c3> ===</c3>
acf-core.help_format=<c1>{command}</c1> <c2>{parameters}</c2> <c3>{separator} {description}</c3>
acf-core.help_detailed_header=<c3>=== </c3><c1>Showing detailed help for </c1><c2>{commandprefix}{command}</c2><c3> ===</c3>
acf-core.help_detailed_command_format=<c1>{command}</c1> <c2>{parameters}</c2> <c3>{separator} {description}</c3>
acf-core.help_detailed_parameter_format=<c2>{name}</c2>: <c3>{description}</c3>
acf-core.help_search_header=<c3>=== </c3><c1>Search results for </c1><c2>{commandprefix}{command} {search}</c2><c3> ===</c3>