Implement initial command permissions system
After our initial discussion on the matter (see #172) this is the system that we all seem to have agreed on. As a result, I have implemented a simple system which effectively implements permissions, while being extensible and tweakable so bot devs can decide what they want to do for permissions. As for default 'permissions', I'm not sure what the best approach would be here; bot devs are likely to implement their own permissions 'levels' and use those. I think the most we could do for now is add attributes to require certain users (by id) and certain roles (by id and possibly by name?) This would probably be the best option for now as it requires less work from us, nor do we know the *exact* approach bot devs want to take with permissions.
This commit is contained in:
12
src/Discord.Net.Commands/Attributes/FilterAttribute.cs
Normal file
12
src/Discord.Net.Commands/Attributes/FilterAttribute.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
public abstract class FilterAttribute : Attribute
|
||||
{
|
||||
public abstract void OnCommandExecuting(CommandExecutionContext context);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ namespace Discord.Commands
|
||||
public string Text { get; }
|
||||
public Module Module { get; }
|
||||
public IReadOnlyList<CommandParameter> Parameters { get; }
|
||||
public IReadOnlyList<FilterAttribute> Filters { get; }
|
||||
|
||||
internal Command(Module module, object instance, CommandAttribute attribute, MethodInfo methodInfo, string groupPrefix)
|
||||
{
|
||||
@@ -37,6 +38,7 @@ namespace Discord.Commands
|
||||
Synopsis = synopsis.Text;
|
||||
|
||||
Parameters = BuildParameters(methodInfo);
|
||||
Filters = BuildFilters(methodInfo);
|
||||
_action = BuildAction(methodInfo);
|
||||
}
|
||||
|
||||
@@ -52,6 +54,14 @@ namespace Discord.Commands
|
||||
if (!parseResult.IsSuccess)
|
||||
return ExecuteResult.FromError(parseResult);
|
||||
|
||||
var context = new CommandExecutionContext(this, parseResult, msg);
|
||||
foreach (FilterAttribute filter in Filters)
|
||||
{
|
||||
filter.OnCommandExecuting(context);
|
||||
if (context.Handled)
|
||||
return ExecuteResult.FromError(CommandError.InvalidPermissions, $"Permission check for {filter.GetType().FullName} failed");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _action.Invoke(msg, parseResult.Values);//Note: This code may need context
|
||||
@@ -63,6 +73,11 @@ namespace Discord.Commands
|
||||
}
|
||||
}
|
||||
|
||||
private IReadOnlyList<FilterAttribute> BuildFilters(MethodInfo methodInfo)
|
||||
{
|
||||
return methodInfo.GetCustomAttributes<FilterAttribute>().ToImmutableArray();
|
||||
}
|
||||
|
||||
private IReadOnlyList<CommandParameter> BuildParameters(MethodInfo methodInfo)
|
||||
{
|
||||
var parameters = methodInfo.GetParameters();
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
|
||||
//Execute
|
||||
Exception,
|
||||
InvalidPermissions
|
||||
}
|
||||
}
|
||||
|
||||
25
src/Discord.Net.Commands/Context/CommandExecutionContext.cs
Normal file
25
src/Discord.Net.Commands/Context/CommandExecutionContext.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Discord.Commands
|
||||
{
|
||||
public class CommandExecutionContext
|
||||
{
|
||||
public Command ExecutingCommand { get; internal set; }
|
||||
public ParseResult ParseResult { get; internal set; }
|
||||
public IMessage Message { get; internal set; }
|
||||
|
||||
public bool Handled { get; set; }
|
||||
|
||||
internal CommandExecutionContext(Command command, ParseResult parseResult, IMessage message)
|
||||
{
|
||||
ExecutingCommand = command;
|
||||
ParseResult = parseResult;
|
||||
Message = message;
|
||||
|
||||
Handled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user