diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index e2b76107..86ce545d 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -462,7 +462,7 @@ namespace IW4MAdmin Link = E.Target.AliasLink }; - var addedPenalty = await Manager.GetPenaltyService().Create(newPenalty); + await Manager.GetPenaltyService().Create(newPenalty); E.Target.SetLevel(Permission.Flagged, E.Origin); } diff --git a/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs b/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs index d9c8bbdd..7b1494e5 100644 --- a/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs +++ b/Application/Meta/ReceivedPenaltyResourceQueryHelper.cs @@ -1,10 +1,12 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Data.Abstractions; using Data.Models; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using SharedLibraryCore; +using SharedLibraryCore.Configuration; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Helpers; using SharedLibraryCore.Interfaces; @@ -21,11 +23,14 @@ namespace IW4MAdmin.Application.Meta { private readonly ILogger _logger; private readonly IDatabaseContextFactory _contextFactory; + private readonly ApplicationConfiguration _appConfig; - public ReceivedPenaltyResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory) + public ReceivedPenaltyResourceQueryHelper(ILogger logger, + IDatabaseContextFactory contextFactory, ApplicationConfiguration appConfig) { _contextFactory = contextFactory; _logger = logger; + _appConfig = appConfig; } public async Task> QueryResource(ClientPaginationRequest query) @@ -39,11 +44,30 @@ namespace IW4MAdmin.Application.Meta .FirstOrDefaultAsync(); var iqPenalties = ctx.Penalties.AsNoTracking() - .Where(_penalty => _penalty.OffenderId == query.ClientId || (linkedPenaltyType.Contains(_penalty.Type) && _penalty.LinkId == linkId)) - .Where(_penalty => _penalty.When < query.Before) - .OrderByDescending(_penalty => _penalty.When); + .Where(_penalty => _penalty.OffenderId == query.ClientId || + linkedPenaltyType.Contains(_penalty.Type) && _penalty.LinkId == linkId); - var penalties = await iqPenalties + var iqIpLinkedPenalties = new List().AsQueryable(); + + if (!_appConfig.EnableImplicitAccountLinking) + { + var usedIps = await ctx.Aliases.AsNoTracking() + .Where(alias => alias.LinkId == linkId && alias.IPAddress != null) + .Select(alias => alias.IPAddress).ToListAsync(); + + var aliasedIds = await ctx.Aliases.AsNoTracking().Where(alias => usedIps.Contains(alias.IPAddress)) + .Select(alias => alias.LinkId) + .ToListAsync(); + + iqIpLinkedPenalties = ctx.Penalties.AsNoTracking() + .Where(penalty => + linkedPenaltyType.Contains(penalty.Type) && + /*usedIps.Contains(penalty.Offender.CurrentAlias.IPAddress)*/aliasedIds.Contains(penalty.LinkId)); + } + + var penalties = await iqPenalties.Union(iqIpLinkedPenalties) + .Where(_penalty => _penalty.When < query.Before) + .OrderByDescending(_penalty => _penalty.When) .Take(query.Count) .Select(_penalty => new ReceivedPenaltyResponse() { diff --git a/SharedLibraryCore/PartialEntities/EFClient.cs b/SharedLibraryCore/PartialEntities/EFClient.cs index 0bd2c97e..2fd5d8dd 100644 --- a/SharedLibraryCore/PartialEntities/EFClient.cs +++ b/SharedLibraryCore/PartialEntities/EFClient.cs @@ -594,22 +594,13 @@ namespace SharedLibraryCore.Database.Models // we want to kick them if any account is banned if (banPenalty != null) { - if (enableImplicitLinking) - { - if (Level != Permission.Banned) - { - 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); - } - } - if (Level != Permission.Banned) { - Ban(banPenalty.Offense, autoKickClient, true); - return false; + Utilities.DefaultLogger.LogInformation( + "Client {client} has a ban penalty, but they're 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); } Utilities.DefaultLogger.LogInformation("Kicking {client} because they are banned", ToString()); diff --git a/SharedLibraryCore/Services/PenaltyService.cs b/SharedLibraryCore/Services/PenaltyService.cs index 28e3b1da..cd7eeaef 100644 --- a/SharedLibraryCore/Services/PenaltyService.cs +++ b/SharedLibraryCore/Services/PenaltyService.cs @@ -9,6 +9,7 @@ using System.Linq.Expressions; using System.Threading.Tasks; using Data.Abstractions; using Data.Models; +using SharedLibraryCore.Configuration; using SharedLibraryCore.Interfaces; namespace SharedLibraryCore.Services @@ -16,10 +17,12 @@ namespace SharedLibraryCore.Services public class PenaltyService : IEntityService { private readonly IDatabaseContextFactory _contextFactory; + private readonly ApplicationConfiguration _appConfig; - public PenaltyService(IDatabaseContextFactory contextFactory) + public PenaltyService(IDatabaseContextFactory contextFactory, ApplicationConfiguration appConfig) { _contextFactory = contextFactory; + _appConfig = appConfig; } public virtual async Task Create(EFPenalty newEntity) @@ -75,7 +78,7 @@ namespace SharedLibraryCore.Services await using var context = _contextFactory.CreateContext(false); var iqPenalties = context.Penalties .Where(p => showOnly == EFPenalty.PenaltyType.Any ? p.Type != EFPenalty.PenaltyType.Any : p.Type == showOnly) - .Where(_penalty => ignoreAutomated ? _penalty.PunisherId != 1 : true) + .Where(_penalty => !ignoreAutomated || _penalty.PunisherId != 1) .OrderByDescending(p => p.When) .Skip(offset) .Take(count) @@ -145,7 +148,7 @@ namespace SharedLibraryCore.Services { var now = DateTime.UtcNow; - Expression> filter = (p) => (new EFPenalty.PenaltyType[] + Expression> filter = (p) => (new [] { EFPenalty.PenaltyType.TempBan, EFPenalty.PenaltyType.Ban, @@ -159,33 +162,43 @@ namespace SharedLibraryCore.Services .Where(p => p.LinkId == linkId) .Where(filter); - var iqIPPenalties = context.Aliases - .Where(a => a.IPAddress != null && a.IPAddress == ip) - .SelectMany(a => a.Link.ReceivedPenalties) - .Where(filter); + var iqIpPenalties = _appConfig.EnableImplicitAccountLinking + ? context.Aliases + .Where(a => a.IPAddress != null && a.IPAddress == ip) + .SelectMany(a => a.Link.ReceivedPenalties) + .Where(filter) + : context.Penalties.Where(penalty => + penalty.Offender.CurrentAlias.IPAddress != null && + penalty.Offender.CurrentAlias.IPAddress == ip) + .Where(filter); var activePenalties = (await iqLinkPenalties.ToListAsync()) - .Union(await iqIPPenalties.ToListAsync()) + .Union(await iqIpPenalties.ToListAsync()) .Distinct(); // this is a bit more performant in memory (ordering) return activePenalties.OrderByDescending(p => p.When).ToList(); } - public virtual async Task RemoveActivePenalties(int aliasLinkId) + public virtual async Task RemoveActivePenalties(int aliasLinkId, int? ipAddress = null) { await using var context = _contextFactory.CreateContext(); var now = DateTime.UtcNow; - await context.Penalties + var penaltiesByLink = context.Penalties .Where(p => p.LinkId == aliasLinkId) - .Where(p => p.Expires > now || p.Expires == null) - .ForEachAsync(p => - { - p.Active = false; - p.Expires = now; - }); + .Where(p => p.Expires > now || p.Expires == null); + var penaltiesByIp = context.Penalties + .Where(p => p.Offender.CurrentAlias.IPAddress != null && p.Offender.CurrentAlias.IPAddress == null) + .Where(p => p.Expires > now || p.Expires == null); + + await penaltiesByLink.Union(penaltiesByIp).Distinct().ForEachAsync(p => + { + p.Active = false; + p.Expires = now; + }); + await context.SaveChangesAsync(); } }