diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 0da506839..0d887b84d 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -177,8 +177,6 @@ namespace IW4MAdmin await command.ExecuteAsync(E); } - - var pluginTasks = Manager.Plugins.Where(_plugin => _plugin.Name != "Login").Select(async _plugin => { try @@ -202,7 +200,10 @@ namespace IW4MAdmin } }); - await Task.WhenAny(pluginTasks); + if (pluginTasks.Count() > 0) + { + await Task.WhenAny(pluginTasks); + } } catch (Exception e) diff --git a/SharedLibraryCore/Command.cs b/SharedLibraryCore/Command.cs index cbde52552..ec8bd4a72 100644 --- a/SharedLibraryCore/Command.cs +++ b/SharedLibraryCore/Command.cs @@ -15,6 +15,7 @@ namespace SharedLibraryCore { private readonly CommandConfiguration _config; protected readonly ITranslationLookup _translationLookup; + protected ILogger logger; public Command(CommandConfiguration config, ITranslationLookup layout) { diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index 27412f032..333260e47 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -76,6 +76,13 @@ namespace SharedLibraryCore.Commands public override async Task ExecuteAsync(GameEvent E) { + // they're trying to set the console's permission level... sigh... + if (E.Origin.Level == Permission.Console) + { + E.Origin.Tell(_translationLookup["COMMANDS_OWNER_IDIOT"]); + return; + } + if (await (E.Owner.Manager.GetClientService() as ClientService).GetOwnerCount() == 0 && !E.Origin.SetLevel(EFClient.Permission.Owner, Utilities.IW4MAdminClient(E.Owner)).Failed) { @@ -604,7 +611,7 @@ namespace SharedLibraryCore.Commands /// public class SetLevelCommand : Command { - public SetLevelCommand(CommandConfiguration config, ITranslationLookup translationLookup) : base(config, translationLookup) + public SetLevelCommand(CommandConfiguration config, ITranslationLookup translationLookup, ILogger logger) : base(config, translationLookup) { Name = "setlevel"; Description = _translationLookup["COMMANDS_SETLEVEL_DESC"]; @@ -624,77 +631,95 @@ namespace SharedLibraryCore.Commands Required = true } }; + this.logger = logger; } - public override async Task ExecuteAsync(GameEvent E) + public override async Task ExecuteAsync(GameEvent gameEvent) { - Permission oldPerm = E.Target.Level; - Permission newPerm = Utilities.MatchPermission(E.Data); + Permission oldPerm = gameEvent.Target.Level; + Permission newPerm = Utilities.MatchPermission(gameEvent.Data); + bool allowMultiOwner = gameEvent.Owner.Manager.GetApplicationSettings().Configuration().EnableMultipleOwners; + bool steppedPrivileges = gameEvent.Owner.Manager.GetApplicationSettings().Configuration().EnableSteppedHierarchy; + var targetClient = gameEvent.Target; - if (E.Target == E.Origin) + // pre setup logic + bool canPromoteSteppedPriv = gameEvent.Origin.Level > newPerm || gameEvent.Origin.Level == Permission.Owner; + bool hasOwner = await gameEvent.Owner.Manager.GetClientService().GetOwnerCount() > 0; + + // trying to set self + if (gameEvent.Target == gameEvent.Origin) { - E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_SELF"]); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_SELF"]); return; } - else if (newPerm == Permission.Owner && - !E.Owner.Manager.GetApplicationSettings().Configuration().EnableMultipleOwners && - await E.Owner.Manager.GetClientService().GetOwnerCount() > 0) + // origin permission not high enough + else if (gameEvent.Origin.Level < gameEvent.Target.Level) + { + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_PERMISSION"].FormatExt(gameEvent.Target.Name)); + return; + } + + // trying to set owner without enabling multiple owners + else if (newPerm == Permission.Owner && !allowMultiOwner && hasOwner) { // only one owner is allowed - E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_OWNER"]); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_OWNER"]); return; } - else if (E.Origin.Level < Permission.Owner && - !E.Owner.Manager.GetApplicationSettings().Configuration().EnableSteppedHierarchy) + // trying to set level when only owner is allowed to + else if (gameEvent.Origin.Level < Permission.Owner && !steppedPrivileges) { // only the owner is allowed to set levels - E.Origin.Tell($"{_translationLookup["COMMANDS_SETLEVEL_STEPPEDDISABLED"]} ^5{E.Target.Name}"); + gameEvent.Origin.Tell($"{_translationLookup["COMMANDS_SETLEVEL_STEPPEDDISABLED"]} ^5{gameEvent.Target.Name}"); return; } - else if ((E.Origin.Level <= newPerm && - E.Origin.Level < Permission.Owner) || - E.Origin.Level == newPerm) + // stepped privilege is enabled, but the new level is too high + else if (steppedPrivileges && !canPromoteSteppedPriv) { // can't promote a client to higher than your current perms // or your peer - E.Origin.Tell(string.Format(_translationLookup["COMMANDS_SETLEVEL_LEVELTOOHIGH"], E.Target.Name, (E.Origin.Level - 1).ToString())); + gameEvent.Origin.Tell(string.Format(_translationLookup["COMMANDS_SETLEVEL_LEVELTOOHIGH"], gameEvent.Target.Name, (gameEvent.Origin.Level - 1).ToString())); return; } + // valid else if (newPerm > Permission.Banned) { - var ActiveClient = E.Owner.Manager.GetActiveClients() - .FirstOrDefault(p => p.NetworkId == E.Target.NetworkId); + targetClient = targetClient.ClientNumber < 0 ? + gameEvent.Owner.Manager.GetActiveClients() + .FirstOrDefault(c => c.ClientId == targetClient?.ClientId) ?? targetClient : targetClient; - if (ActiveClient != null) + logger.WriteInfo($"Beginning set level of client {gameEvent.Origin} to {newPerm}"); + + var result = await targetClient.SetLevel(newPerm, gameEvent.Origin).WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken); + + if (result.Failed) { - ActiveClient.SetLevel(newPerm, E.Origin); - - // inform the client that they were promoted - // we don't really want to tell them if they're demoted haha - if (newPerm > oldPerm) - { - ActiveClient.Tell(_translationLookup["COMMANDS_SETLEVEL_SUCCESS_TARGET"].FormatExt(newPerm)); - } + logger.WriteInfo($"Failed to set level of client {gameEvent.Origin}"); + gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]); + return; } - else + // inform the client that they were promoted + // we don't really want to tell them if they're demoted haha + if (targetClient.IsIngame && newPerm > oldPerm) { - E.Target.SetLevel(newPerm, E.Origin); + targetClient.Tell(_translationLookup["COMMANDS_SETLEVEL_SUCCESS_TARGET"].FormatExt(newPerm)); } // inform the origin that the client has been updated _ = newPerm < oldPerm ? - E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_DEMOTE_SUCCESS"].FormatExt(E.Target.Name)) : - E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_SUCCESS"].FormatExt(E.Target.Name)); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_DEMOTE_SUCCESS"].FormatExt(targetClient.Name)) : + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_SUCCESS"].FormatExt(targetClient.Name)); } + // all other tests failed so it's invalid group else { - E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_FAIL"]); + gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_FAIL"]); } } } diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs index 1a6144ac3..cd24acee8 100644 --- a/SharedLibraryCore/Services/ClientService.cs +++ b/SharedLibraryCore/Services/ClientService.cs @@ -239,7 +239,7 @@ namespace SharedLibraryCore.Services /// /// /// - public async Task UpdateLevel(Permission newPermission, EFClient temporalClient, EFClient origin) + public virtual async Task UpdateLevel(Permission newPermission, EFClient temporalClient, EFClient origin) { using (var ctx = new DatabaseContext()) { @@ -483,7 +483,7 @@ namespace SharedLibraryCore.Services /// (client level is owner) /// /// - public async Task GetOwnerCount() + public virtual async Task GetOwnerCount() { using (var ctx = new DatabaseContext(true)) { diff --git a/Tests/ApplicationTests/CommandTests.cs b/Tests/ApplicationTests/CommandTests.cs index 88b6bbd4d..3d5d50488 100644 --- a/Tests/ApplicationTests/CommandTests.cs +++ b/Tests/ApplicationTests/CommandTests.cs @@ -3,21 +3,17 @@ using System; using SharedLibraryCore.Interfaces; using IW4MAdmin; using FakeItEasy; -using IW4MAdmin.Application.EventParsers; using System.Linq; -using IW4MAdmin.Plugins.Stats.Models; -using IW4MAdmin.Application.Helpers; -using IW4MAdmin.Plugins.Stats.Config; -using System.Collections.Generic; using SharedLibraryCore.Database.Models; using Microsoft.Extensions.DependencyInjection; -using IW4MAdmin.Plugins.Stats.Helpers; using ApplicationTests.Fixtures; using System.Threading.Tasks; using SharedLibraryCore.Commands; using SharedLibraryCore.Configuration; using SharedLibraryCore; using ApplicationTests.Mocks; +using SharedLibraryCore.Services; +using static SharedLibraryCore.Database.Models.EFClient; namespace ApplicationTests { @@ -28,7 +24,10 @@ namespace ApplicationTests private IServiceProvider serviceProvider; private ITranslationLookup transLookup; private CommandConfiguration cmdConfig; - private MockEventHandler mockEventHandler; + private ApplicationConfiguration appConfig; + private EventHandlerMock mockEventHandler; + private ClientService clientService; + private IManager manager; [SetUp] public void Setup() @@ -37,24 +36,31 @@ namespace ApplicationTests cmdConfig = new CommandConfiguration(); serviceProvider = new ServiceCollection() - .BuildBase(new MockEventHandler(true)) - .BuildServiceProvider(); + .BuildBase(new EventHandlerMock(true)) + .BuildServiceProvider() + .SetupTestHooks(); - mockEventHandler = serviceProvider.GetRequiredService(); - - var mgr = serviceProvider.GetRequiredService(); + mockEventHandler = serviceProvider.GetRequiredService(); + manager = serviceProvider.GetRequiredService(); transLookup = serviceProvider.GetRequiredService(); + clientService = serviceProvider.GetRequiredService(); + appConfig = serviceProvider.GetRequiredService(); - A.CallTo(() => mgr.GetCommands()) + A.CallTo(() => manager.GetClientService()) + .Returns(clientService); + + A.CallTo(() => clientService.UpdateLevel(A.Ignored, A.Ignored, A.Ignored)) + .Returns(Task.CompletedTask); + + A.CallTo(() => manager.GetCommands()) .Returns(new Command[] { new ImpersonatableCommand(cmdConfig, transLookup), new NonImpersonatableCommand(cmdConfig, transLookup) }); - A.CallTo(() => mgr.AddEvent(A.Ignored)) - .Invokes((fakeCall) => mockEventHandler.HandleEvent(mgr, fakeCall.Arguments[0] as GameEvent)); - + A.CallTo(() => manager.AddEvent(A.Ignored)) + .Invokes((fakeCall) => mockEventHandler.HandleEvent(manager, fakeCall.Arguments[0] as GameEvent)); } #region RUNAS @@ -174,5 +180,343 @@ namespace ApplicationTests Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Command && !_event.Failed)); } #endregion + + #region SETLEVEL + [Test] + public async Task Test_SetLevelFailOnSelf() + { + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var server = serviceProvider.GetRequiredService(); + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.Owner; + + var gameEvent = new GameEvent() + { + Target = target, + Origin = target, + Data = "Administrator", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.Owner, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission)); + } + + [Test] + public async Task Test_SetLevelFailWithSourcePrivilegeTooLow() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Moderator; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.Administrator; + + A.CallTo(() => clientService.GetOwnerCount()) + .Returns(Task.FromResult(1)); + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Administrator", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.Administrator, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission)); + } + + [Test] + public async Task Test_SetLevelFailWithExistingOwner_AndOnlyOneOwnerAllowed() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.User; + + A.CallTo(() => clientService.GetOwnerCount()) + .Returns(Task.FromResult(1)); + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Owner", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.User, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission)); + } + + [Test] + public async Task Test_SetLevelFailWithStepPrivilegesDisabled_AndNonOwner() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.SeniorAdmin; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.Moderator; + + A.CallTo(() => clientService.GetOwnerCount()) + .Returns(Task.FromResult(1)); + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Administrator", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.Moderator, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission)); + } + + [Test] + public async Task Test_SetLevelFailWithStepPrivilegesEnabled_ButNewPermissionTooHigh() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Moderator; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.User; + appConfig.EnableSteppedHierarchy = true; + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Moderator", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.User, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission)); + } + + [Test] + public async Task Test_SetLevelFailInvalidGroup() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Owner; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.User; + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Banned", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.User, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission)); + } + + [Test] + public async Task Test_SetLevelSucceedWithNoExistingOwner_AndOnlyOneOwnerAllowed() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Owner; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.User; + + A.CallTo(() => clientService.GetOwnerCount()) + .Returns(Task.FromResult(0)); + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Owner", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.Owner, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission && !_event.Failed)); + } + + [Test] + public async Task Test_SetLevelOwnerSucceedWithMultiOwnerAllowed() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Owner; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.User; + appConfig.EnableMultipleOwners = true; + + A.CallTo(() => clientService.GetOwnerCount()) + .Returns(Task.FromResult(1)); + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Owner", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.Owner, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission && !_event.Failed)); + } + + [Test] + public async Task Test_SetLevelOwnerSucceedWithMultiOwnerAllowed_AndSteppedPrivileges() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Owner; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.User; + appConfig.EnableMultipleOwners = true; + appConfig.EnableSteppedHierarchy = true; + + A.CallTo(() => clientService.GetOwnerCount()) + .Returns(Task.FromResult(1)); + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Owner", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.Owner, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission && !_event.Failed)); + } + + [Test] + public async Task Test_SetLevelSucceedWithSteppedPrivileges() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Moderator; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.User; + appConfig.EnableSteppedHierarchy = true; + + A.CallTo(() => clientService.GetOwnerCount()) + .Returns(Task.FromResult(1)); + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Trusted", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.Trusted, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission && !_event.Failed)); + } + + [Test] + public async Task Test_SetLevelSucceed() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Owner; + var target = ClientGenerators.CreateBasicClient(server); + target.Level = Permission.User; + appConfig.EnableSteppedHierarchy = true; + + A.CallTo(() => clientService.GetOwnerCount()) + .Returns(Task.FromResult(1)); + + var gameEvent = new GameEvent() + { + Target = target, + Origin = origin, + Data = "Trusted", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.Trusted, target.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission && !_event.Failed)); + } + + [Test] + public async Task Test_SetLevelSucceed_AndFindsIngameClient() + { + var server = serviceProvider.GetRequiredService(); + var cmd = new SetLevelCommand(cmdConfig, transLookup, logger); + var origin = ClientGenerators.CreateBasicClient(server); + origin.Level = Permission.Owner; + var databaseTarget = ClientGenerators.CreateDatabaseClient(); + databaseTarget.Level = Permission.Administrator; + + var ingameTarget = ClientGenerators.CreateBasicClient(server); + ingameTarget.Level = Permission.Administrator; + + A.CallTo(() => manager.GetActiveClients()) + .Returns(new[] { ingameTarget }); + + A.CallTo(() => clientService.GetOwnerCount()) + .Returns(Task.FromResult(1)); + + var gameEvent = new GameEvent() + { + Target = databaseTarget, + Origin = origin, + Data = "User", + Owner = server, + }; + + await cmd.ExecuteAsync(gameEvent); + + Assert.AreEqual(Permission.User, ingameTarget.Level); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Tell)); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ChangePermission && !_event.Failed)); + } + #endregion } } diff --git a/Tests/ApplicationTests/DependencyInjectionExtensions.cs b/Tests/ApplicationTests/DependencyInjectionExtensions.cs index 2784955fa..fb34a285d 100644 --- a/Tests/ApplicationTests/DependencyInjectionExtensions.cs +++ b/Tests/ApplicationTests/DependencyInjectionExtensions.cs @@ -3,9 +3,11 @@ using ApplicationTests.Mocks; using FakeItEasy; using IW4MAdmin; using Microsoft.Extensions.DependencyInjection; +using SharedLibraryCore.Configuration; using SharedLibraryCore.Database; using SharedLibraryCore.Interfaces; using SharedLibraryCore.Services; +using System; namespace ApplicationTests { @@ -16,11 +18,11 @@ namespace ApplicationTests if (eventHandler == null) { - eventHandler = new MockEventHandler(); - serviceCollection.AddSingleton(eventHandler as MockEventHandler); + eventHandler = new EventHandlerMock(); + serviceCollection.AddSingleton(eventHandler as EventHandlerMock); } - else if (eventHandler is MockEventHandler mockEventHandler) + else if (eventHandler is EventHandlerMock mockEventHandler) { serviceCollection.AddSingleton(mockEventHandler); } @@ -42,7 +44,10 @@ namespace ApplicationTests .AddSingleton() .AddSingleton(A.Fake()) .AddSingleton(A.Fake()) - .AddSingleton(eventHandler); + .AddSingleton(eventHandler) + .AddSingleton(ConfigurationGenerators.CreateApplicationConfiguration()) + .AddSingleton(ConfigurationGenerators.CreateCommandConfiguration()) + .AddSingleton, ApplicationConfigurationHandlerMock>(); serviceCollection.AddSingleton(_sp => new IW4MServer(_sp.GetRequiredService(), ConfigurationGenerators.CreateServerConfiguration(), _sp.GetRequiredService(), _sp.GetRequiredService(), _sp.GetRequiredService()) @@ -52,5 +57,14 @@ namespace ApplicationTests return serviceCollection; } + + public static IServiceProvider SetupTestHooks(this IServiceProvider serviceProvider) + { + var mgr = serviceProvider.GetRequiredService(); + A.CallTo(() => mgr.GetApplicationSettings()) + .Returns(serviceProvider.GetRequiredService>()); + + return serviceProvider; + } } } diff --git a/Tests/ApplicationTests/Fixtures/ConfigurationGenerators.cs b/Tests/ApplicationTests/Fixtures/ConfigurationGenerators.cs index 7e3b70a70..7c4a6b094 100644 --- a/Tests/ApplicationTests/Fixtures/ConfigurationGenerators.cs +++ b/Tests/ApplicationTests/Fixtures/ConfigurationGenerators.cs @@ -18,5 +18,7 @@ namespace ApplicationTests.Fixtures Say = "say" } }; + public static ApplicationConfiguration CreateApplicationConfiguration() => new ApplicationConfiguration() { Servers = new[] { CreateServerConfiguration() } }; + public static CommandConfiguration CreateCommandConfiguration() => new CommandConfiguration(); } } diff --git a/Tests/ApplicationTests/IW4MServerTests.cs b/Tests/ApplicationTests/IW4MServerTests.cs index 899be42f0..02d645b6b 100644 --- a/Tests/ApplicationTests/IW4MServerTests.cs +++ b/Tests/ApplicationTests/IW4MServerTests.cs @@ -25,7 +25,8 @@ namespace ApplicationTests private IManager fakeManager; private IRConConnection fakeRConConnection; private IRConParser fakeRConParser; - private MockEventHandler mockEventHandler; + private EventHandlerMock mockEventHandler; + private ApplicationConfiguration appConfig; [SetUp] public void Setup() @@ -36,7 +37,8 @@ namespace ApplicationTests fakeManager = serviceProvider.GetRequiredService(); fakeRConConnection = serviceProvider.GetRequiredService(); fakeRConParser = serviceProvider.GetRequiredService(); - mockEventHandler = serviceProvider.GetRequiredService(); + mockEventHandler = serviceProvider.GetRequiredService(); + appConfig = serviceProvider.GetRequiredService(); var rconConnectionFactory = serviceProvider.GetRequiredService(); @@ -517,12 +519,7 @@ namespace ApplicationTests { var server = serviceProvider.GetService(); var fakeConfigHandler = A.Fake>(); - - A.CallTo(() => fakeManager.GetApplicationSettings()) - .Returns(fakeConfigHandler); - - A.CallTo(() => fakeConfigHandler.Configuration()) - .Returns(new ApplicationConfiguration() { IgnoreServerConnectionLost = true }); + appConfig.IgnoreServerConnectionLost = true; A.CallTo(() => fakeRConParser.GetStatusAsync(A.Ignored)) .ThrowsAsync(new NetworkException("err")); @@ -535,7 +532,6 @@ namespace ApplicationTests A.CallTo(() => fakeLogger.WriteError(A.Ignored)) .MustNotHaveHappened(); - Assert.IsEmpty(mockEventHandler.Events); } [Test] @@ -544,12 +540,6 @@ namespace ApplicationTests var server = serviceProvider.GetService(); var fakeConfigHandler = A.Fake>(); - A.CallTo(() => fakeManager.GetApplicationSettings()) - .Returns(fakeConfigHandler); - - A.CallTo(() => fakeConfigHandler.Configuration()) - .Returns(new ApplicationConfiguration() { IgnoreServerConnectionLost = false }); - A.CallTo(() => fakeRConParser.GetStatusAsync(A.Ignored)) .ThrowsAsync(new NetworkException("err")); @@ -568,7 +558,7 @@ namespace ApplicationTests A.CallTo(() => fakeLogger.WriteError(A.Ignored)) .MustHaveHappenedOnceExactly(); - Assert.IsNotEmpty(mockEventHandler.Events); + Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.ConnectionLost)); Assert.AreEqual("err", (mockEventHandler.Events[0].Extra as NetworkException).Message); } } diff --git a/Tests/ApplicationTests/Mocks/ApplicationConfigurationHandlerMock.cs b/Tests/ApplicationTests/Mocks/ApplicationConfigurationHandlerMock.cs new file mode 100644 index 000000000..22ab7037b --- /dev/null +++ b/Tests/ApplicationTests/Mocks/ApplicationConfigurationHandlerMock.cs @@ -0,0 +1,36 @@ +using SharedLibraryCore.Configuration; +using SharedLibraryCore.Interfaces; +using System; +using System.Threading.Tasks; + +namespace ApplicationTests.Mocks +{ + class ApplicationConfigurationHandlerMock : IConfigurationHandler + { + private readonly ApplicationConfiguration _appConfig; + + public ApplicationConfigurationHandlerMock(ApplicationConfiguration configuration) + { + _appConfig = configuration; + } + + public string FileName => ""; + + public void Build() + { + + } + + public ApplicationConfiguration Configuration() => _appConfig; + + public Task Save() + { + throw new NotImplementedException(); + } + + public void Set(ApplicationConfiguration config) + { + throw new NotImplementedException(); + } + } +} diff --git a/Tests/ApplicationTests/Mocks/EventHandler.cs b/Tests/ApplicationTests/Mocks/EventHandlerMock.cs similarity index 85% rename from Tests/ApplicationTests/Mocks/EventHandler.cs rename to Tests/ApplicationTests/Mocks/EventHandlerMock.cs index e61a9a206..d00291d09 100644 --- a/Tests/ApplicationTests/Mocks/EventHandler.cs +++ b/Tests/ApplicationTests/Mocks/EventHandlerMock.cs @@ -4,12 +4,12 @@ using System.Collections.Generic; namespace ApplicationTests.Mocks { - class MockEventHandler : IEventHandler + class EventHandlerMock : IEventHandler { public IList Events = new List(); private readonly bool _autoExecute; - public MockEventHandler(bool autoExecute = false) + public EventHandlerMock(bool autoExecute = false) { _autoExecute = autoExecute; } diff --git a/Tests/ApplicationTests/PluginTests.cs b/Tests/ApplicationTests/PluginTests.cs index f4f5ac017..5278eaed1 100644 --- a/Tests/ApplicationTests/PluginTests.cs +++ b/Tests/ApplicationTests/PluginTests.cs @@ -2,6 +2,7 @@ using ApplicationTests.Mocks; using FakeItEasy; using IW4MAdmin; +using IW4MAdmin.Application.Factories; using IW4MAdmin.Application.Misc; using Microsoft.Extensions.DependencyInjection; using NUnit.Framework; @@ -24,14 +25,16 @@ namespace ApplicationTests private static string PLUGIN_DIR = @"X:\IW4MAdmin\Plugins\ScriptPlugins"; private IServiceProvider serviceProvider; private IManager fakeManager; - private MockEventHandler mockEventHandler; + private EventHandlerMock mockEventHandler; [SetUp] public void Setup() { - serviceProvider = new ServiceCollection().BuildBase().BuildServiceProvider(); + serviceProvider = new ServiceCollection().BuildBase() + .AddSingleton() + .BuildServiceProvider(); fakeManager = serviceProvider.GetRequiredService(); - mockEventHandler = serviceProvider.GetRequiredService(); + mockEventHandler = serviceProvider.GetRequiredService(); var rconConnectionFactory = serviceProvider.GetRequiredService(); @@ -62,7 +65,7 @@ namespace ApplicationTests A.CallTo(() => fakeManager.GetClientService()) .Returns(fakeClientService); - await plugin.Initialize(serviceProvider.GetRequiredService()); + await plugin.Initialize(serviceProvider.GetRequiredService(), serviceProvider.GetRequiredService()); var gameEvent = new GameEvent() { diff --git a/Tests/ApplicationTests/StatsTests.cs b/Tests/ApplicationTests/StatsTests.cs index a2296ed00..cff545ceb 100644 --- a/Tests/ApplicationTests/StatsTests.cs +++ b/Tests/ApplicationTests/StatsTests.cs @@ -22,14 +22,17 @@ namespace ApplicationTests { ILogger logger; private IServiceProvider serviceProvider; + private IConfigurationHandlerFactory handlerFactory; [SetUp] public void Setup() { logger = A.Fake(); + handlerFactory = A.Fake(); serviceProvider = new ServiceCollection() .BuildBase() + .AddSingleton() .BuildServiceProvider(); void testLog(string msg) => Console.WriteLine(msg); @@ -44,9 +47,8 @@ namespace ApplicationTests public void TestKDR() { var mgr = A.Fake(); - var handlerFactory = A.Fake(); var config = A.Fake>(); - var plugin = new IW4MAdmin.Plugins.Stats.Plugin(handlerFactory, null); + var plugin = serviceProvider.GetRequiredService(); A.CallTo(() => config.Configuration()) .Returns(new StatsConfiguration()