Skip to content
Permalink
Browse files

Add support for CommandPermission annotation as parameter for permiss… (

#197)

…ions by Optional annotation

In the past we could not handle a permission in relation to the presence of an optional argument, it forced us to manage it in the body of the command, and could be repetitive and boring, note that it also works with the annotation Default
  • Loading branch information...
jdkeke142 authored and aikar committed Mar 9, 2019
1 parent d7477cb commit d2754b99c98e7d4640efe19437567f868b6ad994
@@ -7,17 +7,16 @@
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="acf-sponge" />
<module name="acf" />
<module name="acf-bukkit" />
<module name="acf-bungee" />
<module name="acf-core" />
<module name="acf-example" />
<module name="example-plugin" />
<module name="acf-paper" />
<module name="acf-jda" />
<module name="commands" />
<module name="acf-core" />
<module name="acf-paper" />
<module name="acf-sponge" />
<module name="acf-velocity" />
<module name="acf-bukkit" />
<module name="acf-bungee" />
<module name="example-plugin" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
@@ -27,9 +27,10 @@
import java.lang.reflect.Parameter;
import java.util.List;
import java.util.Map;
import java.util.Set;

@SuppressWarnings({"WeakerAccess"})
public class CommandExecutionContext <CEC extends CommandExecutionContext, I extends CommandIssuer> {
public class CommandExecutionContext<CEC extends CommandExecutionContext, I extends CommandIssuer> {
private final RegisteredCommand cmd;
private final CommandParameter param;
protected final I issuer;
@@ -69,7 +70,7 @@ public String getLastArg() {
}

public boolean isLastArg() {
return cmd.parameters.length -1 == index;
return cmd.parameters.length - 1 == index;
}

public int getNumParams() {
@@ -108,6 +109,10 @@ public Object getResolvedArg(Class<?>... classes) {
return null;
}

public Set<String> getPermissions() {
return param.getPermissions();
}

public boolean isOptional() {
return param.isOptional();
}
@@ -170,6 +175,7 @@ public Double getFlagValue(String flag, Number def) {

/**
* This method will not support annotation processors!! use getAnnotationValue or hasAnnotation
*
* @deprecated Use {@link #getAnnotationValue(Class)}
*/
@Deprecated
@@ -226,6 +232,7 @@ public int getIndex() {
public String joinArgs() {
return ACFUtil.join(args, " ");
}

public String joinArgs(String sep) {
return ACFUtil.join(args, sep);
}
@@ -23,6 +23,7 @@

package co.aikar.commands;

import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Conditions;
import co.aikar.commands.annotation.Default;
import co.aikar.commands.annotation.Description;
@@ -37,10 +38,13 @@
import co.aikar.commands.contexts.OptionalContextResolver;

import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class CommandParameter <CEC extends CommandExecutionContext<CEC, ? extends CommandIssuer>> {
public class CommandParameter<CEC extends CommandExecutionContext<CEC, ? extends CommandIssuer>> {
private final Parameter parameter;
private final Class<?> type;
private final String name;
@@ -49,6 +53,8 @@

private ContextResolver<?, CEC> resolver;
private boolean optional;
private Set<String> permissions = new HashSet<>();
private String permission;
private String description;
private String defaultValue;
private String syntax;
@@ -82,6 +88,7 @@ public CommandParameter(RegisteredCommand<CEC> command, Parameter param, int par
}

this.optional = annotations.hasAnnotation(param, Optional.class) || this.defaultValue != null || (isLast && type == String[].class);
this.permission = annotations.getAnnotationValue(param, CommandPermission.class, Annotations.REPLACEMENTS | Annotations.NO_EMPTY);
this.optionalResolver = isOptionalResolver(resolver);
this.requiresInput = !this.optional && !this.optionalResolver;
//noinspection unchecked
@@ -109,6 +116,7 @@ public CommandParameter(RegisteredCommand<CEC> command, Parameter param, int par
parseFlags(flags);
}
inheritContextFlags(command.scope);
this.computePermissions();
}

private void inheritContextFlags(BaseCommand scope) {
@@ -134,10 +142,17 @@ private void parseFlags(String flags) {
}
}

private void computePermissions() {
this.permissions.clear();
if (this.permission != null && !this.permission.isEmpty()) {
this.permissions.addAll(Arrays.asList(ACFPatterns.COMMA.split(this.permission)));
}
}

private boolean isOptionalResolver(ContextResolver<?, CEC> resolver) {
return resolver instanceof IssuerAwareContextResolver
|| resolver instanceof IssuerOnlyContextResolver
|| resolver instanceof OptionalContextResolver;
|| resolver instanceof IssuerOnlyContextResolver
|| resolver instanceof OptionalContextResolver;
}


@@ -256,4 +271,8 @@ public String getConditions() {
public void setConditions(String conditions) {
this.conditions = conditions;
}

public Set<String> getPermissions() {
return permissions;
}
}
@@ -226,11 +226,13 @@ void handleException(CommandIssuer sender, List<String> args, Exception e) {
if (requiresInput && remainingRequired > 0) {
remainingRequired--;
}

if (args.isEmpty() && !(isLast && type == String[].class)) {
if (allowOptional && parameter.getDefaultValue() != null) {
args.add(parameter.getDefaultValue());
} else if (allowOptional && parameter.isOptional()) {
Object value = parameter.isOptionalResolver() ? resolver.getContext(context) : null;

if (value == null && parameter.getClass().isPrimitive()) {
throw new IllegalStateException("Parameter " + parameter.getName() + " is primitive and does not support Optional.");
}
@@ -244,6 +246,7 @@ void handleException(CommandIssuer sender, List<String> args, Exception e) {
return null;
}
}

if (parameter.getValues() != null) {
String arg = !args.isEmpty() ? args.get(0) : "";

@@ -258,13 +261,27 @@ void handleException(CommandIssuer sender, List<String> args, Exception e) {
possible.add(s.toLowerCase());
}
}

if (!possible.contains(arg.toLowerCase())) {
throw new InvalidCommandArgument(MessageKeys.PLEASE_SPECIFY_ONE_OF,
"{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.");
}
}

//noinspection unchecked
this.manager.conditions.validateConditions(context, paramValue);
passedArgs.put(parameterName, paramValue);
@@ -30,11 +30,11 @@

/**
* Sets the permission required to perform this command.
*
* <p>
* Permission format will vary based on implementation platform
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER})
public @interface CommandPermission {
String value();
}

0 comments on commit d2754b9

Please sign in to comment.
You can’t perform that action at this time.