1
0
mirror of https://github.com/RaidMax/IW4M-Admin.git synced 2025-06-10 15:20:48 -05:00

the meats

This commit is contained in:
RaidMax
2018-03-06 01:22:19 -06:00
parent 2eabfbdf37
commit 4d66d0fff9
56 changed files with 1107 additions and 719 deletions

View File

@ -1,191 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using Kayak.Http;
using Kayak;
namespace IW4MAdmin
{
class Scheduler : ISchedulerDelegate
{
public void OnException(IScheduler scheduler, Exception e)
{
// it looks like there's a library error in
// Kayak.Http.HttpServerTransactionDelegate.OnError
if ((uint)e.HResult == 0x80004003 || (uint)e.InnerException?.HResult == 0x80004003)
return;
ApplicationManager.GetInstance().Logger.WriteWarning("Web service has encountered an error - " + e.Message);
ApplicationManager.GetInstance().Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
if (e.InnerException != null)
{
ApplicationManager.GetInstance().Logger.WriteDebug($"Inner Exception: {e.InnerException.Message}");
ApplicationManager.GetInstance().Logger.WriteDebug($"Inner Stack Trace: {e.InnerException.StackTrace}");
}
}
public void OnStop(IScheduler scheduler)
{
ApplicationManager.GetInstance().Logger.WriteInfo("Web service has been stopped...");
}
}
class Request : IHttpRequestDelegate
{
public void OnRequest(HttpRequestHead request, IDataProducer requestBody, IHttpResponseDelegate response)
{
#if DEBUG
var logger = ApplicationManager.GetInstance().GetLogger();
logger.WriteDebug($"HTTP request {request.Path}");
logger.WriteDebug($"QueryString: {request.QueryString}");
logger.WriteDebug($"IP: {request.IPAddress}");
#endif
NameValueCollection querySet = new NameValueCollection();
if (request.QueryString != null)
querySet = System.Web.HttpUtility.ParseQueryString(request.QueryString);
querySet.Set("IP", request.IPAddress);
try
{
request.Path = String.IsNullOrEmpty(request.Path) ? "/" : request.Path;
SharedLibrary.HttpResponse requestedPage = WebService.GetPage(request.Path, querySet, request.Headers);
bool binaryContent = requestedPage.BinaryContent != null;
if (requestedPage.content != null && requestedPage.content.GetType() != typeof(string))
#if !DEBUG
requestedPage.content = Newtonsoft.Json.JsonConvert.SerializeObject(requestedPage.content);
#else
requestedPage.content = Newtonsoft.Json.JsonConvert.SerializeObject(requestedPage.content, Newtonsoft.Json.Formatting.Indented);
#endif
string maxAge = requestedPage.contentType == "application/json" ? "0" : "21600";
var headers = new HttpResponseHead()
{
Status = "200 OK",
Headers = new Dictionary<string, string>()
{
{ "Content-Type", requestedPage.contentType },
{ "Content-Length", binaryContent ? requestedPage.BinaryContent.Length.ToString() : requestedPage.content.ToString().Length.ToString() },
{ "Access-Control-Allow-Origin", "*" },
{ "Cache-Control", $"public,max-age={maxAge}"}
}
};
foreach (var key in requestedPage.additionalHeaders.Keys)
headers.Headers.Add(key, requestedPage.additionalHeaders[key]);
if (!binaryContent)
response.OnResponse(headers, new BufferedProducer((string)requestedPage.content));
else
response.OnResponse(headers, new BufferedProducer(requestedPage.BinaryContent));
}
catch (Exception e)
{
if (e.GetType() == typeof(FormatException))
{
ApplicationManager.GetInstance().Logger.WriteWarning("Request parameter data format was incorrect");
ApplicationManager.GetInstance().Logger.WriteDebug($"Request Path {request.Path}");
ApplicationManager.GetInstance().Logger.WriteDebug($"Request Query String {request.QueryString}");
response.OnResponse(new HttpResponseHead()
{
Status = "400 Bad Request",
Headers = new Dictionary<string, string>()
{
{ "Content-Type", "text/html" },
{ "Content-Length", "0"},
}
}, new BufferedProducer(""));
}
else
{
ApplicationManager.GetInstance().Logger.WriteError($"Webfront error during request");
ApplicationManager.GetInstance().Logger.WriteDebug($"Message: {e.Message}");
ApplicationManager.GetInstance().Logger.WriteDebug($"Stack Trace: {e.StackTrace}");
response.OnResponse(new HttpResponseHead()
{
Status = "500 Internal Server Error",
Headers = new Dictionary<string, string>()
{
{ "Content-Type", "text/html" },
{ "Content-Length", "0"},
}
}, new BufferedProducer(""));
}
}
}
}
class BufferedProducer : IDataProducer
{
ArraySegment<byte> data;
public BufferedProducer(string data) : this(data, Encoding.ASCII) { }
public BufferedProducer(string data, Encoding encoding) : this(encoding.GetBytes(data)) { }
public BufferedProducer(byte[] data) : this(new ArraySegment<byte>(data)) { }
public BufferedProducer(ArraySegment<byte> data)
{
this.data = data;
}
public IDisposable Connect(IDataConsumer channel)
{
try
{
channel?.OnData(data, null);
channel?.OnEnd();
}
catch (Exception)
{
}
return null;
}
}
class BufferedConsumer : IDataConsumer
{
List<ArraySegment<byte>> buffer = new List<ArraySegment<byte>>();
Action<string> resultCallback;
Action<Exception> errorCallback;
public BufferedConsumer(Action<string> resultCallback, Action<Exception> errorCallback)
{
this.resultCallback = resultCallback;
this.errorCallback = errorCallback;
}
public bool OnData(ArraySegment<byte> data, Action continuation)
{
// this should hopefully clean the non ascii characters out.
buffer?.Add(new ArraySegment<byte>(Encoding.ASCII.GetBytes(Encoding.ASCII.GetString(data.ToArray()))));
return false;
}
public void OnError(Exception error)
{
// errorCallback?.Invoke(error);
}
public void OnEnd()
{
var str = buffer
.Select(b => Encoding.ASCII.GetString(b.Array, b.Offset, b.Count))
.Aggregate((result, next) => result + next);
resultCallback(str);
}
}
}

View File

@ -6,11 +6,7 @@ using System.Threading.Tasks;
using System.IO;
using SharedLibrary.Objects;
using System.Reflection;
#if DEBUG
using SharedLibrary.Database;
#endif
using System.Linq;
namespace IW4MAdmin
{
@ -20,7 +16,7 @@ namespace IW4MAdmin
public static extern bool AllocConsole();
static public double Version { get; private set; }
static public ApplicationManager ServerManager = ApplicationManager.GetInstance();
public static string OperatingDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar;
public static string OperatingDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar;
public static void Start()
{
@ -29,7 +25,6 @@ namespace IW4MAdmin
Version = 1.6;
//double.TryParse(CheckUpdate(), out double latestVersion);
Console.WriteLine("=====================================================");
Console.WriteLine(" IW4M ADMIN");
Console.WriteLine(" by RaidMax ");
@ -40,13 +35,16 @@ namespace IW4MAdmin
{
CheckDirectories();
ServerManager = ApplicationManager.GetInstance();
ServerManager.Init();
Task.Run(async () =>
{
ServerManager = ApplicationManager.GetInstance();
SharedLibrary.Database.Repair.Run(ServerManager.Logger);
await ServerManager.Init();
ServerManager.Start();
});
Task.Run(() =>
{
ServerManager.Start();
String userInput;
Player Origin = ServerManager.GetClientService().Get(1).Result.AsPlayer();
@ -66,6 +64,8 @@ namespace IW4MAdmin
Console.Write('>');
} while (ServerManager.Running);
Console.WriteLine("Shutdown complete");
});
}

View File

@ -11,8 +11,6 @@ using SharedLibrary.Commands;
using SharedLibrary.Helpers;
using SharedLibrary.Exceptions;
using SharedLibrary.Objects;
using SharedLibrary.Database;
using SharedLibrary.Database.Models;
using SharedLibrary.Services;
namespace IW4MAdmin
@ -21,6 +19,7 @@ namespace IW4MAdmin
{
private List<Server> _servers;
public List<Server> Servers => _servers.OrderByDescending(s => s.ClientNum).ToList();
public List<int> AdministratorIPs { get; set; }
public ILogger Logger { get; private set; }
public bool Running { get; private set; }
@ -34,7 +33,7 @@ namespace IW4MAdmin
#if FTP_LOG
const int UPDATE_FREQUENCY = 700;
#else
const int UPDATE_FREQUENCY = 300;
const int UPDATE_FREQUENCY = 750;
#endif
private ApplicationManager()
@ -47,6 +46,7 @@ namespace IW4MAdmin
ClientSvc = new ClientService();
AliasSvc = new AliasService();
PenaltySvc = new PenaltyService();
AdministratorIPs = new List<int>();
}
public IList<Server> GetServers()
@ -64,12 +64,12 @@ namespace IW4MAdmin
return Instance ?? (Instance = new ApplicationManager());
}
public void Init()
public async Task Init()
{
#region WEBSERVICE
// SharedLibrary.WebService.Init();
//WebSvc = new WebService();
//WebSvc.StartScheduler();
#region DATABASE
AdministratorIPs = (await ClientSvc.Find(c => c.Level > Player.Permission.Trusted))
.Select(c => c.IPAddress)
.ToList();
#endregion
#region PLUGINS
@ -79,7 +79,7 @@ namespace IW4MAdmin
{
try
{
Plugin.OnLoadAsync(this);
await Plugin.OnLoadAsync(this);
}
catch (Exception e)
@ -174,6 +174,7 @@ namespace IW4MAdmin
Commands.Add(new CIP());
Commands.Add(new CMask());
Commands.Add(new CPruneAdmins());
Commands.Add(new CRestartServer());
foreach (Command C in SharedLibrary.Plugins.PluginImporter.ActiveCommands)
Commands.Add(C);

View File

@ -10,6 +10,8 @@ using SharedLibrary.Network;
using SharedLibrary.Interfaces;
using SharedLibrary.Objects;
using System.Text.RegularExpressions;
using SharedLibrary.Services;
using SharedLibrary.Database.Models;
namespace IW4MAdmin
{
@ -99,7 +101,7 @@ namespace IW4MAdmin
await Manager.GetClientService().Update(client);
}
else if (existingAlias.Name == polledPlayer.Name)
else if (existingAlias.Name == polledPlayer.Name)
{
client.CurrentAlias = existingAlias;
client.CurrentAliasId = existingAlias.AliasId;
@ -154,12 +156,13 @@ namespace IW4MAdmin
if (cNum >= 0 && Players[cNum] != null)
{
Player Leaving = Players[cNum];
Logger.WriteInfo($"Client {Leaving} disconnecting...");
await ExecuteEvent(new Event(Event.GType.Disconnect, "", Leaving, null, this));
Leaving.TotalConnectionTime += (int)(DateTime.UtcNow - Leaving.ConnectionTime).TotalSeconds;
Leaving.LastConnection = DateTime.UtcNow;
await Manager.GetClientService().Update(Leaving);
Logger.WriteInfo($"Client {Leaving} disconnecting...");
await ExecuteEvent(new Event(Event.GType.Disconnect, "", Leaving, null, this));
Players[cNum] = null;
}
}
@ -357,7 +360,11 @@ namespace IW4MAdmin
async Task<int> PollPlayersAsync()
{
var now = DateTime.Now;
var CurrentPlayers = await this.GetStatusAsync();
#if DEBUG
Logger.WriteInfo($"Polling players took {(DateTime.Now - now).TotalMilliseconds}ms");
#endif
for (int i = 0; i < Players.Count; i++)
{
@ -385,9 +392,9 @@ namespace IW4MAdmin
override public async Task<bool> ProcessUpdatesAsync(CancellationToken cts)
{
this.cts = cts;
#if DEBUG == false
//#if DEBUG == false
try
#endif
//#endif
{
// first start
if (firstRun)
@ -504,7 +511,7 @@ namespace IW4MAdmin
}
return true;
}
#if DEBUG == false
//#if !DEBUG
catch (SharedLibrary.Exceptions.NetworkException)
{
Logger.WriteError($"Could not communicate with {IP}:{Port}");
@ -518,7 +525,7 @@ namespace IW4MAdmin
Logger.WriteDebug("Error Trace: " + E.StackTrace);
return false;
}
#endif
//#endif
}
public async Task Initialize()
@ -537,6 +544,7 @@ namespace IW4MAdmin
await this.GetDvarAsync<int>("sv_maxclients");
var gametype = await this.GetDvarAsync<string>("g_gametype");
var basepath = await this.GetDvarAsync<string>("fs_basepath");
WorkingDirectory = basepath.Value;
var game = await this.GetDvarAsync<string>("fs_game");
var logfile = await this.GetDvarAsync<string>("g_log");
var logsync = await this.GetDvarAsync<int>("g_logsync");
@ -705,6 +713,11 @@ namespace IW4MAdmin
string mapname = this.GetDvarAsync<string>("mapname").Result.Value;
CurrentMap = Maps.Find(m => m.Name == mapname) ?? new Map(mapname, mapname);
// todo: make this more efficient
((ApplicationManager)(Manager)).AdministratorIPs = (await new GenericRepository<EFClient>().FindAsync(c => c.Level > Player.Permission.Trusted))
.Select(c => c.IPAddress)
.ToList();
}
if (E.Type == Event.GType.MapEnd)

View File

@ -0,0 +1,25 @@
using IW4MAdmin;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using SharedLibrary;
using SharedLibrary.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebfrontCore.Controllers
{
public class BaseController : Controller
{
protected ApplicationManager Manager;
protected bool Authorized { get; private set; }
public override void OnActionExecuting(ActionExecutingContext context)
{
Manager = IW4MAdmin.Program.ServerManager;
Authorized = Manager.AdministratorIPs.Contains(context.HttpContext.Connection.RemoteIpAddress.ToString().ConvertToIP());
base.OnActionExecuting(context);
}
}
}

View File

@ -9,11 +9,11 @@ using System.Threading.Tasks;
namespace WebfrontCore.Controllers
{
public class ClientController : Controller
public class ClientController : BaseController
{
public async Task<IActionResult> ProfileAsync(int id)
{
var client = await IW4MAdmin.ApplicationManager.GetInstance().GetClientService().Get(id);
var client = await Manager.GetClientService().Get(id);
var clientDto = new PlayerInfo()
{
Name = client.Name,
@ -38,11 +38,15 @@ namespace WebfrontCore.Controllers
.OrderBy(i => i)
.ToList(),
};
clientDto.Meta.AddRange(await MetaService.GetMeta(client.ClientId));
clientDto.Meta.AddRange(await IW4MAdmin.ApplicationManager.GetInstance().GetPenaltyService().ReadGetClientPenaltiesAsync(client.ClientId));
clientDto.Meta.AddRange(await IW4MAdmin.ApplicationManager.GetInstance().GetPenaltyService().ReadGetClientPenaltiesAsync(client.ClientId, false));
clientDto.Meta = clientDto.Meta.OrderByDescending(m => m.When).ToList();
var meta = await MetaService.GetMeta(client.ClientId);
clientDto.Meta.AddRange(Authorized ? meta : meta.Where(m => !m.Sensitive));
clientDto.Meta.AddRange(await Manager.GetPenaltyService()
.ReadGetClientPenaltiesAsync(client.ClientId));
clientDto.Meta.AddRange(await Manager.GetPenaltyService()
.ReadGetClientPenaltiesAsync(client.ClientId, false));
clientDto.Meta = clientDto.Meta
.OrderByDescending(m => m.When)
.ToList();
ViewBag.Title = clientDto.Name;
@ -51,7 +55,7 @@ namespace WebfrontCore.Controllers
public async Task<IActionResult> PrivilegedAsync()
{
var admins = (await IW4MAdmin.ApplicationManager.GetInstance().GetClientService().GetPrivilegedClients())
var admins = (await Manager.GetClientService().GetPrivilegedClients())
.Where(a => a.Active)
.OrderByDescending(a => a.Level);
var adminsDict = new Dictionary<SharedLibrary.Objects.Player.Permission, IList<ClientInfo>>();
@ -74,7 +78,7 @@ namespace WebfrontCore.Controllers
public async Task<IActionResult> FindAsync(string clientName)
{
var clients = (await IW4MAdmin.ApplicationManager.GetInstance().GetClientService().GetClientByName(clientName))
var clients = (await Manager.GetClientService().GetClientByName(clientName))
.OrderByDescending(c => c.LastConnection);
var clientsDto = clients.Select(c => new PlayerInfo()
{

View File

@ -9,11 +9,11 @@ using System.Threading.Tasks;
namespace WebfrontCore.Controllers
{
public class ConsoleController : Controller
public class ConsoleController : BaseController
{
public IActionResult Index()
{
var activeServers = IW4MAdmin.ApplicationManager.GetInstance().Servers.Select(s => new ServerInfo()
var activeServers = Manager.Servers.Select(s => new ServerInfo()
{
Name = s.Hostname,
ID = s.GetHashCode(),
@ -38,10 +38,10 @@ namespace WebfrontCore.Controllers
IPAddress = intIP
};
#else
var origin = (await IW4MAdmin.ApplicationManager.GetInstance().GetClientService().GetUnique(0)).AsPlayer();
var origin = (await Manager.GetClientService().GetUnique(0)).AsPlayer();
#endif
var server = IW4MAdmin.ApplicationManager.GetInstance().Servers.First(s => s.GetHashCode() == serverId);
var server = Manager.Servers.First(s => s.GetHashCode() == serverId);
origin.CurrentServer = server;
var remoteEvent = new Event(Event.GType.Say, command, origin, null, server);

View File

@ -8,7 +8,7 @@ using SharedLibrary.Dtos;
namespace WebfrontCore.Controllers
{
public class HomeController : Controller
public class HomeController : BaseController
{
public IActionResult Index()
{

View File

@ -9,9 +9,9 @@ using WebfrontCore.ViewComponents;
namespace WebfrontCore.Controllers
{
public class PenaltyController : Controller
public class PenaltyController : BaseController
{
public IActionResult List()
public IActionResult List()
{
ViewBag.Title = "Penalty List";
return View();

View File

@ -7,15 +7,14 @@ using System.Threading.Tasks;
namespace WebfrontCore.Controllers
{
public class ServerController : Controller
public class ServerController : BaseController
{
[HttpGet]
[ResponseCache(NoStore = true, Duration = 0)]
public IActionResult ClientActivity(int id)
{
var s = IW4MAdmin.Program.ServerManager.GetServers().FirstOrDefault(s2 => s2.GetHashCode() == id);
var s = Manager.GetServers().FirstOrDefault(s2 => s2.GetHashCode() == id);
if (s == null)
return View("Error", "Invalid server!");

View File

@ -12,6 +12,12 @@ namespace WebfrontCore.ViewComponents
{
public async Task<IViewComponentResult> InvokeAsync(int offset)
{
int ip = HttpContext.Connection.RemoteIpAddress
.ToString().ConvertToIP();
bool authed = IW4MAdmin.ApplicationManager.GetInstance()
.AdministratorIPs.Contains(ip);
var penalties = await IW4MAdmin.ApplicationManager.GetInstance().GetPenaltyService().GetRecentPenalties(15, offset);
var penaltiesDto = penalties.Select(p => new PenaltyInfo()
{
@ -23,8 +29,11 @@ namespace WebfrontCore.ViewComponents
Offense = p.Offense,
Type = p.Type.ToString(),
TimePunished = Utilities.GetTimePassed(p.When, false),
TimeRemaining = DateTime.UtcNow > p.Expires ? "" : Utilities.TimeSpanText(p.Expires - DateTime.UtcNow)
}).ToList();
TimeRemaining = DateTime.UtcNow > p.Expires ? "" : Utilities.TimeSpanText(p.Expires - DateTime.UtcNow),
Sensitive = p.Type == SharedLibrary.Objects.Penalty.PenaltyType.Flag
});
penaltiesDto = authed ? penaltiesDto.ToList() : penaltiesDto.Where(p => !p.Sensitive).ToList();
return View("_List", penaltiesDto);
}

View File

@ -8,7 +8,10 @@
</div>
<div id="profile_info" class="text-center text-sm-left pr-3 pl-3">
<div id="profile_name">
<h1><span class="client-name mr-4">@Model.Name<span id="profile_aliases_btn" class="oi oi-caret-bottom pl-2"></span></span></h1>
@{
string displayAliasButton = Model.Aliases.Count > 0 ? "" : "display: none;";
}
<h1><span class="client-name mr-4">@Model.Name<span id="profile_aliases_btn" class="oi oi-caret-bottom pl-2 @displayAliasButton"></span></span></h1>
<div id="profile_aliases" class="pr-0 pr-sm-4 pb-2 mb-2 text-muted">
@{
foreach (string alias in Model.Aliases)

View File

@ -8,19 +8,22 @@
<PackageId>WebfrontCore</PackageId>
<Platforms>AnyCPU;x86</Platforms>
<ApplicationIcon>wwwroot\favicon.ico</ApplicationIcon>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<OutputPath>bin\x86\Debug\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Application\Kayak.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="Application\Kayak.cs" />
<None Update="wwwroot\**\*">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</None>
@ -60,12 +63,6 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Content Update="app.config">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="xcopy /Y &quot;$(SolutionDir)BUILD\Plugins&quot; &quot;$(TargetDir)Plugins\&quot;&#xD;&#xA;xcopy /Y /I /E &quot;$(SolutionDir)BUILD\Lib&quot; &quot;$(TargetDir)&quot; &#xD;&#xA;&#xD;&#xA;xcopy /Y /I /E &quot;$(ProjectDir)Application\Config&quot; &quot;$(TargetDir)Config&quot;" />
</Target>

View File

@ -31,6 +31,6 @@
<connectionStrings>
<add name="DefaultConnection"
providerName="System.Data.SqlServerCe.4.0"
connectionString="Data Source=|DataDirectory|\Database\Database.sdf"/>
connectionString="Data Source=|DataDirectory|\Database.sdf"/>
</connectionStrings>
</configuration>

View File

@ -2,9 +2,9 @@
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Debug",
"Default": "Trace",
"System": "Information",
"Microsoft": "Information"
"Microsoft": "None"
}
}
}