mirror of
https://github.com/RaidMax/IW4M-Admin.git
synced 2025-06-10 07:13:58 -05:00
refactor logging in pretty big overhaul
This commit is contained in:
@ -6,6 +6,7 @@ using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using static SharedLibraryCore.Server;
|
||||
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||
|
||||
namespace SharedLibraryCore
|
||||
{
|
||||
|
@ -12,6 +12,8 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog.Context;
|
||||
using static SharedLibraryCore.Database.Models.EFClient;
|
||||
|
||||
namespace SharedLibraryCore.Commands
|
||||
@ -646,7 +648,7 @@ namespace SharedLibraryCore.Commands
|
||||
/// </summary>
|
||||
public class SetLevelCommand : Command
|
||||
{
|
||||
public SetLevelCommand(CommandConfiguration config, ITranslationLookup translationLookup, ILogger logger) : base(config, translationLookup)
|
||||
public SetLevelCommand(CommandConfiguration config, ITranslationLookup translationLookup, ILogger<SetLevelCommand> logger) : base(config, translationLookup)
|
||||
{
|
||||
Name = "setlevel";
|
||||
Description = _translationLookup["COMMANDS_SETLEVEL_DESC"];
|
||||
@ -727,13 +729,16 @@ namespace SharedLibraryCore.Commands
|
||||
gameEvent.Owner.Manager.GetActiveClients()
|
||||
.FirstOrDefault(c => c.ClientId == targetClient?.ClientId) ?? targetClient : targetClient;
|
||||
|
||||
logger.WriteInfo($"Beginning set level of client {gameEvent.Origin} to {newPerm}");
|
||||
logger.LogDebug("Beginning set level of client {origin} to {newPermission}", gameEvent.Origin.ToString(), newPerm);
|
||||
|
||||
var result = await targetClient.SetLevel(newPerm, gameEvent.Origin).WaitAsync(Utilities.DefaultCommandTimeout, gameEvent.Owner.Manager.CancellationToken);
|
||||
|
||||
if (result.Failed)
|
||||
{
|
||||
logger.WriteInfo($"Failed to set level of client {gameEvent.Origin}");
|
||||
using (LogContext.PushProperty("Server", gameEvent.Origin.CurrentServer?.ToString()))
|
||||
{
|
||||
logger.LogWarning("Failed to set level of client {origin}", gameEvent.Origin.ToString());
|
||||
}
|
||||
gameEvent.Origin.Tell(_translationLookup["SERVER_ERROR_COMMAND_INGAME"]);
|
||||
return;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ using SharedLibraryCore.Events;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog.Context;
|
||||
|
||||
namespace SharedLibraryCore
|
||||
{
|
||||
@ -254,9 +256,6 @@ namespace SharedLibraryCore
|
||||
public void Complete()
|
||||
{
|
||||
_eventFinishedWaiter.Set();
|
||||
#if DEBUG
|
||||
Owner?.Logger.WriteDebug($"Completed internal for event {Id}");
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -266,11 +265,7 @@ namespace SharedLibraryCore
|
||||
public async Task<GameEvent> WaitAsync(TimeSpan timeSpan, CancellationToken token)
|
||||
{
|
||||
bool processed = false;
|
||||
|
||||
#if DEBUG
|
||||
Owner?.Logger.WriteDebug($"Begin wait for event {Id}");
|
||||
#endif
|
||||
|
||||
Utilities.DefaultLogger.LogDebug("Begin wait for event {Id}", Id);
|
||||
try
|
||||
{
|
||||
processed = await Task.Run(() => _eventFinishedWaiter.WaitOne(timeSpan), token);
|
||||
@ -283,14 +278,12 @@ namespace SharedLibraryCore
|
||||
|
||||
if (!processed)
|
||||
{
|
||||
Owner?.Logger.WriteError("Waiting for event to complete timed out");
|
||||
Owner?.Logger.WriteDebug($"{Id}, {Type}, {Data}, {Extra}, {FailReason.ToString()}, {Message}, {Origin}, {Target}");
|
||||
#if DEBUG
|
||||
//throw new Exception();
|
||||
#endif
|
||||
using(LogContext.PushProperty("Server", Owner?.ToString()))
|
||||
{
|
||||
Utilities.DefaultLogger.LogError("Waiting for event to complete timed out {@eventData}", new { Event = this, Message, Origin = Origin.ToString(), Target = Target.ToString()});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this lets us know if the the action timed out
|
||||
FailReason = FailReason == EventFailReason.None && !processed ? EventFailReason.Timeout : FailReason;
|
||||
return this;
|
||||
|
11
SharedLibraryCore/Exceptions/RConException.cs
Normal file
11
SharedLibraryCore/Exceptions/RConException.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace SharedLibraryCore.Exceptions
|
||||
{
|
||||
public class RConException : Exception
|
||||
{
|
||||
public RConException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
[Obsolete]
|
||||
public interface ILogger
|
||||
{
|
||||
void WriteVerbose(string msg);
|
||||
|
@ -6,6 +6,7 @@ using SharedLibraryCore.Database.Models;
|
||||
using System.Threading;
|
||||
using System.Collections;
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace SharedLibraryCore.Interfaces
|
||||
{
|
||||
@ -15,6 +16,7 @@ namespace SharedLibraryCore.Interfaces
|
||||
Task Start();
|
||||
void Stop();
|
||||
void Restart();
|
||||
[Obsolete]
|
||||
ILogger GetLogger(long serverId);
|
||||
IList<Server> GetServers();
|
||||
IList<IManagerCommand> GetCommands();
|
||||
|
@ -8,6 +8,8 @@ using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog.Context;
|
||||
|
||||
namespace SharedLibraryCore.Database.Models
|
||||
{
|
||||
@ -89,6 +91,7 @@ namespace SharedLibraryCore.Database.Models
|
||||
SetAdditionalProperty("_reportCount", 0);
|
||||
ReceivedPenalties = new List<EFPenalty>();
|
||||
_processingEvent = new SemaphoreSlim(1, 1);
|
||||
|
||||
}
|
||||
|
||||
~EFClient()
|
||||
@ -475,39 +478,42 @@ namespace SharedLibraryCore.Database.Models
|
||||
{
|
||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Name) || CleanedName.Replace(" ", "").Length < 3)
|
||||
using (LogContext.PushProperty("Server", CurrentServer?.ToString()))
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is too short");
|
||||
Kick(loc["SERVER_KICK_MINNAME"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(Name) || CleanedName.Replace(" ", "").Length < 3)
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation("Kicking {client} because their name is too short", ToString());
|
||||
Kick(loc["SERVER_KICK_MINNAME"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CurrentServer.Manager.GetApplicationSettings().Configuration()
|
||||
.DisallowedClientNames
|
||||
?.Any(_name => Regex.IsMatch(Name, _name)) ?? false)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is not allowed");
|
||||
Kick(loc["SERVER_KICK_GENERICNAME"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
if (CurrentServer.Manager.GetApplicationSettings().Configuration()
|
||||
.DisallowedClientNames
|
||||
?.Any(_name => Regex.IsMatch(Name, _name)) ?? false)
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation("Kicking {client} because their name is not allowed", ToString());
|
||||
Kick(loc["SERVER_KICK_GENERICNAME"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Name.Where(c => char.IsControl(c)).Count() > 0)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name contains control characters");
|
||||
Kick(loc["SERVER_KICK_CONTROLCHARS"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
if (Name.Where(c => char.IsControl(c)).Count() > 0)
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation("Kicking {client} because their name contains control characters", ToString());
|
||||
Kick(loc["SERVER_KICK_CONTROLCHARS"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
|
||||
// reserved slots stuff
|
||||
// todo: bots don't seem to honor party_maxplayers/sv_maxclients
|
||||
if (CurrentServer.MaxClients - (CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged() && !_client.IsBot)) < CurrentServer.ServerConfig.ReservedSlotNumber &&
|
||||
!this.IsPrivileged() &&
|
||||
CurrentServer.GetClientsAsList().Count <= CurrentServer.MaxClients &&
|
||||
CurrentServer.MaxClients != 0)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} their spot is reserved");
|
||||
Kick(loc["SERVER_KICK_SLOT_IS_RESERVED"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
// reserved slots stuff
|
||||
// todo: bots don't seem to honor party_maxplayers/sv_maxclients
|
||||
if (CurrentServer.MaxClients - (CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged() && !_client.IsBot)) < CurrentServer.ServerConfig.ReservedSlotNumber &&
|
||||
!this.IsPrivileged() &&
|
||||
CurrentServer.GetClientsAsList().Count <= CurrentServer.MaxClients &&
|
||||
CurrentServer.MaxClients != 0)
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation("Kicking {client} their spot is reserved", ToString());
|
||||
Kick(loc["SERVER_KICK_SLOT_IS_RESERVED"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -515,126 +521,151 @@ namespace SharedLibraryCore.Database.Models
|
||||
|
||||
public async Task OnDisconnect()
|
||||
{
|
||||
TotalConnectionTime += ConnectionLength;
|
||||
LastConnection = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
using (LogContext.PushProperty("Server", CurrentServer?.ToString()))
|
||||
{
|
||||
await CurrentServer.Manager.GetClientService().Update(this);
|
||||
}
|
||||
TotalConnectionTime += ConnectionLength;
|
||||
LastConnection = DateTime.UtcNow;
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
CurrentServer.Logger.WriteWarning($"Could not update disconnected player {this}");
|
||||
CurrentServer.Logger.WriteDebug(e.GetExceptionInfo());
|
||||
}
|
||||
Utilities.DefaultLogger.LogInformation("Client {client} is leaving the game", ToString());
|
||||
|
||||
finally
|
||||
{
|
||||
State = ClientState.Unknown;
|
||||
try
|
||||
{
|
||||
await CurrentServer.Manager.GetClientService().Update(this);
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
Utilities.DefaultLogger.LogError(e, "Could not update disconnected client {client}",
|
||||
ToString());
|
||||
}
|
||||
|
||||
finally
|
||||
{
|
||||
State = ClientState.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task OnJoin(int? ipAddress)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Start join for {this}::{ipAddress}::{Level.ToString()}");
|
||||
|
||||
if (ipAddress != null)
|
||||
using (LogContext.PushProperty("Server", CurrentServer?.ToString()))
|
||||
{
|
||||
IPAddress = ipAddress;
|
||||
await CurrentServer.Manager.GetClientService().UpdateAlias(this);
|
||||
CurrentServer.Logger.WriteDebug($"Updated alias for {this}");
|
||||
await CurrentServer.Manager.GetClientService().Update(this);
|
||||
CurrentServer.Logger.WriteDebug($"Updated client for {this}");
|
||||
Utilities.DefaultLogger.LogInformation("Client {client} is joining the game from {source}", ToString(), ipAddress.HasValue ? "Status" : "Log");
|
||||
|
||||
bool canConnect = await CanConnect(ipAddress);
|
||||
|
||||
if (!canConnect)
|
||||
if (ipAddress != null)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Client {this} is not allowed to join the server");
|
||||
IPAddress = ipAddress;
|
||||
Utilities.DefaultLogger.LogInformation("Received ip from client {client}", ToString());
|
||||
await CurrentServer.Manager.GetClientService().UpdateAlias(this);
|
||||
await CurrentServer.Manager.GetClientService().Update(this);
|
||||
|
||||
bool canConnect = await CanConnect(ipAddress);
|
||||
|
||||
if (!canConnect)
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation("Client {client} is not allowed to join the server",
|
||||
ToString());
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Utilities.DefaultLogger.LogDebug("Creating join event for {client}", ToString());
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Join,
|
||||
Origin = this,
|
||||
Target = this,
|
||||
Owner = CurrentServer,
|
||||
};
|
||||
|
||||
CurrentServer.Manager.AddEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Creating join event for {this}");
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Join,
|
||||
Origin = this,
|
||||
Target = this,
|
||||
Owner = CurrentServer,
|
||||
};
|
||||
|
||||
CurrentServer.Manager.AddEvent(e);
|
||||
Utilities.DefaultLogger.LogInformation("Waiting to receive ip from client {client}", ToString());
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Client {this} does not have an IP yet");
|
||||
Utilities.DefaultLogger.LogDebug("OnJoin finished for {client}", ToString());
|
||||
}
|
||||
|
||||
CurrentServer.Logger.WriteDebug($"OnJoin finished for {this}");
|
||||
}
|
||||
|
||||
public async Task<bool> CanConnect(int? ipAddress)
|
||||
{
|
||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||
var autoKickClient = Utilities.IW4MAdminClient(CurrentServer);
|
||||
|
||||
bool isAbleToConnectSimple = IsAbleToConnectSimple();
|
||||
|
||||
if (!isAbleToConnectSimple)
|
||||
using (LogContext.PushProperty("Server", CurrentServer?.ToString()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||
var autoKickClient = Utilities.IW4MAdminClient(CurrentServer);
|
||||
|
||||
// we want to get any penalties that are tied to their IP or AliasLink (but not necessarily their GUID)
|
||||
var activePenalties = await CurrentServer.Manager.GetPenaltyService().GetActivePenaltiesAsync(AliasLinkId, ipAddress);
|
||||
var banPenalty = activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Ban);
|
||||
var tempbanPenalty = activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.TempBan);
|
||||
var flagPenalty = activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag);
|
||||
bool isAbleToConnectSimple = IsAbleToConnectSimple();
|
||||
|
||||
// we want to kick them if any account is banned
|
||||
if (banPenalty != null)
|
||||
{
|
||||
if (Level == Permission.Banned)
|
||||
if (!isAbleToConnectSimple)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because they are banned");
|
||||
Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient);
|
||||
return false;
|
||||
}
|
||||
|
||||
else
|
||||
// we want to get any penalties that are tied to their IP or AliasLink (but not necessarily their GUID)
|
||||
var activePenalties = await CurrentServer.Manager.GetPenaltyService()
|
||||
.GetActivePenaltiesAsync(AliasLinkId, ipAddress);
|
||||
var banPenalty = activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Ban);
|
||||
var tempbanPenalty =
|
||||
activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.TempBan);
|
||||
var flagPenalty =
|
||||
activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag);
|
||||
|
||||
// we want to kick them if any account is banned
|
||||
if (banPenalty != null)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Client {this} is banned, but using a new GUID, we we're updating their level and kicking them");
|
||||
await SetLevel(Permission.Banned, autoKickClient).WaitAsync(Utilities.DefaultCommandTimeout, CurrentServer.Manager.CancellationToken);
|
||||
Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient);
|
||||
if (Level == Permission.Banned)
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation("Kicking {client} because they are banned", ToString());
|
||||
Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient);
|
||||
return false;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation(
|
||||
"Client {client} is banned, but using a new GUID, we we're updating their level and kicking them",
|
||||
ToString());
|
||||
await SetLevel(Permission.Banned, autoKickClient).WaitAsync(Utilities.DefaultCommandTimeout,
|
||||
CurrentServer.Manager.CancellationToken);
|
||||
Kick(loc["SERVER_BAN_PREV"].FormatExt(banPenalty?.Offense), autoKickClient);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// we want to kick them if any account is tempbanned
|
||||
if (tempbanPenalty != null)
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation("Kicking {client} because their GUID is temporarily banned",
|
||||
ToString());
|
||||
Kick(
|
||||
$"{loc["SERVER_TB_REMAIN"]} ({(tempbanPenalty.Expires.Value - DateTime.UtcNow).HumanizeForCurrentCulture()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})",
|
||||
autoKickClient);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// we want to kick them if any account is tempbanned
|
||||
if (tempbanPenalty != null)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their GUID is temporarily banned");
|
||||
Kick($"{loc["SERVER_TB_REMAIN"]} ({(tempbanPenalty.Expires.Value - DateTime.UtcNow).HumanizeForCurrentCulture()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient);
|
||||
return false;
|
||||
}
|
||||
// if we found a flag, we need to make sure all the accounts are flagged
|
||||
if (flagPenalty != null && Level != Permission.Flagged)
|
||||
{
|
||||
Utilities.DefaultLogger.LogInformation(
|
||||
"Flagged client {client} joining with new GUID, so we are changing their level to flagged",
|
||||
ToString());
|
||||
await SetLevel(Permission.Flagged, autoKickClient).WaitAsync(Utilities.DefaultCommandTimeout,
|
||||
CurrentServer.Manager.CancellationToken);
|
||||
}
|
||||
|
||||
// if we found a flag, we need to make sure all the accounts are flagged
|
||||
if (flagPenalty != null && Level != Permission.Flagged)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Flagged client {this} joining with new GUID, so we are changing their level to flagged");
|
||||
await SetLevel(Permission.Flagged, autoKickClient).WaitAsync(Utilities.DefaultCommandTimeout, CurrentServer.Manager.CancellationToken);
|
||||
}
|
||||
|
||||
// remove their auto flag
|
||||
if (Level == Permission.Flagged && !activePenalties.Any(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag))
|
||||
{
|
||||
// remove their auto flag status after a week
|
||||
CurrentServer.Logger.WriteInfo($"Unflagging {this} because the auto flag time has expired");
|
||||
Unflag(Utilities.CurrentLocalization.LocalizationIndex["SERVER_AUTOFLAG_UNFLAG"], autoKickClient);
|
||||
// remove their auto flag
|
||||
if (Level == Permission.Flagged &&
|
||||
!activePenalties.Any(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag))
|
||||
{
|
||||
// remove their auto flag status after a week
|
||||
Utilities.DefaultLogger.LogInformation("Unflagging {client} because the auto flag time has expired",
|
||||
ToString());
|
||||
Unflag(Utilities.CurrentLocalization.LocalizationIndex["SERVER_AUTOFLAG_UNFLAG"], autoKickClient);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -56,7 +56,8 @@ namespace SharedLibraryCore.RCon
|
||||
1 => TimeSpan.FromMilliseconds(550),
|
||||
2 => TimeSpan.FromMilliseconds(1000),
|
||||
3 => TimeSpan.FromMilliseconds(2000),
|
||||
_ => TimeSpan.FromMilliseconds(5000),
|
||||
4 => TimeSpan.FromMilliseconds(5000),
|
||||
_ => TimeSpan.FromMilliseconds(10000),
|
||||
};
|
||||
}
|
||||
/// <summary>
|
||||
@ -66,6 +67,6 @@ namespace SharedLibraryCore.RCon
|
||||
/// <summary>
|
||||
/// how many failed connection attempts before aborting connection
|
||||
/// </summary>
|
||||
public static readonly int AllowedConnectionFails = 4;
|
||||
public static readonly int AllowedConnectionFails = 5;
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,14 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog.Context;
|
||||
using SharedLibraryCore.Helpers;
|
||||
using SharedLibraryCore.Dtos;
|
||||
using SharedLibraryCore.Configuration;
|
||||
using SharedLibraryCore.Interfaces;
|
||||
using SharedLibraryCore.Database.Models;
|
||||
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||
|
||||
namespace SharedLibraryCore
|
||||
{
|
||||
@ -28,14 +30,15 @@ namespace SharedLibraryCore
|
||||
T7 = 8
|
||||
}
|
||||
|
||||
public Server(ServerConfiguration config, IManager mgr, IRConConnectionFactory rconConnectionFactory, IGameLogReaderFactory gameLogReaderFactory)
|
||||
public Server(ILogger<Server> logger, SharedLibraryCore.Interfaces.ILogger deprecatedLogger,
|
||||
ServerConfiguration config, IManager mgr, IRConConnectionFactory rconConnectionFactory,
|
||||
IGameLogReaderFactory gameLogReaderFactory)
|
||||
{
|
||||
Password = config.Password;
|
||||
IP = config.IPAddress;
|
||||
Port = config.Port;
|
||||
Manager = mgr;
|
||||
Logger = Manager.GetLogger(this.EndPoint);
|
||||
Logger.WriteInfo(this.ToString());
|
||||
Logger = deprecatedLogger;
|
||||
ServerConfig = config;
|
||||
RemoteConnection = rconConnectionFactory.CreateConnection(IP, Port, Password);
|
||||
EventProcessing = new SemaphoreSlim(1, 1);
|
||||
@ -47,6 +50,7 @@ namespace SharedLibraryCore
|
||||
CustomSayEnabled = Manager.GetApplicationSettings().Configuration().EnableCustomSayName;
|
||||
CustomSayName = Manager.GetApplicationSettings().Configuration().CustomSayName;
|
||||
this.gameLogReaderFactory = gameLogReaderFactory;
|
||||
ServerLogger = logger;
|
||||
InitializeTokens();
|
||||
InitializeAutoMessages();
|
||||
}
|
||||
@ -123,9 +127,7 @@ namespace SharedLibraryCore
|
||||
public GameEvent Broadcast(string message, EFClient sender = null)
|
||||
{
|
||||
string formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Say ?? "", $"{(CustomSayEnabled && GameName == Game.IW4 ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}");
|
||||
#if DEBUG == true
|
||||
Logger.WriteVerbose(message.StripColors());
|
||||
#endif
|
||||
ServerLogger.LogDebug("All->" + message.StripColors());
|
||||
|
||||
var e = new GameEvent()
|
||||
{
|
||||
@ -146,18 +148,27 @@ namespace SharedLibraryCore
|
||||
/// <param name="target">EFClient to send message to</param>
|
||||
protected async Task Tell(string message, EFClient target)
|
||||
{
|
||||
#if !DEBUG
|
||||
string formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Tell, target.ClientNumber, $"{(CustomSayEnabled && GameName == Game.IW4 ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}");
|
||||
if (target.ClientNumber > -1 && message.Length > 0 && target.Level != EFClient.Permission.Console)
|
||||
await this.ExecuteCommandAsync(formattedMessage);
|
||||
#else
|
||||
Logger.WriteVerbose($"{target.ClientNumber}->{message.StripColors()}");
|
||||
await Task.CompletedTask;
|
||||
#endif
|
||||
if (!Utilities.IsDevelopment)
|
||||
{
|
||||
var formattedMessage = string.Format(RconParser.Configuration.CommandPrefixes.Tell,
|
||||
target.ClientNumber,
|
||||
$"{(CustomSayEnabled && GameName == Game.IW4 ? $"{CustomSayName}: " : "")}{message.FixIW4ForwardSlash()}");
|
||||
if (target.ClientNumber > -1 && message.Length > 0 && target.Level != EFClient.Permission.Console)
|
||||
await this.ExecuteCommandAsync(formattedMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerLogger.LogDebug("Tell[{clientNumber}]->{message}", target.ClientNumber, message.StripColors());
|
||||
}
|
||||
|
||||
|
||||
if (target.Level == EFClient.Permission.Console)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Green;
|
||||
using (LogContext.PushProperty("Server", ToString()))
|
||||
{
|
||||
ServerLogger.LogInformation("Command output received: {message}", message);
|
||||
}
|
||||
Console.WriteLine(message.StripColors());
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
}
|
||||
@ -280,7 +291,8 @@ namespace SharedLibraryCore
|
||||
|
||||
// Objects
|
||||
public IManager Manager { get; protected set; }
|
||||
public ILogger Logger { get; private set; }
|
||||
[Obsolete]
|
||||
public SharedLibraryCore.Interfaces.ILogger Logger { get; private set; }
|
||||
public ServerConfiguration ServerConfig { get; private set; }
|
||||
public List<Map> Maps { get; protected set; } = new List<Map>();
|
||||
public List<Report> Reports { get; set; }
|
||||
@ -319,6 +331,7 @@ namespace SharedLibraryCore
|
||||
public string IP { get; protected set; }
|
||||
public string Version { get; protected set; }
|
||||
public bool IsInitialized { get; set; }
|
||||
protected readonly ILogger ServerLogger;
|
||||
|
||||
public int Port { get; private set; }
|
||||
protected string FSGame;
|
||||
|
@ -5,11 +5,20 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||
|
||||
namespace SharedLibraryCore.Services
|
||||
{
|
||||
public class ChangeHistoryService : IEntityService<EFChangeHistory>
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ChangeHistoryService(ILogger<ChangeHistoryService> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public Task<EFChangeHistory> Create(EFChangeHistory entity)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
@ -79,8 +88,7 @@ namespace SharedLibraryCore.Services
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
e.Owner.Logger.WriteWarning(ex.Message);
|
||||
e.Owner.Logger.WriteDebug(ex.GetExceptionInfo());
|
||||
_logger.LogError(ex, "Could not persist change @{change}", change);
|
||||
}
|
||||
|
||||
finally
|
||||
|
@ -8,22 +8,28 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Serilog.Context;
|
||||
using static SharedLibraryCore.Database.Models.EFClient;
|
||||
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||
|
||||
namespace SharedLibraryCore.Services
|
||||
{
|
||||
public class ClientService : IEntityService<EFClient>, IResourceQueryHelper<FindClientRequest, FindClientResult>
|
||||
{
|
||||
private readonly IDatabaseContextFactory _contextFactory;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public ClientService(IDatabaseContextFactory databaseContextFactory)
|
||||
public ClientService(ILogger<ClientService> logger, IDatabaseContextFactory databaseContextFactory)
|
||||
{
|
||||
_contextFactory = databaseContextFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<EFClient> Create(EFClient entity)
|
||||
{
|
||||
using (var context = new DatabaseContext())
|
||||
using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString()))
|
||||
{
|
||||
int? linkId = null;
|
||||
int? aliasId = null;
|
||||
@ -40,13 +46,13 @@ namespace SharedLibraryCore.Services
|
||||
{
|
||||
linkId = existingAliases.OrderBy(_alias => _alias.LinkId).First().LinkId;
|
||||
|
||||
entity.CurrentServer.Logger.WriteDebug($"[create] client with new GUID {entity} has existing link {linkId}");
|
||||
_logger.LogDebug("[create] client with new GUID {entity} has existing link {linkId}", entity.ToString(), linkId);
|
||||
|
||||
var existingExactAlias = existingAliases.FirstOrDefault(_alias => _alias.Name == entity.Name);
|
||||
|
||||
if (existingExactAlias != null)
|
||||
{
|
||||
entity.CurrentServer.Logger.WriteDebug($"[create] client with new GUID {entity} has existing alias {existingExactAlias.AliasId}");
|
||||
_logger.LogDebug("[create] client with new GUID {entity} has existing alias {aliasId}", entity.ToString(), existingExactAlias.AliasId);
|
||||
aliasId = existingExactAlias.AliasId;
|
||||
}
|
||||
}
|
||||
@ -60,13 +66,13 @@ namespace SharedLibraryCore.Services
|
||||
NetworkId = entity.NetworkId
|
||||
};
|
||||
|
||||
entity.CurrentServer.Logger.WriteDebug($"[create] adding {entity} to context");
|
||||
_logger.LogDebug("[create] adding {entity} to context", entity.ToString());
|
||||
context.Clients.Add(client);
|
||||
|
||||
// they're just using a new GUID
|
||||
if (aliasId.HasValue)
|
||||
{
|
||||
entity.CurrentServer.Logger.WriteDebug($"[create] setting {entity}'s alias id and linkid to ({aliasId.Value}, {linkId.Value})");
|
||||
_logger.LogDebug("[create] setting {entity}'s alias id and linkid to ({aliasId}, {linkId})", entity.ToString(), aliasId, linkId);
|
||||
client.CurrentAliasId = aliasId.Value;
|
||||
client.AliasLinkId = linkId.Value;
|
||||
}
|
||||
@ -74,7 +80,7 @@ namespace SharedLibraryCore.Services
|
||||
// link was found but they don't have an exact alias
|
||||
else if (!aliasId.HasValue && linkId.HasValue)
|
||||
{
|
||||
entity.CurrentServer.Logger.WriteDebug($"[create] setting {entity}'s linkid to {linkId.Value}, but creating new alias");
|
||||
_logger.LogDebug("[create] setting {entity}'s linkid to {linkId}, but creating new alias", entity.ToString(), linkId);
|
||||
client.AliasLinkId = linkId.Value;
|
||||
client.CurrentAlias = new EFAlias()
|
||||
{
|
||||
@ -89,7 +95,7 @@ namespace SharedLibraryCore.Services
|
||||
// brand new players (supposedly)
|
||||
else
|
||||
{
|
||||
entity.CurrentServer.Logger.WriteDebug($"[create] creating new Link and Alias for {entity}");
|
||||
_logger.LogDebug("[create] creating new Link and Alias for {entity}", entity.ToString());
|
||||
var link = new EFAliasLink();
|
||||
var alias = new EFAlias()
|
||||
{
|
||||
@ -114,129 +120,139 @@ namespace SharedLibraryCore.Services
|
||||
|
||||
private async Task UpdateAlias(string originalName, int? ip, EFClient entity, DatabaseContext context)
|
||||
{
|
||||
string name = originalName.CapClientName(EFAlias.MAX_NAME_LENGTH);
|
||||
|
||||
// entity is the tracked db context item
|
||||
// get all aliases by IP address and LinkId
|
||||
var iqAliases = context.Aliases
|
||||
.Include(a => a.Link)
|
||||
// we only want alias that have the same IP address or share a link
|
||||
.Where(_alias => _alias.IPAddress == ip || (_alias.LinkId == entity.AliasLinkId));
|
||||
|
||||
var aliases = await iqAliases.ToListAsync();
|
||||
var currentIPs = aliases.Where(_a2 => _a2.IPAddress != null).Select(_a2 => _a2.IPAddress).Distinct();
|
||||
var floatingIPAliases = await context.Aliases.Where(_alias => currentIPs.Contains(_alias.IPAddress)).ToListAsync();
|
||||
aliases.AddRange(floatingIPAliases);
|
||||
|
||||
// see if they have a matching IP + Name but new NetworkId
|
||||
var existingExactAlias = aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault(a => a.Name == name && a.IPAddress == ip);
|
||||
bool hasExactAliasMatch = existingExactAlias != null;
|
||||
|
||||
// if existing alias matches link them
|
||||
var newAliasLink = existingExactAlias?.Link;
|
||||
// if no exact matches find the first IP or LinkId that matches
|
||||
newAliasLink = newAliasLink ?? aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault()?.Link;
|
||||
// if no matches are found, use our current one ( it will become permanent )
|
||||
newAliasLink = newAliasLink ?? entity.AliasLink;
|
||||
|
||||
bool hasExistingAlias = aliases.Count > 0;
|
||||
bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId;
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
int distinctLinkCount = aliases.Select(_alias => _alias.LinkId).Distinct().Count();
|
||||
// this happens when the link we found is different than the one we create before adding an IP
|
||||
if (isAliasLinkUpdated || distinctLinkCount > 1)
|
||||
using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString()))
|
||||
{
|
||||
entity.CurrentServer.Logger.WriteDebug($"[updatealias] found a link for {entity} so we are updating link from {entity.AliasLink.AliasLinkId} to {newAliasLink.AliasLinkId}");
|
||||
string name = originalName.CapClientName(EFAlias.MAX_NAME_LENGTH);
|
||||
|
||||
var completeAliasLinkIds = aliases.Select(_item => _item.LinkId)
|
||||
.Append(entity.AliasLinkId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
// entity is the tracked db context item
|
||||
// get all aliases by IP address and LinkId
|
||||
var iqAliases = context.Aliases
|
||||
.Include(a => a.Link)
|
||||
// we only want alias that have the same IP address or share a link
|
||||
.Where(_alias => _alias.IPAddress == ip || (_alias.LinkId == entity.AliasLinkId));
|
||||
|
||||
entity.CurrentServer.Logger.WriteDebug($"[updatealias] updating aliasLinks {string.Join(',', completeAliasLinkIds)} for IP {ip} to {newAliasLink.AliasLinkId}");
|
||||
var aliases = await iqAliases.ToListAsync();
|
||||
var currentIPs = aliases.Where(_a2 => _a2.IPAddress != null).Select(_a2 => _a2.IPAddress).Distinct();
|
||||
var floatingIPAliases = await context.Aliases.Where(_alias => currentIPs.Contains(_alias.IPAddress))
|
||||
.ToListAsync();
|
||||
aliases.AddRange(floatingIPAliases);
|
||||
|
||||
// update all the clients that have the old alias link
|
||||
await context.Clients
|
||||
.Where(_client => completeAliasLinkIds.Contains(_client.AliasLinkId))
|
||||
.ForEachAsync(_client => _client.AliasLinkId = newAliasLink.AliasLinkId);
|
||||
// see if they have a matching IP + Name but new NetworkId
|
||||
var existingExactAlias = aliases.OrderBy(_alias => _alias.LinkId)
|
||||
.FirstOrDefault(a => a.Name == name && a.IPAddress == ip);
|
||||
bool hasExactAliasMatch = existingExactAlias != null;
|
||||
|
||||
// we also need to update all the penalties or they get deleted
|
||||
// scenario
|
||||
// link1 joins with ip1
|
||||
// link2 joins with ip2,
|
||||
// link2 receives penalty
|
||||
// link2 joins with ip1
|
||||
// pre existing link for link2 detected
|
||||
// link2 is deleted
|
||||
// link2 penalties are orphaned
|
||||
await context.Penalties
|
||||
.Where(_penalty => completeAliasLinkIds.Contains(_penalty.LinkId))
|
||||
.ForEachAsync(_penalty => _penalty.LinkId = newAliasLink.AliasLinkId);
|
||||
// if existing alias matches link them
|
||||
var newAliasLink = existingExactAlias?.Link;
|
||||
// if no exact matches find the first IP or LinkId that matches
|
||||
newAliasLink = newAliasLink ?? aliases.OrderBy(_alias => _alias.LinkId).FirstOrDefault()?.Link;
|
||||
// if no matches are found, use our current one ( it will become permanent )
|
||||
newAliasLink = newAliasLink ?? entity.AliasLink;
|
||||
|
||||
entity.AliasLink = newAliasLink;
|
||||
entity.AliasLinkId = newAliasLink.AliasLinkId;
|
||||
|
||||
// update all previous aliases
|
||||
await context.Aliases
|
||||
.Where(_alias => completeAliasLinkIds.Contains(_alias.LinkId))
|
||||
.ForEachAsync(_alias => _alias.LinkId = newAliasLink.AliasLinkId);
|
||||
bool hasExistingAlias = aliases.Count > 0;
|
||||
bool isAliasLinkUpdated = newAliasLink.AliasLinkId != entity.AliasLink.AliasLinkId;
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
// we want to delete the now inactive alias
|
||||
if (newAliasLink.AliasLinkId != entity.AliasLinkId)
|
||||
int distinctLinkCount = aliases.Select(_alias => _alias.LinkId).Distinct().Count();
|
||||
// this happens when the link we found is different than the one we create before adding an IP
|
||||
if (isAliasLinkUpdated || distinctLinkCount > 1)
|
||||
{
|
||||
context.AliasLinks.Remove(entity.AliasLink);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
_logger.LogDebug(
|
||||
"[updatealias] found a link for {entity} so we are updating link from {oldAliasLinkId} to {newAliasLinkId}",
|
||||
entity.ToString(), entity.AliasLink.AliasLinkId, newAliasLink.AliasLinkId);
|
||||
|
||||
// the existing alias matches ip and name, so we can just ignore the temporary one
|
||||
if (hasExactAliasMatch)
|
||||
{
|
||||
entity.CurrentServer.Logger.WriteDebug($"[updatealias] {entity} has exact alias match");
|
||||
var completeAliasLinkIds = aliases.Select(_item => _item.LinkId)
|
||||
.Append(entity.AliasLinkId)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
var oldAlias = entity.CurrentAlias;
|
||||
entity.CurrentAliasId = existingExactAlias.AliasId;
|
||||
entity.CurrentAlias = existingExactAlias;
|
||||
await context.SaveChangesAsync();
|
||||
_logger.LogDebug("[updatealias] updating aliasLinks {links} for IP {ip} to {linkId}",
|
||||
string.Join(',', completeAliasLinkIds), ip, newAliasLink.AliasLinkId);
|
||||
|
||||
// the alias is the same so we can just remove it
|
||||
if (oldAlias.AliasId != existingExactAlias.AliasId && oldAlias.AliasId > 0)
|
||||
{
|
||||
// update all the clients that have the old alias link
|
||||
await context.Clients
|
||||
.Where(_client => _client.CurrentAliasId == oldAlias.AliasId)
|
||||
.ForEachAsync(_client => _client.CurrentAliasId = existingExactAlias.AliasId);
|
||||
.Where(_client => completeAliasLinkIds.Contains(_client.AliasLinkId))
|
||||
.ForEachAsync(_client => _client.AliasLinkId = newAliasLink.AliasLinkId);
|
||||
|
||||
// we also need to update all the penalties or they get deleted
|
||||
// scenario
|
||||
// link1 joins with ip1
|
||||
// link2 joins with ip2,
|
||||
// link2 receives penalty
|
||||
// link2 joins with ip1
|
||||
// pre existing link for link2 detected
|
||||
// link2 is deleted
|
||||
// link2 penalties are orphaned
|
||||
await context.Penalties
|
||||
.Where(_penalty => completeAliasLinkIds.Contains(_penalty.LinkId))
|
||||
.ForEachAsync(_penalty => _penalty.LinkId = newAliasLink.AliasLinkId);
|
||||
|
||||
entity.AliasLink = newAliasLink;
|
||||
entity.AliasLinkId = newAliasLink.AliasLinkId;
|
||||
|
||||
// update all previous aliases
|
||||
await context.Aliases
|
||||
.Where(_alias => completeAliasLinkIds.Contains(_alias.LinkId))
|
||||
.ForEachAsync(_alias => _alias.LinkId = newAliasLink.AliasLinkId);
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
if (context.Entry(oldAlias).State != EntityState.Deleted)
|
||||
// we want to delete the now inactive alias
|
||||
if (newAliasLink.AliasLinkId != entity.AliasLinkId)
|
||||
{
|
||||
entity.CurrentServer.Logger.WriteDebug($"[updatealias] {entity} has exact alias match, so we're going to try to remove aliasId {oldAlias.AliasId} with linkId {oldAlias.AliasId}");
|
||||
context.Aliases.Remove(oldAlias);
|
||||
context.AliasLinks.Remove(entity.AliasLink);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// theres no exact match, but they've played before with the GUID or IP
|
||||
else
|
||||
{
|
||||
entity.CurrentServer.Logger.WriteDebug($"[updatealias] {entity} is using a new alias");
|
||||
|
||||
var newAlias = new EFAlias()
|
||||
// the existing alias matches ip and name, so we can just ignore the temporary one
|
||||
if (hasExactAliasMatch)
|
||||
{
|
||||
DateAdded = DateTime.UtcNow,
|
||||
IPAddress = ip,
|
||||
LinkId = newAliasLink.AliasLinkId,
|
||||
Name = name,
|
||||
SearchableName = name.StripColors().ToLower(),
|
||||
Active = true,
|
||||
};
|
||||
_logger.LogDebug("[updatealias] {entity} has exact alias match", entity.ToString());
|
||||
|
||||
entity.CurrentAlias = newAlias;
|
||||
entity.CurrentAliasId = 0;
|
||||
await context.SaveChangesAsync();
|
||||
var oldAlias = entity.CurrentAlias;
|
||||
entity.CurrentAliasId = existingExactAlias.AliasId;
|
||||
entity.CurrentAlias = existingExactAlias;
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
// the alias is the same so we can just remove it
|
||||
if (oldAlias.AliasId != existingExactAlias.AliasId && oldAlias.AliasId > 0)
|
||||
{
|
||||
await context.Clients
|
||||
.Where(_client => _client.CurrentAliasId == oldAlias.AliasId)
|
||||
.ForEachAsync(_client => _client.CurrentAliasId = existingExactAlias.AliasId);
|
||||
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
if (context.Entry(oldAlias).State != EntityState.Deleted)
|
||||
{
|
||||
_logger.LogDebug(
|
||||
"[updatealias] {entity} has exact alias match, so we're going to try to remove aliasId {aliasId} with linkId {linkId}",
|
||||
entity.ToString(), oldAlias.AliasId, oldAlias.LinkId);
|
||||
context.Aliases.Remove(oldAlias);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// theres no exact match, but they've played before with the GUID or IP
|
||||
else
|
||||
{
|
||||
_logger.LogDebug("[updatealias] {entity} is using a new alias", entity.ToString());
|
||||
|
||||
var newAlias = new EFAlias()
|
||||
{
|
||||
DateAdded = DateTime.UtcNow,
|
||||
IPAddress = ip,
|
||||
LinkId = newAliasLink.AliasLinkId,
|
||||
Name = name,
|
||||
SearchableName = name.StripColors().ToLower(),
|
||||
Active = true,
|
||||
};
|
||||
|
||||
entity.CurrentAlias = newAlias;
|
||||
entity.CurrentAliasId = 0;
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,29 +277,29 @@ namespace SharedLibraryCore.Services
|
||||
entity.Level = newPermission;
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
#if DEBUG == true
|
||||
temporalClient.CurrentServer.Logger.WriteDebug($"Updated {temporalClient.ClientId} to {newPermission}");
|
||||
#endif
|
||||
|
||||
var linkedPermissionSet = new[] { Permission.Banned, Permission.Flagged };
|
||||
// if their permission level has been changed to level that needs to be updated on all accounts
|
||||
if (linkedPermissionSet.Contains(newPermission) || linkedPermissionSet.Contains(oldPermission))
|
||||
using (LogContext.PushProperty("Server", entity?.CurrentServer?.ToString()))
|
||||
{
|
||||
//get all clients that have the same linkId
|
||||
var iqMatchingClients = ctx.Clients
|
||||
.Where(_client => _client.AliasLinkId == entity.AliasLinkId);
|
||||
_logger.LogInformation("Updated {clientId} to {newPermission}", temporalClient.ClientId, newPermission);
|
||||
|
||||
// this updates the level for all the clients with the same LinkId
|
||||
// only if their new level is flagged or banned
|
||||
await iqMatchingClients.ForEachAsync(_client =>
|
||||
var linkedPermissionSet = new[] {Permission.Banned, Permission.Flagged};
|
||||
// if their permission level has been changed to level that needs to be updated on all accounts
|
||||
if (linkedPermissionSet.Contains(newPermission) || linkedPermissionSet.Contains(oldPermission))
|
||||
{
|
||||
_client.Level = newPermission;
|
||||
#if DEBUG == true
|
||||
temporalClient.CurrentServer.Logger.WriteDebug($"Updated linked {_client.ClientId} to {newPermission}");
|
||||
#endif
|
||||
});
|
||||
//get all clients that have the same linkId
|
||||
var iqMatchingClients = ctx.Clients
|
||||
.Where(_client => _client.AliasLinkId == entity.AliasLinkId);
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
// this updates the level for all the clients with the same LinkId
|
||||
// only if their new level is flagged or banned
|
||||
await iqMatchingClients.ForEachAsync(_client =>
|
||||
{
|
||||
_client.Level = newPermission;
|
||||
_logger.LogInformation("Updated linked {clientId} to {newPermission}", _client.ClientId,
|
||||
newPermission);
|
||||
});
|
||||
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -432,7 +448,7 @@ namespace SharedLibraryCore.Services
|
||||
{
|
||||
if (temporalClient.ClientId < 1)
|
||||
{
|
||||
temporalClient.CurrentServer?.Logger.WriteDebug($"[update] {temporalClient} needs to be updated but they do not have a valid client id, ignoring..");
|
||||
_logger.LogDebug("[update] {client} needs to be updated but they do not have a valid client id, ignoring..", temporalClient.ToString());
|
||||
// note: we never do anything with the result of this so we can safely return null
|
||||
return null;
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<ApplicationIcon />
|
||||
<StartupObject />
|
||||
<PackageId>RaidMax.IW4MAdmin.SharedLibraryCore</PackageId>
|
||||
<Version>2.4.10</Version>
|
||||
<Authors>RaidMax</Authors>
|
||||
@ -21,8 +19,9 @@
|
||||
<IsPackable>true</IsPackable>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<Description>Shared Library for IW4MAdmin</Description>
|
||||
<AssemblyVersion>2.4.10.0</AssemblyVersion>
|
||||
<FileVersion>2.4.10.0</FileVersion>
|
||||
<AssemblyVersion>2020.11.11.1</AssemblyVersion>
|
||||
<FileVersion>2020.11.11.1</FileVersion>
|
||||
<PackageVersion>2020.11.11.1</PackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Prerelease|AnyCPU'">
|
||||
@ -54,6 +53,7 @@
|
||||
<PackageReference Include="Npgsql" Version="4.1.4" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.2" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
|
||||
<PackageReference Include="SimpleCrypto.NetCore" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -17,14 +17,18 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using static SharedLibraryCore.Database.Models.EFClient;
|
||||
using static SharedLibraryCore.Database.Models.EFPenalty;
|
||||
using static SharedLibraryCore.Server;
|
||||
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||
|
||||
namespace SharedLibraryCore
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
// note: this is only to be used by classes not created by dependency injection
|
||||
public static ILogger DefaultLogger { get; set; }
|
||||
#if DEBUG == true
|
||||
public static string OperatingDirectory => $"{Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)}{Path.DirectorySeparatorChar}";
|
||||
#else
|
||||
@ -881,8 +885,7 @@ namespace SharedLibraryCore
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.WriteWarning($"Could not create penalty of type {penalty.Type.ToString()}");
|
||||
logger.WriteDebug(e.GetExceptionInfo());
|
||||
logger.LogError(e, $"Could not create penalty of type {penalty.Type.ToString()}");
|
||||
}
|
||||
|
||||
return false;
|
||||
|
Reference in New Issue
Block a user