bugfixes/enhancements

prevent users from trying to set the console's level to owner
fix issue with setting multiple owners
update/improve unit tests
This commit is contained in:
RaidMax 2020-05-16 11:54:01 -05:00
parent 420e0d5ab5
commit d3d1f31ee0
12 changed files with 500 additions and 82 deletions

View File

@ -177,8 +177,6 @@ namespace IW4MAdmin
await command.ExecuteAsync(E); await command.ExecuteAsync(E);
} }
var pluginTasks = Manager.Plugins.Where(_plugin => _plugin.Name != "Login").Select(async _plugin => var pluginTasks = Manager.Plugins.Where(_plugin => _plugin.Name != "Login").Select(async _plugin =>
{ {
try try
@ -202,7 +200,10 @@ namespace IW4MAdmin
} }
}); });
await Task.WhenAny(pluginTasks); if (pluginTasks.Count() > 0)
{
await Task.WhenAny(pluginTasks);
}
} }
catch (Exception e) catch (Exception e)

View File

@ -15,6 +15,7 @@ namespace SharedLibraryCore
{ {
private readonly CommandConfiguration _config; private readonly CommandConfiguration _config;
protected readonly ITranslationLookup _translationLookup; protected readonly ITranslationLookup _translationLookup;
protected ILogger logger;
public Command(CommandConfiguration config, ITranslationLookup layout) public Command(CommandConfiguration config, ITranslationLookup layout)
{ {

View File

@ -76,6 +76,13 @@ namespace SharedLibraryCore.Commands
public override async Task ExecuteAsync(GameEvent E) 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 && if (await (E.Owner.Manager.GetClientService() as ClientService).GetOwnerCount() == 0 &&
!E.Origin.SetLevel(EFClient.Permission.Owner, Utilities.IW4MAdminClient(E.Owner)).Failed) !E.Origin.SetLevel(EFClient.Permission.Owner, Utilities.IW4MAdminClient(E.Owner)).Failed)
{ {
@ -604,7 +611,7 @@ namespace SharedLibraryCore.Commands
/// </summary> /// </summary>
public class SetLevelCommand : Command 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"; Name = "setlevel";
Description = _translationLookup["COMMANDS_SETLEVEL_DESC"]; Description = _translationLookup["COMMANDS_SETLEVEL_DESC"];
@ -624,77 +631,95 @@ namespace SharedLibraryCore.Commands
Required = true 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 oldPerm = gameEvent.Target.Level;
Permission newPerm = Utilities.MatchPermission(E.Data); 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; return;
} }
else if (newPerm == Permission.Owner && // origin permission not high enough
!E.Owner.Manager.GetApplicationSettings().Configuration().EnableMultipleOwners && else if (gameEvent.Origin.Level < gameEvent.Target.Level)
await E.Owner.Manager.GetClientService().GetOwnerCount() > 0) {
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 // only one owner is allowed
E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_OWNER"]); gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_OWNER"]);
return; return;
} }
else if (E.Origin.Level < Permission.Owner && // trying to set level when only owner is allowed to
!E.Owner.Manager.GetApplicationSettings().Configuration().EnableSteppedHierarchy) else if (gameEvent.Origin.Level < Permission.Owner && !steppedPrivileges)
{ {
// only the owner is allowed to set levels // 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; return;
} }
else if ((E.Origin.Level <= newPerm && // stepped privilege is enabled, but the new level is too high
E.Origin.Level < Permission.Owner) || else if (steppedPrivileges && !canPromoteSteppedPriv)
E.Origin.Level == newPerm)
{ {
// can't promote a client to higher than your current perms // can't promote a client to higher than your current perms
// or your peer // 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; return;
} }
// valid
else if (newPerm > Permission.Banned) else if (newPerm > Permission.Banned)
{ {
var ActiveClient = E.Owner.Manager.GetActiveClients() targetClient = targetClient.ClientNumber < 0 ?
.FirstOrDefault(p => p.NetworkId == E.Target.NetworkId); 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); logger.WriteInfo($"Failed to set level of client {gameEvent.Origin}");
gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
// inform the client that they were promoted return;
// 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));
}
} }
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 // inform the origin that the client has been updated
_ = newPerm < oldPerm ? _ = newPerm < oldPerm ?
E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_DEMOTE_SUCCESS"].FormatExt(E.Target.Name)) : gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_DEMOTE_SUCCESS"].FormatExt(targetClient.Name)) :
E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_SUCCESS"].FormatExt(E.Target.Name)); gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_SUCCESS"].FormatExt(targetClient.Name));
} }
// all other tests failed so it's invalid group
else else
{ {
E.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_FAIL"]); gameEvent.Origin.Tell(_translationLookup["COMMANDS_SETLEVEL_FAIL"]);
} }
} }
} }

View File

@ -239,7 +239,7 @@ namespace SharedLibraryCore.Services
/// <param name="origin"></param> /// <param name="origin"></param>
/// <param name="ctx"></param> /// <param name="ctx"></param>
/// <returns></returns> /// <returns></returns>
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()) using (var ctx = new DatabaseContext())
{ {
@ -483,7 +483,7 @@ namespace SharedLibraryCore.Services
/// (client level is owner) /// (client level is owner)
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public async Task<int> GetOwnerCount() public virtual async Task<int> GetOwnerCount()
{ {
using (var ctx = new DatabaseContext(true)) using (var ctx = new DatabaseContext(true))
{ {

View File

@ -3,21 +3,17 @@ using System;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using IW4MAdmin; using IW4MAdmin;
using FakeItEasy; using FakeItEasy;
using IW4MAdmin.Application.EventParsers;
using System.Linq; 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 SharedLibraryCore.Database.Models;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using IW4MAdmin.Plugins.Stats.Helpers;
using ApplicationTests.Fixtures; using ApplicationTests.Fixtures;
using System.Threading.Tasks; using System.Threading.Tasks;
using SharedLibraryCore.Commands; using SharedLibraryCore.Commands;
using SharedLibraryCore.Configuration; using SharedLibraryCore.Configuration;
using SharedLibraryCore; using SharedLibraryCore;
using ApplicationTests.Mocks; using ApplicationTests.Mocks;
using SharedLibraryCore.Services;
using static SharedLibraryCore.Database.Models.EFClient;
namespace ApplicationTests namespace ApplicationTests
{ {
@ -28,7 +24,10 @@ namespace ApplicationTests
private IServiceProvider serviceProvider; private IServiceProvider serviceProvider;
private ITranslationLookup transLookup; private ITranslationLookup transLookup;
private CommandConfiguration cmdConfig; private CommandConfiguration cmdConfig;
private MockEventHandler mockEventHandler; private ApplicationConfiguration appConfig;
private EventHandlerMock mockEventHandler;
private ClientService clientService;
private IManager manager;
[SetUp] [SetUp]
public void Setup() public void Setup()
@ -37,24 +36,31 @@ namespace ApplicationTests
cmdConfig = new CommandConfiguration(); cmdConfig = new CommandConfiguration();
serviceProvider = new ServiceCollection() serviceProvider = new ServiceCollection()
.BuildBase(new MockEventHandler(true)) .BuildBase(new EventHandlerMock(true))
.BuildServiceProvider(); .BuildServiceProvider()
.SetupTestHooks();
mockEventHandler = serviceProvider.GetRequiredService<MockEventHandler>(); mockEventHandler = serviceProvider.GetRequiredService<EventHandlerMock>();
manager = serviceProvider.GetRequiredService<IManager>();
var mgr = serviceProvider.GetRequiredService<IManager>();
transLookup = serviceProvider.GetRequiredService<ITranslationLookup>(); transLookup = serviceProvider.GetRequiredService<ITranslationLookup>();
clientService = serviceProvider.GetRequiredService<ClientService>();
appConfig = serviceProvider.GetRequiredService<ApplicationConfiguration>();
A.CallTo(() => mgr.GetCommands()) A.CallTo(() => manager.GetClientService())
.Returns(clientService);
A.CallTo(() => clientService.UpdateLevel(A<Permission>.Ignored, A<EFClient>.Ignored, A<EFClient>.Ignored))
.Returns(Task.CompletedTask);
A.CallTo(() => manager.GetCommands())
.Returns(new Command[] .Returns(new Command[]
{ {
new ImpersonatableCommand(cmdConfig, transLookup), new ImpersonatableCommand(cmdConfig, transLookup),
new NonImpersonatableCommand(cmdConfig, transLookup) new NonImpersonatableCommand(cmdConfig, transLookup)
}); });
A.CallTo(() => mgr.AddEvent(A<GameEvent>.Ignored)) A.CallTo(() => manager.AddEvent(A<GameEvent>.Ignored))
.Invokes((fakeCall) => mockEventHandler.HandleEvent(mgr, fakeCall.Arguments[0] as GameEvent)); .Invokes((fakeCall) => mockEventHandler.HandleEvent(manager, fakeCall.Arguments[0] as GameEvent));
} }
#region RUNAS #region RUNAS
@ -174,5 +180,343 @@ namespace ApplicationTests
Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Command && !_event.Failed)); Assert.IsNotEmpty(mockEventHandler.Events.Where(_event => _event.Type == GameEvent.EventType.Command && !_event.Failed));
} }
#endregion #endregion
#region SETLEVEL
[Test]
public async Task Test_SetLevelFailOnSelf()
{
var cmd = new SetLevelCommand(cmdConfig, transLookup, logger);
var server = serviceProvider.GetRequiredService<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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<IW4MServer>();
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
} }
} }

View File

@ -3,9 +3,11 @@ using ApplicationTests.Mocks;
using FakeItEasy; using FakeItEasy;
using IW4MAdmin; using IW4MAdmin;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Database; using SharedLibraryCore.Database;
using SharedLibraryCore.Interfaces; using SharedLibraryCore.Interfaces;
using SharedLibraryCore.Services; using SharedLibraryCore.Services;
using System;
namespace ApplicationTests namespace ApplicationTests
{ {
@ -16,11 +18,11 @@ namespace ApplicationTests
if (eventHandler == null) if (eventHandler == null)
{ {
eventHandler = new MockEventHandler(); eventHandler = new EventHandlerMock();
serviceCollection.AddSingleton(eventHandler as MockEventHandler); serviceCollection.AddSingleton(eventHandler as EventHandlerMock);
} }
else if (eventHandler is MockEventHandler mockEventHandler) else if (eventHandler is EventHandlerMock mockEventHandler)
{ {
serviceCollection.AddSingleton(mockEventHandler); serviceCollection.AddSingleton(mockEventHandler);
} }
@ -42,7 +44,10 @@ namespace ApplicationTests
.AddSingleton<DataFileLoader>() .AddSingleton<DataFileLoader>()
.AddSingleton(A.Fake<ClientService>()) .AddSingleton(A.Fake<ClientService>())
.AddSingleton(A.Fake<IGameLogReaderFactory>()) .AddSingleton(A.Fake<IGameLogReaderFactory>())
.AddSingleton(eventHandler); .AddSingleton(eventHandler)
.AddSingleton(ConfigurationGenerators.CreateApplicationConfiguration())
.AddSingleton(ConfigurationGenerators.CreateCommandConfiguration())
.AddSingleton<IConfigurationHandler<ApplicationConfiguration>, ApplicationConfigurationHandlerMock>();
serviceCollection.AddSingleton(_sp => new IW4MServer(_sp.GetRequiredService<IManager>(), ConfigurationGenerators.CreateServerConfiguration(), serviceCollection.AddSingleton(_sp => new IW4MServer(_sp.GetRequiredService<IManager>(), ConfigurationGenerators.CreateServerConfiguration(),
_sp.GetRequiredService<ITranslationLookup>(), _sp.GetRequiredService<IRConConnectionFactory>(), _sp.GetRequiredService<IGameLogReaderFactory>()) _sp.GetRequiredService<ITranslationLookup>(), _sp.GetRequiredService<IRConConnectionFactory>(), _sp.GetRequiredService<IGameLogReaderFactory>())
@ -52,5 +57,14 @@ namespace ApplicationTests
return serviceCollection; return serviceCollection;
} }
public static IServiceProvider SetupTestHooks(this IServiceProvider serviceProvider)
{
var mgr = serviceProvider.GetRequiredService<IManager>();
A.CallTo(() => mgr.GetApplicationSettings())
.Returns(serviceProvider.GetRequiredService<IConfigurationHandler<ApplicationConfiguration>>());
return serviceProvider;
}
} }
} }

View File

@ -18,5 +18,7 @@ namespace ApplicationTests.Fixtures
Say = "say" Say = "say"
} }
}; };
public static ApplicationConfiguration CreateApplicationConfiguration() => new ApplicationConfiguration() { Servers = new[] { CreateServerConfiguration() } };
public static CommandConfiguration CreateCommandConfiguration() => new CommandConfiguration();
} }
} }

View File

@ -25,7 +25,8 @@ namespace ApplicationTests
private IManager fakeManager; private IManager fakeManager;
private IRConConnection fakeRConConnection; private IRConConnection fakeRConConnection;
private IRConParser fakeRConParser; private IRConParser fakeRConParser;
private MockEventHandler mockEventHandler; private EventHandlerMock mockEventHandler;
private ApplicationConfiguration appConfig;
[SetUp] [SetUp]
public void Setup() public void Setup()
@ -36,7 +37,8 @@ namespace ApplicationTests
fakeManager = serviceProvider.GetRequiredService<IManager>(); fakeManager = serviceProvider.GetRequiredService<IManager>();
fakeRConConnection = serviceProvider.GetRequiredService<IRConConnection>(); fakeRConConnection = serviceProvider.GetRequiredService<IRConConnection>();
fakeRConParser = serviceProvider.GetRequiredService<IRConParser>(); fakeRConParser = serviceProvider.GetRequiredService<IRConParser>();
mockEventHandler = serviceProvider.GetRequiredService<MockEventHandler>(); mockEventHandler = serviceProvider.GetRequiredService<EventHandlerMock>();
appConfig = serviceProvider.GetRequiredService<ApplicationConfiguration>();
var rconConnectionFactory = serviceProvider.GetRequiredService<IRConConnectionFactory>(); var rconConnectionFactory = serviceProvider.GetRequiredService<IRConConnectionFactory>();
@ -517,12 +519,7 @@ namespace ApplicationTests
{ {
var server = serviceProvider.GetService<IW4MServer>(); var server = serviceProvider.GetService<IW4MServer>();
var fakeConfigHandler = A.Fake<IConfigurationHandler<ApplicationConfiguration>>(); var fakeConfigHandler = A.Fake<IConfigurationHandler<ApplicationConfiguration>>();
appConfig.IgnoreServerConnectionLost = true;
A.CallTo(() => fakeManager.GetApplicationSettings())
.Returns(fakeConfigHandler);
A.CallTo(() => fakeConfigHandler.Configuration())
.Returns(new ApplicationConfiguration() { IgnoreServerConnectionLost = true });
A.CallTo(() => fakeRConParser.GetStatusAsync(A<IRConConnection>.Ignored)) A.CallTo(() => fakeRConParser.GetStatusAsync(A<IRConConnection>.Ignored))
.ThrowsAsync(new NetworkException("err")); .ThrowsAsync(new NetworkException("err"));
@ -535,7 +532,6 @@ namespace ApplicationTests
A.CallTo(() => fakeLogger.WriteError(A<string>.Ignored)) A.CallTo(() => fakeLogger.WriteError(A<string>.Ignored))
.MustNotHaveHappened(); .MustNotHaveHappened();
Assert.IsEmpty(mockEventHandler.Events);
} }
[Test] [Test]
@ -544,12 +540,6 @@ namespace ApplicationTests
var server = serviceProvider.GetService<IW4MServer>(); var server = serviceProvider.GetService<IW4MServer>();
var fakeConfigHandler = A.Fake<IConfigurationHandler<ApplicationConfiguration>>(); var fakeConfigHandler = A.Fake<IConfigurationHandler<ApplicationConfiguration>>();
A.CallTo(() => fakeManager.GetApplicationSettings())
.Returns(fakeConfigHandler);
A.CallTo(() => fakeConfigHandler.Configuration())
.Returns(new ApplicationConfiguration() { IgnoreServerConnectionLost = false });
A.CallTo(() => fakeRConParser.GetStatusAsync(A<IRConConnection>.Ignored)) A.CallTo(() => fakeRConParser.GetStatusAsync(A<IRConConnection>.Ignored))
.ThrowsAsync(new NetworkException("err")); .ThrowsAsync(new NetworkException("err"));
@ -568,7 +558,7 @@ namespace ApplicationTests
A.CallTo(() => fakeLogger.WriteError(A<string>.Ignored)) A.CallTo(() => fakeLogger.WriteError(A<string>.Ignored))
.MustHaveHappenedOnceExactly(); .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); Assert.AreEqual("err", (mockEventHandler.Events[0].Extra as NetworkException).Message);
} }
} }

View File

@ -0,0 +1,36 @@
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Interfaces;
using System;
using System.Threading.Tasks;
namespace ApplicationTests.Mocks
{
class ApplicationConfigurationHandlerMock : IConfigurationHandler<ApplicationConfiguration>
{
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();
}
}
}

View File

@ -4,12 +4,12 @@ using System.Collections.Generic;
namespace ApplicationTests.Mocks namespace ApplicationTests.Mocks
{ {
class MockEventHandler : IEventHandler class EventHandlerMock : IEventHandler
{ {
public IList<GameEvent> Events = new List<GameEvent>(); public IList<GameEvent> Events = new List<GameEvent>();
private readonly bool _autoExecute; private readonly bool _autoExecute;
public MockEventHandler(bool autoExecute = false) public EventHandlerMock(bool autoExecute = false)
{ {
_autoExecute = autoExecute; _autoExecute = autoExecute;
} }

View File

@ -2,6 +2,7 @@
using ApplicationTests.Mocks; using ApplicationTests.Mocks;
using FakeItEasy; using FakeItEasy;
using IW4MAdmin; using IW4MAdmin;
using IW4MAdmin.Application.Factories;
using IW4MAdmin.Application.Misc; using IW4MAdmin.Application.Misc;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using NUnit.Framework; using NUnit.Framework;
@ -24,14 +25,16 @@ namespace ApplicationTests
private static string PLUGIN_DIR = @"X:\IW4MAdmin\Plugins\ScriptPlugins"; private static string PLUGIN_DIR = @"X:\IW4MAdmin\Plugins\ScriptPlugins";
private IServiceProvider serviceProvider; private IServiceProvider serviceProvider;
private IManager fakeManager; private IManager fakeManager;
private MockEventHandler mockEventHandler; private EventHandlerMock mockEventHandler;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
serviceProvider = new ServiceCollection().BuildBase().BuildServiceProvider(); serviceProvider = new ServiceCollection().BuildBase()
.AddSingleton<IScriptCommandFactory, ScriptCommandFactory>()
.BuildServiceProvider();
fakeManager = serviceProvider.GetRequiredService<IManager>(); fakeManager = serviceProvider.GetRequiredService<IManager>();
mockEventHandler = serviceProvider.GetRequiredService<MockEventHandler>(); mockEventHandler = serviceProvider.GetRequiredService<EventHandlerMock>();
var rconConnectionFactory = serviceProvider.GetRequiredService<IRConConnectionFactory>(); var rconConnectionFactory = serviceProvider.GetRequiredService<IRConConnectionFactory>();
@ -62,7 +65,7 @@ namespace ApplicationTests
A.CallTo(() => fakeManager.GetClientService()) A.CallTo(() => fakeManager.GetClientService())
.Returns(fakeClientService); .Returns(fakeClientService);
await plugin.Initialize(serviceProvider.GetRequiredService<IManager>()); await plugin.Initialize(serviceProvider.GetRequiredService<IManager>(), serviceProvider.GetRequiredService<IScriptCommandFactory>());
var gameEvent = new GameEvent() var gameEvent = new GameEvent()
{ {

View File

@ -22,14 +22,17 @@ namespace ApplicationTests
{ {
ILogger logger; ILogger logger;
private IServiceProvider serviceProvider; private IServiceProvider serviceProvider;
private IConfigurationHandlerFactory handlerFactory;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
logger = A.Fake<ILogger>(); logger = A.Fake<ILogger>();
handlerFactory = A.Fake<IConfigurationHandlerFactory>();
serviceProvider = new ServiceCollection() serviceProvider = new ServiceCollection()
.BuildBase() .BuildBase()
.AddSingleton<IW4MAdmin.Plugins.Stats.Plugin>()
.BuildServiceProvider(); .BuildServiceProvider();
void testLog(string msg) => Console.WriteLine(msg); void testLog(string msg) => Console.WriteLine(msg);
@ -44,9 +47,8 @@ namespace ApplicationTests
public void TestKDR() public void TestKDR()
{ {
var mgr = A.Fake<IManager>(); var mgr = A.Fake<IManager>();
var handlerFactory = A.Fake<IConfigurationHandlerFactory>();
var config = A.Fake<IConfigurationHandler<StatsConfiguration>>(); var config = A.Fake<IConfigurationHandler<StatsConfiguration>>();
var plugin = new IW4MAdmin.Plugins.Stats.Plugin(handlerFactory, null); var plugin = serviceProvider.GetRequiredService<IW4MAdmin.Plugins.Stats.Plugin>();
A.CallTo(() => config.Configuration()) A.CallTo(() => config.Configuration())
.Returns(new StatsConfiguration() .Returns(new StatsConfiguration()