1
0
mirror of https://github.com/RaidMax/IW4M-Admin.git synced 2025-06-11 15:52:25 -05:00

hide chat for password protected servers for issue #162

This commit is contained in:
RaidMax
2020-08-20 10:38:11 -05:00
parent 774d4a5d30
commit 2e0b1b3569
39 changed files with 1171 additions and 188 deletions

View File

@ -10,7 +10,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.SyndicationFeed.ReaderWriter" Version="1.0.2" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.7" PrivateAssets="All" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.9" PrivateAssets="All" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -10,7 +10,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.7" PrivateAssets="All" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.9" PrivateAssets="All" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -16,7 +16,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.7" PrivateAssets="All" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.9" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>

View File

@ -23,7 +23,7 @@
</Target>
<ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.7" PrivateAssets="All" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.9" PrivateAssets="All" />
</ItemGroup>
</Project>

View File

@ -16,7 +16,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.7" PrivateAssets="All" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.9" PrivateAssets="All" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -1,8 +1,7 @@
using SharedLibraryCore.Dtos;
using SharedLibraryCore.QueryHelper;
using SharedLibraryCore.QueryHelper;
using System;
namespace StatsWeb.Dtos
namespace Stats.Dtos
{
public class ChatSearchQuery : ClientPaginationRequest
{
@ -30,5 +29,10 @@ namespace StatsWeb.Dtos
/// only look for messages sent before this date0
/// </summary>
public DateTime SentBefore { get; set; } = DateTime.UtcNow;
/// <summary>
/// indicates if the chat is on the meta page
/// </summary>
public bool IsProfileMeta { get; set; }
}
}

View File

@ -248,6 +248,10 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
ctx.Entry(server).Property(_prop => _prop.HostName).IsModified = true;
ctx.SaveChanges();
}
ctx.Entry(server).Property(_prop => _prop.IsPasswordProtected).IsModified = true;
server.IsPasswordProtected = !string.IsNullOrEmpty(sv.GamePassword);
ctx.SaveChanges();
}
// check to see if the stats have ever been initialized

View File

@ -16,5 +16,6 @@ namespace IW4MAdmin.Plugins.Stats.Models
public string EndPoint { get; set; }
public Game? GameName { get; set; }
public string HostName { get; set; }
public bool IsPasswordProtected { get; set; }
}
}

View File

@ -5,12 +5,11 @@ using Microsoft.EntityFrameworkCore;
using SharedLibraryCore;
using SharedLibraryCore.Database;
using SharedLibraryCore.Database.Models;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Dtos.Meta.Responses;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using SharedLibraryCore.QueryHelper;
using SharedLibraryCore.Services;
using Stats.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
@ -36,14 +35,16 @@ namespace IW4MAdmin.Plugins.Stats
private readonly IDatabaseContextFactory _databaseContextFactory;
private readonly ITranslationLookup _translationLookup;
private readonly IMetaService _metaService;
private readonly IResourceQueryHelper<ChatSearchQuery, MessageResponse> _chatQueryHelper;
public Plugin(IConfigurationHandlerFactory configurationHandlerFactory, IDatabaseContextFactory databaseContextFactory,
ITranslationLookup translationLookup, IMetaService metaService)
ITranslationLookup translationLookup, IMetaService metaService, IResourceQueryHelper<ChatSearchQuery, MessageResponse> chatQueryHelper)
{
Config = configurationHandlerFactory.GetConfigurationHandler<StatsConfiguration>("StatsPluginSettings");
_databaseContextFactory = databaseContextFactory;
_translationLookup = translationLookup;
_metaService = metaService;
_chatQueryHelper = chatQueryHelper;
}
public async Task OnEventAsync(GameEvent E, Server S)
@ -199,7 +200,7 @@ namespace IW4MAdmin.Plugins.Stats
using (var ctx = _databaseContextFactory.CreateContext(enableTracking: false))
{
clientStats = await ctx.Set<EFClientStatistics>().Where(c => c.ClientId == request.ClientId).ToListAsync();
messageCount = await ctx.Set<EFClientMessage>().CountAsync(_message => _message.ClientId == request.ClientId);
messageCount = await ctx.Set<EFClientMessage>().CountAsync(_message => _message.ClientId == request.ClientId);
}
int kills = clientStats.Sum(c => c.Kills);
@ -392,45 +393,16 @@ namespace IW4MAdmin.Plugins.Stats
async Task<IEnumerable<MessageResponse>> getMessages(ClientPaginationRequest request)
{
List<MessageResponse> messageMeta;
using (var ctx = _databaseContextFactory.CreateContext(enableTracking: false))
var query = new ChatSearchQuery()
{
var messages = ctx.Set<EFClientMessage>()
.Where(m => m.ClientId == request.ClientId)
.Where(_message => _message.TimeSent < request.Before)
.OrderByDescending(_message => _message.TimeSent)
.Take(request.Count);
ClientId = request.ClientId,
Before = request.Before,
SentBefore = request.Before ?? DateTime.UtcNow,
Count = request.Count,
IsProfileMeta = true
};
messageMeta = await messages.Select(m => new MessageResponse()
{
// todo: game name
Message = m.Message,
When = m.TimeSent,
ServerId = m.ServerId,
Type = MetaType.ChatMessage
}).ToListAsync();
foreach (var meta in messageMeta)
{
if ((meta.Message).IsQuickMessage())
{
try
{
var quickMessages = ServerManager.GetApplicationSettings().Configuration()
.QuickMessages
.First(/*_qm => _qm.Game == meta.GameName*/);
meta.Message = quickMessages.Messages[(meta.Message as string).Substring(1)];
meta.Type = MetaType.QuickMessage;
}
catch
{
}
}
}
}
return messageMeta;
return (await _chatQueryHelper.QueryResource(query)).Results;
}
if (Config.Configuration().EnableAntiCheat)

View File

@ -16,7 +16,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.7" PrivateAssets="All" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.9" PrivateAssets="All" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -1,9 +1,13 @@
using IW4MAdmin.Plugins.Stats.Models;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Dtos.Meta.Responses;
using SharedLibraryCore.Helpers;
using SharedLibraryCore.Interfaces;
using StatsWeb.Dtos;
using Stats.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@ -12,31 +16,44 @@ namespace StatsWeb
/// <summary>
/// implementation of IResourceQueryHelper
/// </summary>
public class ChatResourceQueryHelper : IResourceQueryHelper<ChatSearchQuery, ChatSearchResult>
public class ChatResourceQueryHelper : IResourceQueryHelper<ChatSearchQuery, MessageResponse>
{
private readonly IDatabaseContextFactory _contextFactory;
private readonly ILogger _logger;
private readonly ApplicationConfiguration _appConfig;
private List<EFServer> serverCache;
public ChatResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory)
public ChatResourceQueryHelper(ILogger logger, IDatabaseContextFactory contextFactory, ApplicationConfiguration appConfig)
{
_contextFactory = contextFactory;
_logger = logger;
_appConfig = appConfig;
}
/// <inheritdoc/>
public async Task<ResourceQueryHelperResult<ChatSearchResult>> QueryResource(ChatSearchQuery query)
public async Task<ResourceQueryHelperResult<MessageResponse>> QueryResource(ChatSearchQuery query)
{
if (query == null)
{
throw new ArgumentException("Query must be specified");
}
var result = new ResourceQueryHelperResult<ChatSearchResult>();
var result = new ResourceQueryHelperResult<MessageResponse>();
using var context = _contextFactory.CreateContext(enableTracking: false);
if (serverCache == null)
{
serverCache = await context.Set<EFServer>().ToListAsync();
}
if (int.TryParse(query.ServerId, out int serverId))
{
query.ServerId = serverCache.FirstOrDefault(_server => _server.ServerId == serverId)?.EndPoint ?? query.ServerId;
}
var iqMessages = context.Set<EFClientMessage>()
.Where(_message => _message.TimeSent >= query.SentAfter)
.Where(_message => _message.TimeSent <= query.SentBefore);
.Where(_message => _message.TimeSent < query.SentBefore);
if (query.ClientId != null)
{
@ -50,27 +67,29 @@ namespace StatsWeb
if (!string.IsNullOrEmpty(query.MessageContains))
{
iqMessages = iqMessages.Where(_message => EF.Functions.Like(_message.Message, $"%{query.MessageContains}%"));
iqMessages = iqMessages.Where(_message => EF.Functions.Like(_message.Message.ToLower(), $"%{query.MessageContains.ToLower()}%"));
}
var iqResponse = iqMessages
.Select(_message => new ChatSearchResult
.Select(_message => new MessageResponse
{
ClientId = _message.ClientId,
ClientName = _message.Client.CurrentAlias.Name,
Date = _message.TimeSent,
ClientName = query.IsProfileMeta ? "" : _message.Client.CurrentAlias.Name,
ServerId = _message.ServerId,
When = _message.TimeSent,
Message = _message.Message,
ServerName = _message.Server.HostName
ServerName = query.IsProfileMeta ? "" : _message.Server.HostName,
GameName = _message.Server.GameName == null ? Server.Game.IW4 : _message.Server.GameName.Value
});
if (query.Direction == SharedLibraryCore.Dtos.SortDirection.Descending)
{
iqResponse = iqResponse.OrderByDescending(_message => _message.Date);
iqResponse = iqResponse.OrderByDescending(_message => _message.When);
}
else
{
iqResponse = iqResponse.OrderBy(_message => _message.Date);
iqResponse = iqResponse.OrderBy(_message => _message.When);
}
var resultList = await iqResponse
@ -78,6 +97,27 @@ namespace StatsWeb
.Take(query.Count)
.ToListAsync();
foreach (var message in resultList)
{
message.IsHidden = serverCache.Any(server => server.ServerId == message.ServerId && server.IsPasswordProtected);
if (message.Message.IsQuickMessage())
{
try
{
var quickMessages = _appConfig
.QuickMessages
.First(_qm => _qm.Game == message.GameName);
message.Message = quickMessages.Messages[message.Message.Substring(1)];
message.IsQuickMessage = true;
}
catch
{
message.Message = message.Message.Substring(1);
}
}
}
result.TotalResultCount = await iqResponse.CountAsync();
result.Results = resultList;
result.RetrievedResultCount = resultList.Count;

View File

@ -5,8 +5,9 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using SharedLibraryCore;
using SharedLibraryCore.Dtos;
using SharedLibraryCore.Dtos.Meta.Responses;
using SharedLibraryCore.Interfaces;
using StatsWeb.Dtos;
using Stats.Dtos;
using StatsWeb.Extensions;
using System;
using System.Linq;
@ -18,10 +19,10 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers
{
private readonly ILogger _logger;
private readonly IManager _manager;
private readonly IResourceQueryHelper<ChatSearchQuery, ChatSearchResult> _chatResourceQueryHelper;
private readonly IResourceQueryHelper<ChatSearchQuery, MessageResponse> _chatResourceQueryHelper;
private readonly ITranslationLookup _translationLookup;
public StatsController(ILogger logger, IManager manager, IResourceQueryHelper<ChatSearchQuery, ChatSearchResult> resourceQueryHelper,
public StatsController(ILogger logger, IManager manager, IResourceQueryHelper<ChatSearchQuery, MessageResponse> resourceQueryHelper,
ITranslationLookup translationLookup) : base(manager)
{
_logger = logger;
@ -72,51 +73,24 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers
}
[HttpGet]
public async Task<IActionResult> GetMessageAsync(int serverId, long when)
public async Task<IActionResult> GetMessageAsync(string serverId, long when)
{
var whenTime = DateTime.FromFileTimeUtc(when);
var whenUpper = whenTime.AddMinutes(5);
var whenLower = whenTime.AddMinutes(-5);
using (var ctx = new SharedLibraryCore.Database.DatabaseContext(true))
var messages = await _chatResourceQueryHelper.QueryResource(new ChatSearchQuery()
{
var iqMessages = from message in ctx.Set<Stats.Models.EFClientMessage>()
where message.ServerId == serverId
where message.TimeSent >= whenLower
where message.TimeSent <= whenUpper
select new ChatInfo()
{
ClientId = message.ClientId,
Message = message.Message,
Name = message.Client.CurrentAlias.Name,
Time = message.TimeSent,
ServerGame = message.Server.GameName ?? Server.Game.IW4
};
ServerId = serverId,
SentBefore = whenUpper,
SentAfter = whenLower
});
var messages = await iqMessages.ToListAsync();
foreach (var message in messages)
{
if (message.Message.IsQuickMessage())
{
try
{
var quickMessages = _manager.GetApplicationSettings().Configuration()
.QuickMessages
.First(_qm => _qm.Game == message.ServerGame);
message.Message = quickMessages.Messages[message.Message.Substring(1)];
message.IsQuickMessage = true;
}
catch { }
}
}
return View("_MessageContext", messages);
}
return View("_MessageContext", messages.Results);
}
[HttpGet("Message/Find")]
public async Task<IActionResult> FindMessage([FromQuery]string query)
public async Task<IActionResult> FindMessage([FromQuery] string query)
{
ViewBag.Localization = _translationLookup;
ViewBag.EnableColorCodes = _manager.GetApplicationSettings().Configuration().EnableColorCodes;
@ -151,7 +125,7 @@ namespace IW4MAdmin.Plugins.Web.StatsWeb.Controllers
}
[HttpGet("Message/FindNext")]
public async Task<IActionResult> FindNextMessages([FromQuery]string query, [FromQuery]int count, [FromQuery]int offset)
public async Task<IActionResult> FindNextMessages([FromQuery] string query, [FromQuery] int count, [FromQuery] int offset)
{
ChatSearchQuery searchRequest;

View File

@ -1,32 +0,0 @@
using System;
namespace StatsWeb.Dtos
{
public class ChatSearchResult
{
/// <summary>
/// name of the client
/// </summary>
public string ClientName { get; set; }
/// <summary>
/// client id
/// </summary>
public int ClientId { get; set; }
/// <summary>
/// hostname of the server
/// </summary>
public string ServerName { get; set; }
/// <summary>
/// chat message
/// </summary>
public string Message { get; set; }
/// <summary>
/// date the chat occured on
/// </summary>
public DateTime Date { get; set; }
}
}

View File

@ -1,5 +1,5 @@
using SharedLibraryCore.Dtos;
using StatsWeb.Dtos;
using Stats.Dtos;
using System;
using System.Linq;

View File

@ -14,7 +14,7 @@
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.7" PrivateAssets="All" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.9" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>

View File

@ -1,4 +1,5 @@
@model SharedLibraryCore.Helpers.ResourceQueryHelperResult<StatsWeb.Dtos.ChatSearchResult>
@using SharedLibraryCore.Dtos.Meta.Responses
@model SharedLibraryCore.Helpers.ResourceQueryHelperResult<MessageResponse>
@if (ViewBag.Error != null)
{

View File

@ -1,4 +1,5 @@
@model IEnumerable<StatsWeb.Dtos.ChatSearchResult>
@using SharedLibraryCore.Dtos.Meta.Responses
@model IEnumerable<MessageResponse>
@foreach (var message in Model)
{
@ -10,13 +11,20 @@
</a>
</td>
<td class="text-light w-50 text-break">
<color-code value="@message.Message" allow="@ViewBag.EnableColorCodes"></color-code>
@if (message.IsHidden && !ViewBag.Authorized)
{
<color-code value="@SharedLibraryCore.Utilities.FormatExt(ViewBag.Localization["WEBFRONT_CLIENT_META_CHAT_HIDDEN"], message.HiddenMessage)" allow="@ViewBag.EnableColorCodes"></color-code>
}
else
{
<color-code value="@message.Message" allow="@ViewBag.EnableColorCodes"></color-code>
}
</td>
<td class="text-light">
<color-code value="@(message.ServerName ?? "--")" allow="@ViewBag.EnableColorCodes"></color-code>
</td>
<td class="text-right text-light">
@message.Date
@message.When
</td>
</tr>
@ -33,7 +41,14 @@
<tr class="d-table-row d-lg-none bg-dark">
<th scope="row" class="bg-primary">@ViewBag.Localization["WEBFRONT_ACTION_LABEL_MESSAGE"]</th>
<td class="text-light">
<color-code value="@message.Message" allow="@ViewBag.EnableColorCodes"></color-code>
@if (message.IsHidden && !ViewBag.Authorized)
{
<color-code value="@SharedLibraryCore.Utilities.FormatExt(ViewBag.Localization["WEBFRONT_CLIENT_META_CHAT_HIDDEN"], message.HiddenMessage)" allow="@ViewBag.EnableColorCodes"></color-code>
}
else
{
<color-code value="@message.Message" allow="@ViewBag.EnableColorCodes"></color-code>
}
</td>
</tr>
@ -47,7 +62,7 @@
<tr class="d-table-row d-lg-none bg-dark">
<th scope="row" class="bg-primary" style="border-bottom: 1px solid #222">@ViewBag.Localization["WEBFRONT_ADMIN_AUDIT_LOG_TIME"]</th>
<td class="text-light mb-2 border-bottom">
@message.Date
@message.When
</td>
</tr>
}

View File

@ -1,20 +1,21 @@
@model IEnumerable<SharedLibraryCore.Dtos.ChatInfo>
@using SharedLibraryCore.Dtos.Meta.Responses
@model IEnumerable<MessageResponse>
@{
Layout = null;
}
<div class="client-message-context">
<h5 class="bg-primary pt-2 pb-2 pl-3 mb-0 mt-2 text-white">@Model.First().Time.ToString()</h5>
<h5 class="bg-primary pt-2 pb-2 pl-3 mb-0 mt-2 text-white">@Model.First().When.ToString()</h5>
<div class="bg-dark p-3 mb-2 border-bottom">
@foreach (var message in Model)
{
<span class="text-white">
<color-code value="@message.Name" allow="ViewBag.EnableColorCodes"></color-code>
<color-code value="@message.ClientName" allow="ViewBag.EnableColorCodes"></color-code>
</span>
<span>
&mdash;
<span class="@(message.IsQuickMessage ? "font-italic" : "")">
<color-code value="@message.Message" allow="ViewBag.EnableColorCodes"></color-code>
<color-code value="@(message.IsHidden ? message.HiddenMessage : message.Message)" allow="ViewBag.EnableColorCodes"></color-code>
</span>
</span>
<br />

View File

@ -16,7 +16,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.7" PrivateAssets="All" />
<PackageReference Include="RaidMax.IW4MAdmin.SharedLibraryCore" Version="2.4.9" PrivateAssets="All" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">