private void OnCommandSourcesChanged() { AsyncHelper.RunSync(async() => { await m_CommandSources.DisposeAllAsync(); try { m_CommandSources = m_Options.Value.CreateCommandSources(m_ServiceProvider); } catch (ObjectDisposedException) { // https://github.com/openmod/OpenMod/issues/61 m_CommandSources = new List <ICommandSource>(); } var commands = new List <ICommandRegistration>(); foreach (var sources in m_CommandSources) { commands.AddRange(await sources.GetCommandsAsync()); } foreach (var registration in commands) { var permission = m_CommandPermissionBuilder.GetPermission(registration, commands); m_PermissionRegistry.RegisterPermission(registration.Component, permission, description: $"Grants access to the {registration.Id} command.", defaultGrant: PermissionGrantResult.Default); if (registration.PermissionRegistrations == null) { continue; } foreach (var permissionRegistration in registration.PermissionRegistrations) { m_PermissionRegistry.RegisterPermission(permissionRegistration.Owner, $"{permission}.{permissionRegistration.Permission}", permissionRegistration.Description, permissionRegistration.DefaultGrant); } } var commandsData = await m_CommandDataStore.GetRegisteredCommandsAsync() ?? new RegisteredCommandsData(); commandsData.Commands ??= new List <RegisteredCommandData>(); foreach (var command in commands .Where(d => !commandsData.Commands.Any(c => c.Id.Equals(d.Id, StringComparison.OrdinalIgnoreCase)))) { commandsData.Commands.Add(CreateDefaultCommandData(command)); } await m_CommandDataStore.SetRegisteredCommandsAsync(commandsData); }); }
protected override async Task OnExecuteAsync() { var commands = m_CommandStore.Commands; var totalCount = commands.Count; const int itemsPerPage = 10; int currentPage = 1; if (Context.Parameters.Length == 0 || Context.Parameters.TryGet(0, out currentPage)) { if (currentPage < 1) { throw new CommandWrongUsageException(Context); } var pageCommands = commands .Where(d => d.ParentId == null) .Skip(itemsPerPage * (currentPage - 1)) .Take(itemsPerPage) .ToList(); await PrintPageAsync(currentPage, (int)Math.Ceiling((double)totalCount / itemsPerPage), pageCommands); } else if (Context.Parameters.Length > 0) { var context = m_CommandContextBuilder.CreateContext(Context.Actor, Context.Parameters.ToArray(), Context.CommandPrefix, commands); var permission = context.CommandRegistration == null ? null : m_CommandPermissionBuilder.GetPermission(context.CommandRegistration, commands); if (context.CommandRegistration == null) { await Context.Actor.PrintMessageAsync(m_StringLocalizer["commands:errors:not_found", new { CommandName = context.GetCommandLine(false) }], Color.Red); return; } if (!string.IsNullOrEmpty(permission) && await m_PermissionChecker.CheckPermissionAsync(Context.Actor, permission) != PermissionGrantResult.Grant) { throw new NotEnoughPermissionException(permission, m_StringLocalizer); } await PrintCommandHelpAsync(context, permission, commands); await context.DisposeAsync(); } }
protected virtual string GetPermission(ICommandRegistration commandRegistration, IReadOnlyCollection <ICommandRegistration> commands) { var permission = commandRegistration == null ? null : m_CommandPermissionBuilder.GetPermission(commandRegistration, commands); if (permission == null) { return(null); } var registeredPermission = m_PermissionRegistry.FindPermission(commandRegistration.Component, permission); if (registeredPermission == null) { throw new Exception($"Unregistered permission \"{permission}\" in component: {commandRegistration.Component.OpenModComponentId}"); } return($"{registeredPermission.Owner.OpenModComponentId}:{registeredPermission.Permission}"); }
private void OnCommandSourcesChanged() { AsyncHelper.RunSync(m_CommandSources.DisposeAllAsync); try { m_CommandSources = m_Options.Value.CreateCommandSources(m_ServiceProvider); } catch (ObjectDisposedException) { // https://github.com/openmod/OpenMod/issues/61 m_CommandSources = new List <ICommandSource>(); } var commands = m_CommandSources.SelectMany(d => d.Commands).ToList(); foreach (var registration in commands) { var permission = m_CommandPermissionBuilder.GetPermission(registration, commands); m_PermissionRegistry.RegisterPermission(registration.Component, permission, description: $"Grants access to the {registration.Id} command.", defaultGrant: PermissionGrantResult.Default); if (registration.PermissionRegistrations == null) { continue; } foreach (var permissionRegistration in registration.PermissionRegistrations) { m_PermissionRegistry.RegisterPermission(permissionRegistration.Owner, $"{permission}.{permissionRegistration.Permission}", permissionRegistration.Description, permissionRegistration.DefaultGrant); } } }
public async Task <ICommandContext> ExecuteAsync(ICommandActor actor, string[] args, string prefix) { if (args == null || args.Length == 0) { throw new Exception("Can not execute command with null or empty args"); } var currentCommandAccessor = m_LifetimeScope.Resolve <ICurrentCommandContextAccessor>(); var commandsRegistrations = m_CommandStore.Commands; var logger = m_LifetimeScope.Resolve <ILogger <CommandExecutor> >(); var commandContextBuilder = m_LifetimeScope.Resolve <ICommandContextBuilder>(); var permissionChecker = m_LifetimeScope.Resolve <IPermissionChecker>(); var stringLocalizer = m_LifetimeScope.Resolve <IOpenModStringLocalizer>(); var commandContext = commandContextBuilder.CreateContext(actor, args, prefix, commandsRegistrations); var commandExecutingEvent = new CommandExecutingEvent(actor, commandContext); await m_EventBus.EmitAsync(m_Runtime, this, commandExecutingEvent); if (commandExecutingEvent.IsCancelled) { return(commandExecutingEvent.CommandContext); } logger.LogInformation($"Actor {actor.Type}/{actor.DisplayName} ({actor.Id}) has executed command \"{string.Join(" ", args)}\"."); try { if (commandContext.Exception != null) { throw commandContext.Exception; } currentCommandAccessor.Context = commandContext; var permission = m_CommandPermissionBuilder.GetPermission(commandContext.CommandRegistration); if (!string.IsNullOrWhiteSpace(permission) && await permissionChecker.CheckPermissionAsync(actor, permission) != PermissionGrantResult.Grant) { throw new NotEnoughPermissionException(permission, stringLocalizer); } var command = commandContext.CommandRegistration.Instantiate(commandContext.ServiceProvider); await command.ExecuteAsync(); currentCommandAccessor.Context = null; } catch (UserFriendlyException ex) { await actor.PrintMessageAsync(ex.Message, Color.DarkRed); commandContext.Exception = ex; } catch (Exception ex) { await actor.PrintMessageAsync("An internal error occured during the command execution.", Color.DarkRed); logger.LogError(ex, $"Exception occured on command \"{string.Join(" ", args)}\" by actor {actor.Type}/{actor.DisplayName} ({actor.Id})"); commandContext.Exception = ex; #if DEBUG throw; // in debug mode we want to debug such exceptions instead of catching them #endif } finally { var commandExecutedEvent = new CommandExecutedEvent(actor, commandContext); await m_EventBus.EmitAsync(m_Runtime, this, commandExecutedEvent); await commandContext.DisposeAsync(); } return(commandContext); }
public async Task InvalidateAsync() { await m_CommandSources.DisposeAllAsync(); if (m_Runtime.IsDisposing) { return; } m_CommandSources = m_Options.Value.CreateCommandSources(m_ServiceProvider); if (m_CommandSources.Count == 0) { m_Logger.LogDebug("InvalidateAsync: failed because no command sources were found; this is normal on booting."); return; } var commands = new List <ICommandRegistration>(); foreach (var sources in m_CommandSources) { commands.AddRange(await sources.GetCommandsAsync()); } foreach (var registration in commands) { var permission = m_CommandPermissionBuilder.GetPermission(registration, commands).Split(':')[1]; m_PermissionRegistry.RegisterPermission(registration.Component, permission, description: $"Grants access to the {registration.Id} command.", defaultGrant: PermissionGrantResult.Default); if (registration.PermissionRegistrations == null) { continue; } foreach (var permissionRegistration in registration.PermissionRegistrations) { m_PermissionRegistry.RegisterPermission(permissionRegistration.Owner, $"{permission}.{permissionRegistration.Permission}", permissionRegistration.Description, permissionRegistration.DefaultGrant); } } var commandsData = await m_CommandDataStore.GetRegisteredCommandsAsync(); if (commandsData?.Commands == null) { throw new Exception("Failed to register commands: command data was null"); } foreach (var command in commands .Where(d => !commandsData.Commands.Any(c => c.Id?.Equals(d.Id, StringComparison.OrdinalIgnoreCase) ?? false))) { commandsData.Commands.Add(CreateDefaultCommandData(command)); } if (commandsData.Commands.Count == 0) { throw new Exception("Failed to register commands: command data was empty."); } await m_CommandDataStore.SetRegisteredCommandsAsync(commandsData); m_Logger.LogDebug($"Reloaded {commands.Count} commands."); }
private void AppendCommand( StringBuilder markdownBuilder, ICommandRegistration command, List <ICommandRegistration> commands, ICommandContext commandContext) { markdownBuilder.Append("- ").Append(commandContext.CommandPrefix).Append(commandContext.CommandAlias); if (!string.IsNullOrEmpty(command.Syntax)) { markdownBuilder.Append(' ').Append(command.Syntax); } if (!string.IsNullOrEmpty(command.Description)) { markdownBuilder.Append(": ").Append(command.Description); } markdownBuilder.AppendLine(); markdownBuilder.Append(" id: ").AppendLine(command.Id); var permissionRegistrations = new List <IPermissionRegistration>(); var commandPermission = m_PermissionBuilder.GetPermission(command, commands); var commandPermissionRegistration = m_PermissionRegistry.FindPermission(m_Plugin, commandPermission); if (commandPermissionRegistration != null) { permissionRegistrations.Add(commandPermissionRegistration); } if (command.PermissionRegistrations != null) { var prefixedPermissions = new List <IPermissionRegistration>(); foreach (var permission in command.PermissionRegistrations) { prefixedPermissions.Add(new PermissionRegistration { Permission = commandPermission + "." + permission.Permission, Description = permission.Description, DefaultGrant = permission.DefaultGrant, Owner = permission.Owner }); } permissionRegistrations.AddRange(prefixedPermissions); } if (permissionRegistrations.Count > 0) { markdownBuilder.AppendLine(" permissions:"); foreach (var permissionRegistration in permissionRegistrations) { markdownBuilder.Append(" - ").Append(permissionRegistration.Permission); if (!string.IsNullOrEmpty(permissionRegistration.Description)) { markdownBuilder.Append(": ").Append(permissionRegistration.Description); } markdownBuilder.AppendLine(); } m_PrintedCommandPermissions.AddRange(permissionRegistrations); } var childCommands = commands .Where(d => string.Equals(d.ParentId, command.Id, StringComparison.OrdinalIgnoreCase)); foreach (var child in childCommands) { var ctx2 = m_CommandContextBuilder.CreateContext(null, new string[] { command.Name, child.Name }, string.Empty, commands); AppendCommand(markdownBuilder, child, commands, ctx2); } commandContext.DisposeAsync().GetAwaiter().GetResult(); }
private void AppendCommand( StringBuilder markdownBuilder, ICommandRegistration command, List <ICommandRegistration> commands, List <string> args) { var ctx = m_CommandContextBuilder.CreateContext(null, args.ToArray(), string.Empty, commands); try { markdownBuilder.Append($"- {ctx.CommandPrefix}{ctx.CommandAlias}"); if (!string.IsNullOrEmpty(command.Syntax)) { markdownBuilder.Append($" {command.Syntax}"); } if (!string.IsNullOrEmpty(command.Description)) { markdownBuilder.Append($": {command.Description}"); } markdownBuilder.AppendLine(" "); markdownBuilder.AppendLine($" id: {command.Id} "); var permissionRegistrations = new List <IPermissionRegistration>(); var commandPermission = m_PermissionBuilder.GetPermission(command, commands); var commandPermissionRegistration = m_PermissionRegistry.FindPermission(m_Plugin, commandPermission); if (commandPermissionRegistration != null) { permissionRegistrations.Add(commandPermissionRegistration); } if (command.PermissionRegistrations != null) { var prefixedPermissions = new List <IPermissionRegistration>(); foreach (var permission in command.PermissionRegistrations) { prefixedPermissions.Add(new PermissionRegistration { Permission = commandPermission + "." + permission.Permission, Description = permission.Description, DefaultGrant = permission.DefaultGrant, Owner = permission.Owner }); } permissionRegistrations.AddRange(prefixedPermissions); } if (permissionRegistrations.Count > 0) { markdownBuilder.AppendLine($" permissions: "); foreach (var permissionRegistration in permissionRegistrations) { markdownBuilder.Append($" - {permissionRegistration.Owner.OpenModComponentId}:{permissionRegistration.Permission}"); if (!string.IsNullOrEmpty(permissionRegistration.Description)) { markdownBuilder.Append($": {permissionRegistration.Description}"); } markdownBuilder.AppendLine(" "); } m_PrintedCommandPermissions.AddRange(permissionRegistrations); } var childCommands = commands .Where(d => string.Equals(d.ParentId, command.Id, StringComparison.OrdinalIgnoreCase)); foreach (var child in childCommands) { args.Add(child.Name); AppendCommand(markdownBuilder, child, commands, args); } } finally { ctx.DisposeAsync().GetAwaiter().GetResult(); } }
public async Task <ICommandContext> ExecuteAsync(ICommandActor actor, string[] args, string prefix) { if (args == null || args.Length == 0) { throw new Exception("Can not execute command with null or empty args"); } m_Logger.LogInformation($"Actor {actor.Type}/{actor.DisplayName} ({actor.Id}) has executed command \"{string.Join(" ", args)}\"."); var currentCommandAccessor = m_LifetimeScope.Resolve <ICurrentCommandContextAccessor>(); var commandContextBuilder = m_LifetimeScope.Resolve <ICommandContextBuilder>(); var stringLocalizer = m_LifetimeScope.Resolve <IOpenModStringLocalizer>(); var commandsRegistrations = await m_CommandStore.GetCommandsAsync(); var commandContext = commandContextBuilder.CreateContext(actor, args, prefix, commandsRegistrations); var commandExecutingEvent = new CommandExecutingEvent(actor, commandContext); await m_EventBus.EmitAsync(m_Runtime, this, commandExecutingEvent); if (commandExecutingEvent.IsCancelled) { return(commandExecutingEvent.CommandContext); } try { if (commandContext.Exception != null) { throw commandContext.Exception; } currentCommandAccessor.Context = commandContext; var permission = m_CommandPermissionBuilder.GetPermission(commandContext.CommandRegistration); var permissionChecker = m_Runtime.Host.Services.GetRequiredService <IPermissionChecker>(); if (!string.IsNullOrWhiteSpace(permission) && await permissionChecker.CheckPermissionAsync(actor, permission) != PermissionGrantResult.Grant) { throw new NotEnoughPermissionException(stringLocalizer, permission); } Stopwatch sw = new Stopwatch(); sw.Start(); var command = commandContext.CommandRegistration.Instantiate(commandContext.ServiceProvider); await command.ExecuteAsync(); m_Logger.LogDebug($"Command \"{string.Join(" ", args)}\" executed in {sw.ElapsedMilliseconds}ms"); sw.Reset(); currentCommandAccessor.Context = null; } catch (UserFriendlyException ex) { commandContext.Exception = ex; } catch (Exception ex) { commandContext.Exception = ex; } finally { var commandExecutedEvent = new CommandExecutedEvent(actor, commandContext); await m_EventBus.EmitAsync(m_Runtime, this, commandExecutedEvent); if (commandContext.Exception != null && !commandExecutedEvent.ExceptionHandled) { if (commandContext.Exception is UserFriendlyException) { await actor.PrintMessageAsync(commandContext.Exception.Message, Color.DarkRed); } else { await actor.PrintMessageAsync("An internal error occured during the command execution.", Color.DarkRed); m_Logger.LogError(commandContext.Exception, $"Exception occured on command \"{string.Join(" ", args)}\" by actor {actor.Type}/{actor.DisplayName} ({actor.Id})"); } } await commandContext.DisposeAsync(); } return(commandContext); }