mirror of
https://github.com/aikar/commands.git
synced 2026-05-31 06:11:55 +00:00
Improve parameter permissions and fix RC permission check
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user