fixes for new polling setup
update database model for alias (nullable ip) heartbeats now send ip to master server
This commit is contained in:
parent
9bdd7d1b8a
commit
5ac8a55c72
@ -9,6 +9,8 @@ namespace IW4MAdmin.Application.API.Master
|
|||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
[JsonProperty("ip")]
|
||||||
|
public string IPAddress { get; set; }
|
||||||
[JsonProperty("port")]
|
[JsonProperty("port")]
|
||||||
public short Port { get; set; }
|
public short Port { get; set; }
|
||||||
[JsonProperty("gametype")]
|
[JsonProperty("gametype")]
|
||||||
|
@ -44,7 +44,8 @@ namespace IW4MAdmin.Application.API.Master
|
|||||||
Map = s.CurrentMap.Name,
|
Map = s.CurrentMap.Name,
|
||||||
MaxClientNum = s.MaxClients,
|
MaxClientNum = s.MaxClients,
|
||||||
Id = s.GetHashCode(),
|
Id = s.GetHashCode(),
|
||||||
Port = (short)s.GetPort()
|
Port = (short)s.GetPort(),
|
||||||
|
IPAddress = s.IP
|
||||||
}).ToList()
|
}).ToList()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
using System;
|
using SharedLibraryCore;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using SharedLibraryCore;
|
|
||||||
using SharedLibraryCore.Database.Models;
|
using SharedLibraryCore.Database.Models;
|
||||||
using SharedLibraryCore.Interfaces;
|
using SharedLibraryCore.Interfaces;
|
||||||
using SharedLibraryCore.Objects;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace IW4MAdmin.Application.EventParsers
|
namespace IW4MAdmin.Application.EventParsers
|
||||||
{
|
{
|
||||||
@ -149,7 +147,11 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Owner = server,
|
Owner = server,
|
||||||
Origin = new EFClient()
|
Origin = new EFClient()
|
||||||
{
|
{
|
||||||
|
CurrentAlias = new EFAlias()
|
||||||
|
{
|
||||||
|
Active = false,
|
||||||
Name = regexMatch.Groups[4].ToString().StripColors(),
|
Name = regexMatch.Groups[4].ToString().StripColors(),
|
||||||
|
},
|
||||||
NetworkId = regexMatch.Groups[2].ToString().ConvertLong(),
|
NetworkId = regexMatch.Groups[2].ToString().ConvertLong(),
|
||||||
ClientNumber = Convert.ToInt32(regexMatch.Groups[3].ToString()),
|
ClientNumber = Convert.ToInt32(regexMatch.Groups[3].ToString()),
|
||||||
State = EFClient.ClientState.Connecting,
|
State = EFClient.ClientState.Connecting,
|
||||||
@ -171,7 +173,11 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
Owner = server,
|
Owner = server,
|
||||||
Origin = new EFClient()
|
Origin = new EFClient()
|
||||||
{
|
{
|
||||||
Name = regexMatch.Groups[4].ToString().StripColors(),
|
CurrentAlias = new EFAlias()
|
||||||
|
{
|
||||||
|
Active = false,
|
||||||
|
Name = regexMatch.Groups[4].ToString().StripColors()
|
||||||
|
},
|
||||||
NetworkId = regexMatch.Groups[2].ToString().ConvertLong(),
|
NetworkId = regexMatch.Groups[2].ToString().ConvertLong(),
|
||||||
ClientNumber = Convert.ToInt32(regexMatch.Groups[3].ToString()),
|
ClientNumber = Convert.ToInt32(regexMatch.Groups[3].ToString()),
|
||||||
State = EFClient.ClientState.Disconnecting
|
State = EFClient.ClientState.Disconnecting
|
||||||
@ -217,6 +223,9 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
}
|
}
|
||||||
|
|
||||||
// other parsers can derive from this parser so we make it virtual
|
// other parsers can derive from this parser so we make it virtual
|
||||||
public virtual string GetGameDir() => "userraw";
|
public virtual string GetGameDir()
|
||||||
|
{
|
||||||
|
return "userraw";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
using SharedLibraryCore;
|
using SharedLibraryCore;
|
||||||
using SharedLibraryCore.Database.Models;
|
using SharedLibraryCore.Database.Models;
|
||||||
using SharedLibraryCore.Interfaces;
|
|
||||||
using SharedLibraryCore.Objects;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace IW4MAdmin.Application.EventParsers
|
namespace IW4MAdmin.Application.EventParsers
|
||||||
{
|
{
|
||||||
class IW5EventParser : IW4EventParser
|
class IW5EventParser : IW4EventParser
|
||||||
{
|
{
|
||||||
public override string GetGameDir() => "logs";
|
public override string GetGameDir()
|
||||||
|
{
|
||||||
|
return "logs";
|
||||||
|
}
|
||||||
|
|
||||||
public override GameEvent GetEvent(Server server, string logLine)
|
public override GameEvent GetEvent(Server server, string logLine)
|
||||||
{
|
{
|
||||||
@ -28,7 +26,11 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
{
|
{
|
||||||
NetworkId = lineSplit[1].ConvertLong(),
|
NetworkId = lineSplit[1].ConvertLong(),
|
||||||
ClientNumber = clientNum,
|
ClientNumber = clientNum,
|
||||||
|
CurrentAlias = new EFAlias()
|
||||||
|
{
|
||||||
|
Active = false,
|
||||||
Name = lineSplit[3]
|
Name = lineSplit[3]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return new GameEvent()
|
return new GameEvent()
|
||||||
@ -48,7 +50,9 @@ namespace IW4MAdmin.Application.EventParsers
|
|||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return base.GetEvent(server, logLine);
|
return base.GetEvent(server, logLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,12 +28,12 @@ namespace IW4MAdmin.Application.IO
|
|||||||
|
|
||||||
public long Length => -1;
|
public long Length => -1;
|
||||||
|
|
||||||
public int UpdateInterval => 1000;
|
public int UpdateInterval => 350;
|
||||||
|
|
||||||
public async Task<ICollection<GameEvent>> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
public async Task<ICollection<GameEvent>> ReadEventsFromLog(Server server, long fileSizeDiff, long startPosition)
|
||||||
{
|
{
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
server.Logger.WriteDebug($"Begin reading {fileSizeDiff} from http log");
|
server.Logger.WriteDebug($"Begin reading from http log");
|
||||||
#endif
|
#endif
|
||||||
var events = new List<GameEvent>();
|
var events = new List<GameEvent>();
|
||||||
string b64Path = server.LogPath.ToBase64UrlSafeString();
|
string b64Path = server.LogPath.ToBase64UrlSafeString();
|
||||||
|
@ -75,27 +75,9 @@ namespace IW4MAdmin
|
|||||||
// client has connected in the past
|
// client has connected in the past
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var existingAlias = client.AliasLink.Children
|
// this is only a temporary version until the IPAddress is transmitted
|
||||||
.FirstOrDefault(a => a.Name == clientFromLog.Name);
|
client.CurrentAlias.Active = false;
|
||||||
|
client.CurrentAlias.Name = clientFromLog.Name;
|
||||||
if (existingAlias == null)
|
|
||||||
{
|
|
||||||
Logger.WriteDebug($"Client {clientFromLog} has connected previously under a different ip/name");
|
|
||||||
client.CurrentAlias = new EFAlias()
|
|
||||||
{
|
|
||||||
// this gets updated on client join
|
|
||||||
IPAddress = clientFromLog.IPAddress,
|
|
||||||
Name = clientFromLog.Name,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client.CurrentAlias = existingAlias;
|
|
||||||
client.CurrentAliasId = existingAlias.AliasId;
|
|
||||||
}
|
|
||||||
|
|
||||||
await Manager.GetClientService().Update(client);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.WriteInfo($"Client {client} connected...");
|
Logger.WriteInfo($"Client {client} connected...");
|
||||||
@ -108,14 +90,15 @@ namespace IW4MAdmin
|
|||||||
client.CurrentServer = this;
|
client.CurrentServer = this;
|
||||||
|
|
||||||
Clients[client.ClientNumber] = client;
|
Clients[client.ClientNumber] = client;
|
||||||
client.OnConnect();
|
|
||||||
|
|
||||||
// this only happens the preconnect event occurred from RCon polling
|
// this only happens if the preconnect event occurred from RCon polling
|
||||||
if (clientFromLog.IPAddress != 0)
|
if (clientFromLog.IPAddress.HasValue)
|
||||||
{
|
{
|
||||||
await client.OnJoin(clientFromLog.IPAddress);
|
await client.OnJoin(clientFromLog.IPAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client.OnConnect();
|
||||||
|
|
||||||
client.State = EFClient.ClientState.Connected;
|
client.State = EFClient.ClientState.Connected;
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
Logger.WriteDebug($"End PreConnect for {client}");
|
Logger.WriteDebug($"End PreConnect for {client}");
|
||||||
@ -218,11 +201,23 @@ namespace IW4MAdmin
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
override protected async Task<bool> ProcessEvent(GameEvent E)
|
override protected async Task<bool> ProcessEvent(GameEvent E)
|
||||||
{
|
{
|
||||||
if (E.Type == GameEvent.EventType.PreConnect)
|
if (E.Type == GameEvent.EventType.ChangePermission)
|
||||||
{
|
{
|
||||||
bool clientExists = GetClientsAsList().Exists(_client => _client.NetworkId.Equals(E.Origin));
|
if (!E.Target.IsPrivileged())
|
||||||
|
{
|
||||||
|
// remove banned or demoted privileged user
|
||||||
|
Manager.GetPrivilegedClients().Remove(E.Target.ClientId);
|
||||||
|
}
|
||||||
|
|
||||||
if (!clientExists)
|
else
|
||||||
|
{
|
||||||
|
Manager.GetPrivilegedClients()[E.Target.ClientId] = E.Target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (E.Type == GameEvent.EventType.PreConnect)
|
||||||
|
{
|
||||||
|
if (Clients[E.Origin.ClientNumber] == null)
|
||||||
{
|
{
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
Logger.WriteDebug($"Begin PreConnect for {E.Origin}");
|
Logger.WriteDebug($"Begin PreConnect for {E.Origin}");
|
||||||
@ -468,7 +463,8 @@ namespace IW4MAdmin
|
|||||||
client.Ping = origin.Ping;
|
client.Ping = origin.Ping;
|
||||||
client.Score = origin.Score;
|
client.Score = origin.Score;
|
||||||
|
|
||||||
if (origin.IPAddress == 0)
|
// update their IP if it hasn't been set yet
|
||||||
|
if (!client.IPAddress.HasValue)
|
||||||
{
|
{
|
||||||
return client.OnJoin(origin.IPAddress);
|
return client.OnJoin(origin.IPAddress);
|
||||||
}
|
}
|
||||||
@ -499,17 +495,9 @@ namespace IW4MAdmin
|
|||||||
#endif
|
#endif
|
||||||
Throttled = false;
|
Throttled = false;
|
||||||
|
|
||||||
foreach (var client in polledClients)
|
|
||||||
{
|
|
||||||
// todo: move out somehwere
|
|
||||||
var existingClient = Clients[client.ClientNumber] ?? client;
|
|
||||||
existingClient.Ping = client.Ping;
|
|
||||||
existingClient.Score = client.Score;
|
|
||||||
}
|
|
||||||
|
|
||||||
var disconnectingClients = currentClients.Except(polledClients);
|
var disconnectingClients = currentClients.Except(polledClients);
|
||||||
var connectingClients = polledClients.Except(currentClients);
|
var connectingClients = polledClients.Except(currentClients);
|
||||||
var updatedClients = polledClients.Except(connectingClients);
|
var updatedClients = polledClients.Except(connectingClients).Except(disconnectingClients);
|
||||||
|
|
||||||
return new List<EFClient>[]
|
return new List<EFClient>[]
|
||||||
{
|
{
|
||||||
@ -753,6 +741,7 @@ namespace IW4MAdmin
|
|||||||
infoResponse["fs_game"];
|
infoResponse["fs_game"];
|
||||||
var logfile = await this.GetDvarAsync<string>("g_log");
|
var logfile = await this.GetDvarAsync<string>("g_log");
|
||||||
var logsync = await this.GetDvarAsync<int>("g_logsync");
|
var logsync = await this.GetDvarAsync<int>("g_logsync");
|
||||||
|
var ip = await this.GetDvarAsync<string>("net_ip");
|
||||||
|
|
||||||
WorkingDirectory = basepath.Value;
|
WorkingDirectory = basepath.Value;
|
||||||
|
|
||||||
@ -774,6 +763,8 @@ namespace IW4MAdmin
|
|||||||
this.MaxClients = maxplayers;
|
this.MaxClients = maxplayers;
|
||||||
this.FSGame = game;
|
this.FSGame = game;
|
||||||
this.Gametype = gametype;
|
this.Gametype = gametype;
|
||||||
|
this.IP = ip.Value;
|
||||||
|
|
||||||
if (logsync.Value == 0 || logfile.Value == string.Empty)
|
if (logsync.Value == 0 || logfile.Value == string.Empty)
|
||||||
{
|
{
|
||||||
// this DVAR isn't set until the a map is loaded
|
// this DVAR isn't set until the a map is loaded
|
||||||
@ -1000,8 +991,6 @@ namespace IW4MAdmin
|
|||||||
};
|
};
|
||||||
|
|
||||||
await Manager.GetPenaltyService().Create(newPenalty);
|
await Manager.GetPenaltyService().Create(newPenalty);
|
||||||
// prevent them from logging in again
|
|
||||||
Manager.GetPrivilegedClients().Remove(Target.ClientId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override public async Task Unban(string reason, EFClient Target, EFClient Origin)
|
override public async Task Unban(string reason, EFClient Target, EFClient Origin)
|
||||||
|
@ -1,25 +1,21 @@
|
|||||||
using System;
|
using IW4MAdmin.Application.API.Master;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Text;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
using SharedLibraryCore;
|
using SharedLibraryCore;
|
||||||
using SharedLibraryCore.Interfaces;
|
|
||||||
using SharedLibraryCore.Commands;
|
using SharedLibraryCore.Commands;
|
||||||
using SharedLibraryCore.Helpers;
|
|
||||||
using SharedLibraryCore.Exceptions;
|
|
||||||
using SharedLibraryCore.Objects;
|
|
||||||
using SharedLibraryCore.Services;
|
|
||||||
using SharedLibraryCore.Configuration;
|
using SharedLibraryCore.Configuration;
|
||||||
using SharedLibraryCore.Database;
|
using SharedLibraryCore.Database;
|
||||||
using SharedLibraryCore.Events;
|
|
||||||
|
|
||||||
using IW4MAdmin.Application.API.Master;
|
|
||||||
using IW4MAdmin.Application.Migration;
|
|
||||||
using SharedLibraryCore.Database.Models;
|
using SharedLibraryCore.Database.Models;
|
||||||
|
using SharedLibraryCore.Events;
|
||||||
|
using SharedLibraryCore.Exceptions;
|
||||||
|
using SharedLibraryCore.Helpers;
|
||||||
|
using SharedLibraryCore.Interfaces;
|
||||||
|
using SharedLibraryCore.Services;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace IW4MAdmin.Application
|
namespace IW4MAdmin.Application
|
||||||
{
|
{
|
||||||
@ -61,7 +57,6 @@ namespace IW4MAdmin.Application
|
|||||||
ClientSvc = new ClientService();
|
ClientSvc = new ClientService();
|
||||||
AliasSvc = new AliasService();
|
AliasSvc = new AliasService();
|
||||||
PenaltySvc = new PenaltyService();
|
PenaltySvc = new PenaltyService();
|
||||||
PrivilegedClients = new Dictionary<int, EFClient>();
|
|
||||||
ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("IW4MAdminSettings");
|
ConfigHandler = new BaseConfigurationHandler<ApplicationConfiguration>("IW4MAdminSettings");
|
||||||
StartTime = DateTime.UtcNow;
|
StartTime = DateTime.UtcNow;
|
||||||
OnQuit = new ManualResetEventSlim();
|
OnQuit = new ManualResetEventSlim();
|
||||||
@ -86,61 +81,12 @@ namespace IW4MAdmin.Application
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
{
|
|
||||||
|
|
||||||
await newEvent.Owner.ExecuteEvent(newEvent);
|
await newEvent.Owner.ExecuteEvent(newEvent);
|
||||||
|
|
||||||
// save the event info to the database
|
// save the event info to the database
|
||||||
var changeHistorySvc = new ChangeHistoryService();
|
var changeHistorySvc = new ChangeHistoryService();
|
||||||
await changeHistorySvc.Add(args.Event);
|
await changeHistorySvc.Add(args.Event);
|
||||||
|
|
||||||
// todo: this is a hacky mess
|
|
||||||
if (newEvent.Origin?.DelayedEvents.Count > 0 &&
|
|
||||||
(//newEvent.Origin?.State == Player.ClientState.Connected ||
|
|
||||||
newEvent.Type == GameEvent.EventType.Connect))
|
|
||||||
{
|
|
||||||
var events = newEvent.Origin.DelayedEvents;
|
|
||||||
|
|
||||||
// add the delayed event to the queue
|
|
||||||
while (events.Count > 0)
|
|
||||||
{
|
|
||||||
var oldEvent = events.Dequeue();
|
|
||||||
|
|
||||||
var e = new GameEvent()
|
|
||||||
{
|
|
||||||
Type = oldEvent.Type,
|
|
||||||
Origin = newEvent.Origin,
|
|
||||||
Data = oldEvent.Data,
|
|
||||||
Extra = oldEvent.Extra,
|
|
||||||
Owner = oldEvent.Owner,
|
|
||||||
Message = oldEvent.Message,
|
|
||||||
Target = oldEvent.Target,
|
|
||||||
Remote = oldEvent.Remote
|
|
||||||
};
|
|
||||||
|
|
||||||
e.Origin = newEvent.Origin;
|
|
||||||
// check if the target was assigned
|
|
||||||
if (e.Target != null)
|
|
||||||
{
|
|
||||||
// update the target incase they left or have newer info
|
|
||||||
e.Target = newEvent.Owner.GetClientsAsList()
|
|
||||||
.FirstOrDefault(p => p.NetworkId == e.Target.NetworkId);
|
|
||||||
// we have to throw out the event because they left
|
|
||||||
if (e.Target == null)
|
|
||||||
{
|
|
||||||
Logger.WriteWarning($"Delayed event for {e.Origin} was ignored because the target has left");
|
|
||||||
// hack: don't do anything with the event because the target is invalid
|
|
||||||
e.Origin = null;
|
|
||||||
e.Type = GameEvent.EventType.Unknown;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Logger.WriteDebug($"Adding delayed event of type {e.Type} for {e.Origin} back for processing");
|
|
||||||
this.GetEventHandler().AddEvent(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
Logger.WriteDebug($"Processed event with id {newEvent.Id}");
|
Logger.WriteDebug($"Processed event with id {newEvent.Id}");
|
||||||
#endif
|
#endif
|
||||||
@ -263,36 +209,7 @@ namespace IW4MAdmin.Application
|
|||||||
await new ContextSeed(db).Seed();
|
await new ContextSeed(db).Seed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: optimize this (or replace it)
|
PrivilegedClients = (await ClientSvc.GetPrivilegedClients()).ToDictionary(_client => _client.ClientId);
|
||||||
var ipList = (await ClientSvc.Find(c => c.Level > EFClient.Permission.Trusted))
|
|
||||||
.Select(c => new
|
|
||||||
{
|
|
||||||
c.Password,
|
|
||||||
c.PasswordSalt,
|
|
||||||
c.ClientId,
|
|
||||||
c.Level,
|
|
||||||
c.Name
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach (var a in ipList)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
PrivilegedClients.Add(a.ClientId, new EFClient()
|
|
||||||
{
|
|
||||||
Name = a.Name,
|
|
||||||
ClientId = a.ClientId,
|
|
||||||
Level = a.Level,
|
|
||||||
PasswordSalt = a.PasswordSalt,
|
|
||||||
Password = a.Password
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (ArgumentException)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region CONFIG
|
#region CONFIG
|
||||||
@ -341,7 +258,9 @@ namespace IW4MAdmin.Application
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (config.Servers.Count == 0)
|
else if (config.Servers.Count == 0)
|
||||||
|
{
|
||||||
throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid");
|
throw new ServerException("A server configuration in IW4MAdminSettings.json is invalid");
|
||||||
|
}
|
||||||
|
|
||||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||||
Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252");
|
Utilities.EncodingType = Encoding.GetEncoding(!string.IsNullOrEmpty(config.CustomParserEncoding) ? config.CustomParserEncoding : "windows-1252");
|
||||||
@ -367,7 +286,9 @@ namespace IW4MAdmin.Application
|
|||||||
|
|
||||||
#region COMMANDS
|
#region COMMANDS
|
||||||
if (ClientSvc.GetOwners().Result.Count == 0)
|
if (ClientSvc.GetOwners().Result.Count == 0)
|
||||||
|
{
|
||||||
Commands.Add(new COwner());
|
Commands.Add(new COwner());
|
||||||
|
}
|
||||||
|
|
||||||
Commands.Add(new CQuit());
|
Commands.Add(new CQuit());
|
||||||
Commands.Add(new CKick());
|
Commands.Add(new CKick());
|
||||||
@ -408,7 +329,9 @@ namespace IW4MAdmin.Application
|
|||||||
Commands.Add(new CNextMap());
|
Commands.Add(new CNextMap());
|
||||||
|
|
||||||
foreach (Command C in SharedLibraryCore.Plugins.PluginImporter.ActiveCommands)
|
foreach (Command C in SharedLibraryCore.Plugins.PluginImporter.ActiveCommands)
|
||||||
|
{
|
||||||
Commands.Add(C);
|
Commands.Add(C);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region INIT
|
#region INIT
|
||||||
@ -443,7 +366,9 @@ namespace IW4MAdmin.Application
|
|||||||
{
|
{
|
||||||
Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_UNFIXABLE"]} [{Conf.IPAddress}:{Conf.Port}]");
|
Logger.WriteError($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_UNFIXABLE"]} [{Conf.IPAddress}:{Conf.Port}]");
|
||||||
if (e.GetType() == typeof(DvarException))
|
if (e.GetType() == typeof(DvarException))
|
||||||
|
{
|
||||||
Logger.WriteDebug($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR"]} {(e as DvarException).Data["dvar_name"]} ({Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR_HELP"]})");
|
Logger.WriteDebug($"{Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR"]} {(e as DvarException).Data["dvar_name"]} ({Utilities.CurrentLocalization.LocalizationIndex["SERVER_ERROR_DVAR_HELP"]})");
|
||||||
|
}
|
||||||
else if (e.GetType() == typeof(NetworkException))
|
else if (e.GetType() == typeof(NetworkException))
|
||||||
{
|
{
|
||||||
Logger.WriteDebug(e.Message);
|
Logger.WriteDebug(e.Message);
|
||||||
@ -572,23 +497,59 @@ namespace IW4MAdmin.Application
|
|||||||
return MessageTokens;
|
return MessageTokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<EFClient> GetActiveClients() => _servers.SelectMany(s => s.Clients).Where(p => p != null).ToList();
|
public IList<EFClient> GetActiveClients()
|
||||||
|
{
|
||||||
|
return _servers.SelectMany(s => s.Clients).Where(p => p != null).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public ClientService GetClientService() => ClientSvc;
|
public ClientService GetClientService()
|
||||||
public AliasService GetAliasService() => AliasSvc;
|
{
|
||||||
public PenaltyService GetPenaltyService() => PenaltySvc;
|
return ClientSvc;
|
||||||
public IConfigurationHandler<ApplicationConfiguration> GetApplicationSettings() => ConfigHandler;
|
}
|
||||||
public IDictionary<int, EFClient> GetPrivilegedClients() => PrivilegedClients;
|
|
||||||
public bool ShutdownRequested() => !Running;
|
public AliasService GetAliasService()
|
||||||
public IEventHandler GetEventHandler() => Handler;
|
{
|
||||||
|
return AliasSvc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PenaltyService GetPenaltyService()
|
||||||
|
{
|
||||||
|
return PenaltySvc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfigurationHandler<ApplicationConfiguration> GetApplicationSettings()
|
||||||
|
{
|
||||||
|
return ConfigHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDictionary<int, EFClient> GetPrivilegedClients()
|
||||||
|
{
|
||||||
|
return PrivilegedClients;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShutdownRequested()
|
||||||
|
{
|
||||||
|
return !Running;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEventHandler GetEventHandler()
|
||||||
|
{
|
||||||
|
return Handler;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetHasEvent()
|
public void SetHasEvent()
|
||||||
{
|
{
|
||||||
OnQuit.Set();
|
OnQuit.Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<Assembly> GetPluginAssemblies() => SharedLibraryCore.Plugins.PluginImporter.PluginAssemblies;
|
public IList<Assembly> GetPluginAssemblies()
|
||||||
|
{
|
||||||
|
return SharedLibraryCore.Plugins.PluginImporter.PluginAssemblies;
|
||||||
|
}
|
||||||
|
|
||||||
public IPageList GetPageList() => PageList;
|
public IPageList GetPageList()
|
||||||
|
{
|
||||||
|
return PageList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
using System;
|
using SharedLibraryCore;
|
||||||
|
using SharedLibraryCore.Database.Models;
|
||||||
|
using SharedLibraryCore.Exceptions;
|
||||||
|
using SharedLibraryCore.Interfaces;
|
||||||
|
using SharedLibraryCore.RCon;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using SharedLibraryCore.Interfaces;
|
|
||||||
using SharedLibraryCore.Objects;
|
|
||||||
using SharedLibraryCore;
|
|
||||||
using SharedLibraryCore.RCon;
|
|
||||||
using SharedLibraryCore.Exceptions;
|
|
||||||
using SharedLibraryCore.Database.Models;
|
|
||||||
|
|
||||||
namespace IW4MAdmin.Application.RconParsers
|
namespace IW4MAdmin.Application.RconParsers
|
||||||
{
|
{
|
||||||
@ -73,14 +71,19 @@ namespace IW4MAdmin.Application.RconParsers
|
|||||||
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"set {dvarName} {dvarValue}")).Length > 0;
|
return (await connection.SendQueryAsync(StaticHelpers.QueryType.COMMAND, $"set {dvarName} {dvarValue}")).Length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual CommandPrefix GetCommandPrefixes() => Prefixes;
|
public virtual CommandPrefix GetCommandPrefixes()
|
||||||
|
{
|
||||||
|
return Prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
private List<EFClient> ClientsFromStatus(string[] Status)
|
private List<EFClient> ClientsFromStatus(string[] Status)
|
||||||
{
|
{
|
||||||
List<EFClient> StatusPlayers = new List<EFClient>();
|
List<EFClient> StatusPlayers = new List<EFClient>();
|
||||||
|
|
||||||
if (Status.Length < 4)
|
if (Status.Length < 4)
|
||||||
|
{
|
||||||
throw new ServerException("Unexpected status response received");
|
throw new ServerException("Unexpected status response received");
|
||||||
|
}
|
||||||
|
|
||||||
int validMatches = 0;
|
int validMatches = 0;
|
||||||
foreach (String S in Status)
|
foreach (String S in Status)
|
||||||
@ -103,13 +106,21 @@ namespace IW4MAdmin.Application.RconParsers
|
|||||||
ping = int.Parse(regex.Groups[3].Value);
|
ping = int.Parse(regex.Groups[3].Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
long networkId = regex.Groups[4].Value.ConvertLong();
|
long networkId = regex.Groups[4].Value.ConvertLong();
|
||||||
string name = regex.Groups[5].Value.StripColors().Trim();
|
string name = regex.Groups[5].Value.StripColors().Trim();
|
||||||
int ip = regex.Groups[7].Value.Split(':')[0].ConvertToIP();
|
int ip = regex.Groups[7].Value.Split(':')[0].ConvertToIP();
|
||||||
|
|
||||||
var P = new EFClient()
|
var P = new EFClient()
|
||||||
{
|
{
|
||||||
Name = name,
|
CurrentAlias = new EFAlias()
|
||||||
|
{
|
||||||
|
Name = name
|
||||||
|
},
|
||||||
NetworkId = networkId,
|
NetworkId = networkId,
|
||||||
ClientNumber = clientNumber,
|
ClientNumber = clientNumber,
|
||||||
IPAddress = ip == 0 ? int.MinValue : ip,
|
IPAddress = ip == 0 ? int.MinValue : ip,
|
||||||
|
@ -23,6 +23,7 @@ class Instance(Resource):
|
|||||||
def put(self, id):
|
def put(self, id):
|
||||||
try:
|
try:
|
||||||
for server in request.json['servers']:
|
for server in request.json['servers']:
|
||||||
|
if 'ip' not in server or server['ip'] == 'localhost':
|
||||||
server['ip'] = request.remote_addr
|
server['ip'] = request.remote_addr
|
||||||
instance = InstanceSchema().load(request.json)
|
instance = InstanceSchema().load(request.json)
|
||||||
except ValidationError as err:
|
except ValidationError as err:
|
||||||
@ -34,6 +35,7 @@ class Instance(Resource):
|
|||||||
def post(self):
|
def post(self):
|
||||||
try:
|
try:
|
||||||
for server in request.json['servers']:
|
for server in request.json['servers']:
|
||||||
|
if 'ip' not in server or server['ip'] == 'localhost':
|
||||||
server['ip'] = request.remote_addr
|
server['ip'] = request.remote_addr
|
||||||
instance = InstanceSchema().load(request.json)
|
instance = InstanceSchema().load(request.json)
|
||||||
except ValidationError as err:
|
except ValidationError as err:
|
||||||
|
@ -25,7 +25,6 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
private ILogger Log;
|
private ILogger Log;
|
||||||
private readonly IManager Manager;
|
private readonly IManager Manager;
|
||||||
|
|
||||||
|
|
||||||
private readonly SemaphoreSlim OnProcessingPenalty;
|
private readonly SemaphoreSlim OnProcessingPenalty;
|
||||||
private readonly SemaphoreSlim OnProcessingSensitive;
|
private readonly SemaphoreSlim OnProcessingSensitive;
|
||||||
|
|
||||||
@ -348,7 +347,7 @@ namespace IW4MAdmin.Plugins.Stats.Helpers
|
|||||||
Log.WriteWarning("Could not add client to detection");
|
Log.WriteWarning("Could not add client to detection");
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.WriteInfo($"Adding {pl} to stats");
|
pl.CurrentServer.Logger.WriteInfo($"Adding {pl} to stats");
|
||||||
}
|
}
|
||||||
|
|
||||||
return clientStats;
|
return clientStats;
|
||||||
|
@ -250,7 +250,7 @@ namespace Tests
|
|||||||
unbanCommand.ExecuteAsync(new GameEvent()
|
unbanCommand.ExecuteAsync(new GameEvent()
|
||||||
{
|
{
|
||||||
Origin = new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer },
|
Origin = new EFClient() { ClientId = 1, Level = EFClient.Permission.Console, CurrentServer = client.CurrentServer },
|
||||||
Target = Manager.GetClientService().Find(c => c.NetworkId == client.NetworkId).Result.First().AsEFClient(),
|
Target = Manager.GetClientService().Find(c => c.NetworkId == client.NetworkId).Result.First(),
|
||||||
Data = "test unban",
|
Data = "test unban",
|
||||||
Type = GameEvent.EventType.Command,
|
Type = GameEvent.EventType.Command,
|
||||||
Owner = client.CurrentServer
|
Owner = client.CurrentServer
|
||||||
|
@ -84,7 +84,7 @@ namespace IW4MAdmin.Plugins.Welcome
|
|||||||
|
|
||||||
public async Task OnEventAsync(GameEvent E, Server S)
|
public async Task OnEventAsync(GameEvent E, Server S)
|
||||||
{
|
{
|
||||||
if (E.Type == GameEvent.EventType.Connect)
|
if (E.Type == GameEvent.EventType.Join)
|
||||||
{
|
{
|
||||||
EFClient newPlayer = E.Origin;
|
EFClient newPlayer = E.Origin;
|
||||||
if (newPlayer.Level >= Permission.Trusted && !E.Origin.Masked)
|
if (newPlayer.Level >= Permission.Trusted && !E.Origin.Masked)
|
||||||
|
@ -37,11 +37,25 @@ namespace SharedLibraryCore.Commands
|
|||||||
{
|
{
|
||||||
if ((await (E.Owner.Manager.GetClientService() as ClientService).GetOwners()).Count == 0)
|
if ((await (E.Owner.Manager.GetClientService() as ClientService).GetOwners()).Count == 0)
|
||||||
{
|
{
|
||||||
|
var oldPermission = E.Origin.Level;
|
||||||
E.Origin.Level = EFClient.Permission.Owner;
|
E.Origin.Level = EFClient.Permission.Owner;
|
||||||
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_SUCCESS"]);
|
E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_SUCCESS"]);
|
||||||
// so setpassword/login works
|
|
||||||
E.Owner.Manager.GetPrivilegedClients().Add(E.Origin.ClientId, E.Origin);
|
|
||||||
await E.Owner.Manager.GetClientService().Update(E.Origin);
|
await E.Owner.Manager.GetClientService().Update(E.Origin);
|
||||||
|
|
||||||
|
var e = new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.ChangePermission,
|
||||||
|
Origin = E.Origin,
|
||||||
|
Target = E.Origin,
|
||||||
|
Owner = E.Owner,
|
||||||
|
Extra = new Change()
|
||||||
|
{
|
||||||
|
PreviousValue = oldPermission.ToString(),
|
||||||
|
NewValue = E.Origin.Level.ToString()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
E.Owner.Manager.GetEventHandler().AddEvent(e);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -494,17 +508,6 @@ namespace SharedLibraryCore.Commands
|
|||||||
await E.Owner.Manager.GetClientService().Update(E.Target);
|
await E.Owner.Manager.GetClientService().Update(E.Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
E.Owner.Manager.GetPrivilegedClients().Add(E.Target.ClientId, E.Target);
|
|
||||||
}
|
|
||||||
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// this updates their privilege level to the webfront claims
|
|
||||||
E.Owner.Manager.GetPrivilegedClients()[E.Target.ClientId] = E.Target;
|
|
||||||
}
|
|
||||||
|
|
||||||
var e = new GameEvent()
|
var e = new GameEvent()
|
||||||
{
|
{
|
||||||
Origin = E.Origin,
|
Origin = E.Origin,
|
||||||
|
@ -22,7 +22,7 @@ namespace SharedLibraryCore.Database
|
|||||||
|
|
||||||
static string _ConnectionString;
|
static string _ConnectionString;
|
||||||
static string _provider;
|
static string _provider;
|
||||||
private static string _migrationPluginDirectory = @"X:\IW4MAdmin\BUILD\Plugins\";
|
private static readonly string _migrationPluginDirectory = @"X:\IW4MAdmin\BUILD\Plugins\";
|
||||||
|
|
||||||
public DatabaseContext(DbContextOptions<DatabaseContext> opt) : base(opt) { }
|
public DatabaseContext(DbContextOptions<DatabaseContext> opt) : base(opt) { }
|
||||||
|
|
||||||
@ -110,6 +110,7 @@ namespace SharedLibraryCore.Database
|
|||||||
|
|
||||||
modelBuilder.Entity<EFAlias>(ent =>
|
modelBuilder.Entity<EFAlias>(ent =>
|
||||||
{
|
{
|
||||||
|
ent.Property(a => a.IPAddress).IsRequired(false);
|
||||||
ent.HasIndex(a => a.IPAddress);
|
ent.HasIndex(a => a.IPAddress);
|
||||||
ent.Property(a => a.Name).HasMaxLength(24);
|
ent.Property(a => a.Name).HasMaxLength(24);
|
||||||
ent.HasIndex(a => a.Name);
|
ent.HasIndex(a => a.Name);
|
||||||
@ -123,14 +124,15 @@ namespace SharedLibraryCore.Database
|
|||||||
|
|
||||||
// adapted from
|
// adapted from
|
||||||
// https://aleemkhan.wordpress.com/2013/02/28/dynamically-adding-dbset-properties-in-dbcontext-for-entity-framework-code-first/
|
// https://aleemkhan.wordpress.com/2013/02/28/dynamically-adding-dbset-properties-in-dbcontext-for-entity-framework-code-first/
|
||||||
|
#if DEBUG
|
||||||
|
string pluginDir = _migrationPluginDirectory;
|
||||||
|
#else
|
||||||
string pluginDir = Path.Join(Utilities.OperatingDirectory, "Plugins");
|
string pluginDir = Path.Join(Utilities.OperatingDirectory, "Plugins");
|
||||||
|
#endif
|
||||||
IEnumerable<string> directoryFiles = Directory.GetFiles(pluginDir).Where(f => f.EndsWith(".dll"));
|
IEnumerable<string> directoryFiles = Directory.GetFiles(pluginDir).Where(f => f.EndsWith(".dll"));
|
||||||
|
|
||||||
#if DEBUG == TRUE
|
|
||||||
foreach (string dllPath in Directory.GetFiles(_migrationPluginDirectory).Where(f => f.EndsWith(".dll")))
|
|
||||||
#else
|
|
||||||
foreach (string dllPath in directoryFiles)
|
foreach (string dllPath in directoryFiles)
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
Assembly library;
|
Assembly library;
|
||||||
try
|
try
|
||||||
|
@ -16,7 +16,7 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
[MaxLength(24)]
|
[MaxLength(24)]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
[Required]
|
[Required]
|
||||||
public int IPAddress { get; set; }
|
public int? IPAddress { get; set; }
|
||||||
[Required]
|
[Required]
|
||||||
public DateTime DateAdded { get; set; }
|
public DateTime DateAdded { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -44,14 +44,14 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
set { CurrentAlias.Name = value; }
|
set { CurrentAlias.Name = value; }
|
||||||
}
|
}
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public virtual int IPAddress
|
public virtual int? IPAddress
|
||||||
{
|
{
|
||||||
get { return CurrentAlias.IPAddress; }
|
get { return CurrentAlias.IPAddress; }
|
||||||
set { CurrentAlias.IPAddress = value; }
|
set { CurrentAlias.IPAddress = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public string IPAddressString => new System.Net.IPAddress(BitConverter.GetBytes(IPAddress)).ToString();
|
public string IPAddressString => IPAddress.ConvertIPtoString();
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public virtual IDictionary<int, long> LinkedAccounts { get; set; }
|
public virtual IDictionary<int, long> LinkedAccounts { get; set; }
|
||||||
|
|
||||||
|
@ -208,38 +208,5 @@ namespace SharedLibraryCore
|
|||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// determine whether an event should be delayed or not
|
|
||||||
/// applies only to the origin entity
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="queuedEvent">event to determine status for</param>
|
|
||||||
/// <returns>true if event should be delayed, false otherwise</returns>
|
|
||||||
public static bool ShouldOriginEventBeDelayed(GameEvent queuedEvent)
|
|
||||||
{
|
|
||||||
return queuedEvent.Origin != null &&
|
|
||||||
(queuedEvent.Origin.State != EFClient.ClientState.Connected &&
|
|
||||||
// we want to allow join and quit events
|
|
||||||
queuedEvent.Type != EventType.Connect &&
|
|
||||||
queuedEvent.Type != EventType.Join &&
|
|
||||||
queuedEvent.Type != EventType.Quit &&
|
|
||||||
queuedEvent.Type != EventType.Disconnect &&
|
|
||||||
// we don't care about unknown events
|
|
||||||
queuedEvent.Origin.NetworkId != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// determine whether an event should be delayed or not
|
|
||||||
/// applies only to the target entity
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="queuedEvent">event to determine status for</param>
|
|
||||||
/// <returns>true if event should be delayed, false otherwise</returns>
|
|
||||||
public static bool ShouldTargetEventBeDelayed(GameEvent queuedEvent)
|
|
||||||
{
|
|
||||||
return (queuedEvent.Target != null && queuedEvent.Target.ClientNumber != -1) &&
|
|
||||||
(queuedEvent.Target.State != EFClient.ClientState.Connected &&
|
|
||||||
queuedEvent.Target.NetworkId != 0 &&
|
|
||||||
queuedEvent.Origin?.ClientId != 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
690
SharedLibraryCore/Migrations/20181125193243_MakeClientIPNullable.Designer.cs
generated
Normal file
690
SharedLibraryCore/Migrations/20181125193243_MakeClientIPNullable.Designer.cs
generated
Normal file
@ -0,0 +1,690 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using SharedLibraryCore.Database;
|
||||||
|
|
||||||
|
namespace SharedLibraryCore.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(DatabaseContext))]
|
||||||
|
[Migration("20181125193243_MakeClientIPNullable")]
|
||||||
|
partial class MakeClientIPNullable
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.1.4-rtm-31024");
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("SnapshotId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.Property<int>("CurrentSessionLength");
|
||||||
|
|
||||||
|
b.Property<double>("CurrentStrain");
|
||||||
|
|
||||||
|
b.Property<int>("CurrentViewAngleId");
|
||||||
|
|
||||||
|
b.Property<int>("Deaths");
|
||||||
|
|
||||||
|
b.Property<double>("Distance");
|
||||||
|
|
||||||
|
b.Property<double>("EloRating");
|
||||||
|
|
||||||
|
b.Property<int>("HitDestinationId");
|
||||||
|
|
||||||
|
b.Property<int>("HitLocation");
|
||||||
|
|
||||||
|
b.Property<int>("HitOriginId");
|
||||||
|
|
||||||
|
b.Property<int>("HitType");
|
||||||
|
|
||||||
|
b.Property<int>("Hits");
|
||||||
|
|
||||||
|
b.Property<int>("Kills");
|
||||||
|
|
||||||
|
b.Property<int>("LastStrainAngleId");
|
||||||
|
|
||||||
|
b.Property<double>("SessionAngleOffset");
|
||||||
|
|
||||||
|
b.Property<double>("SessionSPM");
|
||||||
|
|
||||||
|
b.Property<int>("SessionScore");
|
||||||
|
|
||||||
|
b.Property<double>("StrainAngleBetween");
|
||||||
|
|
||||||
|
b.Property<int>("TimeSinceLastEvent");
|
||||||
|
|
||||||
|
b.Property<int>("WeaponId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("SnapshotId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.HasIndex("CurrentViewAngleId");
|
||||||
|
|
||||||
|
b.HasIndex("HitDestinationId");
|
||||||
|
|
||||||
|
b.HasIndex("HitOriginId");
|
||||||
|
|
||||||
|
b.HasIndex("LastStrainAngleId");
|
||||||
|
|
||||||
|
b.ToTable("EFACSnapshot");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("KillId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("AttackerId");
|
||||||
|
|
||||||
|
b.Property<int>("Damage");
|
||||||
|
|
||||||
|
b.Property<int?>("DeathOriginVector3Id");
|
||||||
|
|
||||||
|
b.Property<int>("DeathType");
|
||||||
|
|
||||||
|
b.Property<double>("Fraction");
|
||||||
|
|
||||||
|
b.Property<int>("HitLoc");
|
||||||
|
|
||||||
|
b.Property<bool>("IsKill");
|
||||||
|
|
||||||
|
b.Property<int?>("KillOriginVector3Id");
|
||||||
|
|
||||||
|
b.Property<int>("Map");
|
||||||
|
|
||||||
|
b.Property<int>("ServerId");
|
||||||
|
|
||||||
|
b.Property<int>("VictimId");
|
||||||
|
|
||||||
|
b.Property<int?>("ViewAnglesVector3Id");
|
||||||
|
|
||||||
|
b.Property<double>("VisibilityPercentage");
|
||||||
|
|
||||||
|
b.Property<int>("Weapon");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("KillId");
|
||||||
|
|
||||||
|
b.HasIndex("AttackerId");
|
||||||
|
|
||||||
|
b.HasIndex("DeathOriginVector3Id");
|
||||||
|
|
||||||
|
b.HasIndex("KillOriginVector3Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("VictimId");
|
||||||
|
|
||||||
|
b.HasIndex("ViewAnglesVector3Id");
|
||||||
|
|
||||||
|
b.ToTable("EFClientKills");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("MessageId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.Property<int>("ServerId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TimeSent");
|
||||||
|
|
||||||
|
b.HasKey("MessageId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("TimeSent");
|
||||||
|
|
||||||
|
b.ToTable("EFClientMessages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("RatingHistoryId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.HasKey("RatingHistoryId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("EFClientRatingHistory");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.Property<int>("ServerId");
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("Deaths");
|
||||||
|
|
||||||
|
b.Property<double>("EloRating");
|
||||||
|
|
||||||
|
b.Property<int>("Kills");
|
||||||
|
|
||||||
|
b.Property<double>("MaxStrain");
|
||||||
|
|
||||||
|
b.Property<double>("RollingWeightedKDR");
|
||||||
|
|
||||||
|
b.Property<double>("SPM");
|
||||||
|
|
||||||
|
b.Property<double>("Skill");
|
||||||
|
|
||||||
|
b.Property<int>("TimePlayed");
|
||||||
|
|
||||||
|
b.Property<double>("VisionAverage");
|
||||||
|
|
||||||
|
b.HasKey("ClientId", "ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("EFClientStatistics");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("HitLocationCountId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId")
|
||||||
|
.HasColumnName("EFClientStatistics_ClientId");
|
||||||
|
|
||||||
|
b.Property<int>("HitCount");
|
||||||
|
|
||||||
|
b.Property<float>("HitOffsetAverage");
|
||||||
|
|
||||||
|
b.Property<int>("Location");
|
||||||
|
|
||||||
|
b.Property<float>("MaxAngleDistance");
|
||||||
|
|
||||||
|
b.Property<int>("ServerId")
|
||||||
|
.HasColumnName("EFClientStatistics_ServerId");
|
||||||
|
|
||||||
|
b.HasKey("HitLocationCountId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId", "ServerId");
|
||||||
|
|
||||||
|
b.ToTable("EFHitLocationCounts");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("RatingId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ActivityAmount");
|
||||||
|
|
||||||
|
b.Property<bool>("Newest");
|
||||||
|
|
||||||
|
b.Property<double>("Performance");
|
||||||
|
|
||||||
|
b.Property<int>("Ranking");
|
||||||
|
|
||||||
|
b.Property<int>("RatingHistoryId");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("RatingId");
|
||||||
|
|
||||||
|
b.HasIndex("Performance");
|
||||||
|
|
||||||
|
b.HasIndex("Ranking");
|
||||||
|
|
||||||
|
b.HasIndex("RatingHistoryId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.HasIndex("When");
|
||||||
|
|
||||||
|
b.ToTable("EFRating");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ServerId");
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("Port");
|
||||||
|
|
||||||
|
b.HasKey("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("EFServers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("StatisticId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ServerId");
|
||||||
|
|
||||||
|
b.Property<long>("TotalKills");
|
||||||
|
|
||||||
|
b.Property<long>("TotalPlayTime");
|
||||||
|
|
||||||
|
b.HasKey("StatisticId");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("EFServerStatistics");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AliasId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateAdded");
|
||||||
|
|
||||||
|
b.Property<int?>("IPAddress");
|
||||||
|
|
||||||
|
b.Property<int>("LinkId");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(24);
|
||||||
|
|
||||||
|
b.HasKey("AliasId");
|
||||||
|
|
||||||
|
b.HasIndex("IPAddress");
|
||||||
|
|
||||||
|
b.HasIndex("LinkId");
|
||||||
|
|
||||||
|
b.HasIndex("Name");
|
||||||
|
|
||||||
|
b.ToTable("EFAlias");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAliasLink", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AliasLinkId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.HasKey("AliasLinkId");
|
||||||
|
|
||||||
|
b.ToTable("EFAliasLinks");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFChangeHistory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ChangeHistoryId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<string>("Comment")
|
||||||
|
.HasMaxLength(128);
|
||||||
|
|
||||||
|
b.Property<string>("CurrentValue");
|
||||||
|
|
||||||
|
b.Property<int>("OriginEntityId");
|
||||||
|
|
||||||
|
b.Property<string>("PreviousValue");
|
||||||
|
|
||||||
|
b.Property<int>("TargetEntityId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TimeChanged");
|
||||||
|
|
||||||
|
b.Property<int>("TypeOfChange");
|
||||||
|
|
||||||
|
b.HasKey("ChangeHistoryId");
|
||||||
|
|
||||||
|
b.ToTable("EFChangeHistory");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("ClientId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("AliasLinkId");
|
||||||
|
|
||||||
|
b.Property<int>("Connections");
|
||||||
|
|
||||||
|
b.Property<int>("CurrentAliasId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FirstConnection");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastConnection");
|
||||||
|
|
||||||
|
b.Property<int>("Level");
|
||||||
|
|
||||||
|
b.Property<bool>("Masked");
|
||||||
|
|
||||||
|
b.Property<long>("NetworkId");
|
||||||
|
|
||||||
|
b.Property<string>("Password");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt");
|
||||||
|
|
||||||
|
b.Property<int>("TotalConnectionTime");
|
||||||
|
|
||||||
|
b.HasKey("ClientId");
|
||||||
|
|
||||||
|
b.HasIndex("AliasLinkId");
|
||||||
|
|
||||||
|
b.HasIndex("CurrentAliasId");
|
||||||
|
|
||||||
|
b.HasIndex("NetworkId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("EFClients");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("MetaId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<int>("ClientId");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Created");
|
||||||
|
|
||||||
|
b.Property<string>("Extra");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<DateTime>("Updated");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("MetaId");
|
||||||
|
|
||||||
|
b.HasIndex("ClientId");
|
||||||
|
|
||||||
|
b.ToTable("EFMeta");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("PenaltyId")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Active");
|
||||||
|
|
||||||
|
b.Property<string>("AutomatedOffense");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("Expires");
|
||||||
|
|
||||||
|
b.Property<int>("LinkId");
|
||||||
|
|
||||||
|
b.Property<int>("OffenderId");
|
||||||
|
|
||||||
|
b.Property<string>("Offense")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<int>("PunisherId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<DateTime>("When");
|
||||||
|
|
||||||
|
b.HasKey("PenaltyId");
|
||||||
|
|
||||||
|
b.HasIndex("LinkId");
|
||||||
|
|
||||||
|
b.HasIndex("OffenderId");
|
||||||
|
|
||||||
|
b.HasIndex("PunisherId");
|
||||||
|
|
||||||
|
b.ToTable("EFPenalties");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Vector3Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int?>("EFACSnapshotSnapshotId");
|
||||||
|
|
||||||
|
b.Property<float>("X");
|
||||||
|
|
||||||
|
b.Property<float>("Y");
|
||||||
|
|
||||||
|
b.Property<float>("Z");
|
||||||
|
|
||||||
|
b.HasKey("Vector3Id");
|
||||||
|
|
||||||
|
b.HasIndex("EFACSnapshotSnapshotId");
|
||||||
|
|
||||||
|
b.ToTable("Vector3");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "CurrentViewAngle")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CurrentViewAngleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitDestination")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("HitDestinationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "HitOrigin")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("HitOriginId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "LastStrainAngle")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("LastStrainAngleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientKill", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Attacker")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AttackerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "DeathOrigin")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("DeathOriginVector3Id");
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "KillOrigin")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("KillOriginVector3Id");
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Victim")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("VictimId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Helpers.Vector3", "ViewAngles")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ViewAnglesVector3Id");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientMessage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFHitLocationCount", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientStatistics")
|
||||||
|
.WithMany("HitLocations")
|
||||||
|
.HasForeignKey("ClientId", "ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFRating", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFClientRatingHistory", "RatingHistory")
|
||||||
|
.WithMany("Ratings")
|
||||||
|
.HasForeignKey("RatingHistoryId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("IW4MAdmin.Plugins.Stats.Models.EFServerStatistics", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFServer", "Server")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFAlias", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
|
||||||
|
.WithMany("Children")
|
||||||
|
.HasForeignKey("LinkId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFClient", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "AliasLink")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AliasLinkId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFAlias", "CurrentAlias")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CurrentAliasId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFMeta", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Client")
|
||||||
|
.WithMany("Meta")
|
||||||
|
.HasForeignKey("ClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Database.Models.EFPenalty", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFAliasLink", "Link")
|
||||||
|
.WithMany("ReceivedPenalties")
|
||||||
|
.HasForeignKey("LinkId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Offender")
|
||||||
|
.WithMany("ReceivedPenalties")
|
||||||
|
.HasForeignKey("OffenderId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
b.HasOne("SharedLibraryCore.Database.Models.EFClient", "Punisher")
|
||||||
|
.WithMany("AdministeredPenalties")
|
||||||
|
.HasForeignKey("PunisherId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("SharedLibraryCore.Helpers.Vector3", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("IW4MAdmin.Plugins.Stats.Models.EFACSnapshot")
|
||||||
|
.WithMany("PredictedViewAngles")
|
||||||
|
.HasForeignKey("EFACSnapshotSnapshotId");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace SharedLibraryCore.Migrations
|
||||||
|
{
|
||||||
|
public partial class MakeClientIPNullable : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
if (migrationBuilder.ActiveProvider == "Microsoft.EntityFrameworkCore.Sqlite")
|
||||||
|
{
|
||||||
|
migrationBuilder.Sql(@"PRAGMA foreign_keys = 0;
|
||||||
|
|
||||||
|
CREATE TABLE sqlitestudio_temp_table AS SELECT *
|
||||||
|
FROM EFAlias;
|
||||||
|
|
||||||
|
DROP TABLE EFAlias;
|
||||||
|
|
||||||
|
CREATE TABLE EFAlias (
|
||||||
|
AliasId INTEGER NOT NULL
|
||||||
|
CONSTRAINT PK_EFAlias PRIMARY KEY AUTOINCREMENT,
|
||||||
|
Active INTEGER NOT NULL,
|
||||||
|
DateAdded TEXT NOT NULL,
|
||||||
|
IPAddress INTEGER,
|
||||||
|
LinkId INTEGER NOT NULL,
|
||||||
|
Name TEXT NOT NULL,
|
||||||
|
CONSTRAINT FK_EFAlias_EFAliasLinks_LinkId FOREIGN KEY (
|
||||||
|
LinkId
|
||||||
|
)
|
||||||
|
REFERENCES EFAliasLinks (AliasLinkId) ON DELETE RESTRICT
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO EFAlias (
|
||||||
|
AliasId,
|
||||||
|
Active,
|
||||||
|
DateAdded,
|
||||||
|
IPAddress,
|
||||||
|
LinkId,
|
||||||
|
Name
|
||||||
|
)
|
||||||
|
SELECT AliasId,
|
||||||
|
Active,
|
||||||
|
DateAdded,
|
||||||
|
IPAddress,
|
||||||
|
LinkId,
|
||||||
|
Name
|
||||||
|
FROM sqlitestudio_temp_table;
|
||||||
|
|
||||||
|
DROP TABLE sqlitestudio_temp_table;
|
||||||
|
|
||||||
|
CREATE INDEX IX_EFAlias_LinkId ON EFAlias (
|
||||||
|
""LinkId""
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IX_EFAlias_IPAddress ON EFAlias(
|
||||||
|
""IPAddress""
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IX_EFAlias_Name ON EFAlias(
|
||||||
|
""Name""
|
||||||
|
);
|
||||||
|
|
||||||
|
PRAGMA foreign_keys = 1;
|
||||||
|
");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "IPAddress",
|
||||||
|
table: "EFAlias",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(int));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "IPAddress",
|
||||||
|
table: "EFAlias",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(int),
|
||||||
|
oldNullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -317,7 +317,7 @@ namespace SharedLibraryCore.Migrations
|
|||||||
|
|
||||||
b.Property<DateTime>("DateAdded");
|
b.Property<DateTime>("DateAdded");
|
||||||
|
|
||||||
b.Property<int>("IPAddress");
|
b.Property<int?>("IPAddress");
|
||||||
|
|
||||||
b.Property<int>("LinkId");
|
b.Property<int>("LinkId");
|
||||||
|
|
||||||
|
@ -80,7 +80,6 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
{
|
{
|
||||||
{ "_reportCount", 0 }
|
{ "_reportCount", 0 }
|
||||||
};
|
};
|
||||||
CurrentAlias = CurrentAlias ?? new EFAlias();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -405,7 +404,7 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
public void OnConnect()
|
public void OnConnect()
|
||||||
{
|
{
|
||||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||||
#if !DEBUG
|
|
||||||
if (Name.Length < 3)
|
if (Name.Length < 3)
|
||||||
{
|
{
|
||||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is too short");
|
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is too short");
|
||||||
@ -440,8 +439,6 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
|
|
||||||
LastConnection = DateTime.UtcNow;
|
LastConnection = DateTime.UtcNow;
|
||||||
Connections += 1;
|
Connections += 1;
|
||||||
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnDisconnect()
|
public async Task OnDisconnect()
|
||||||
@ -452,24 +449,11 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
await CurrentServer.Manager.GetClientService().Update(this);
|
await CurrentServer.Manager.GetClientService().Update(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task OnJoin(int ipAddress)
|
public async Task OnJoin(int? ipAddress)
|
||||||
{
|
{
|
||||||
// todo: fix this up
|
IPAddress = ipAddress;
|
||||||
var existingAlias = AliasLink.Children
|
|
||||||
.FirstOrDefault(a => a.Name == Name && a.IPAddress == ipAddress);
|
|
||||||
|
|
||||||
if (existingAlias == null)
|
await CurrentServer.Manager.GetClientService().UpdateAlias(this);
|
||||||
{
|
|
||||||
CurrentServer.Logger.WriteDebug($"Client {this} has connected previously under a different ip/name");
|
|
||||||
|
|
||||||
CurrentAlias = new EFAlias()
|
|
||||||
{
|
|
||||||
IPAddress = ipAddress,
|
|
||||||
Name = Name
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
await CurrentServer.Manager.GetClientService().Update(this);
|
|
||||||
|
|
||||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||||
var activePenalties = await CurrentServer.Manager.GetPenaltyService().GetActivePenaltiesAsync(AliasLinkId, ipAddress);
|
var activePenalties = await CurrentServer.Manager.GetPenaltyService().GetActivePenaltiesAsync(AliasLinkId, ipAddress);
|
||||||
@ -519,6 +503,19 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
Kick($"{loc["SERVER_TB_REMAIN"]} ({(currentBan.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient);
|
Kick($"{loc["SERVER_TB_REMAIN"]} ({(currentBan.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var e = new GameEvent()
|
||||||
|
{
|
||||||
|
Type = GameEvent.EventType.Join,
|
||||||
|
Origin = this,
|
||||||
|
Target = this,
|
||||||
|
Owner = CurrentServer
|
||||||
|
};
|
||||||
|
|
||||||
|
CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
@ -557,18 +554,7 @@ namespace SharedLibraryCore.Database.Models
|
|||||||
public int Score { get; set; }
|
public int Score { get; set; }
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public bool IsBot { get; set; }
|
public bool IsBot { get; set; }
|
||||||
//private int _ipaddress;
|
|
||||||
//public override int IPAddress
|
|
||||||
//{
|
|
||||||
// get => _ipaddress;
|
|
||||||
// set => _ipaddress = value;
|
|
||||||
//}
|
|
||||||
//private string _name;
|
|
||||||
//public override string Name
|
|
||||||
//{
|
|
||||||
// get => _name;
|
|
||||||
// set => _name = value;
|
|
||||||
//}
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public ClientState State { get; set; }
|
public ClientState State { get; set; }
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
|
@ -313,7 +313,7 @@ namespace SharedLibraryCore
|
|||||||
public bool RestartRequested { get; set; }
|
public bool RestartRequested { get; set; }
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
protected string IP;
|
public string IP { get; protected set; }
|
||||||
protected int Port;
|
protected int Port;
|
||||||
protected string FSGame;
|
protected string FSGame;
|
||||||
protected int NextMessage;
|
protected int NextMessage;
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
using System;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
using SharedLibraryCore.Database;
|
using SharedLibraryCore.Database;
|
||||||
using SharedLibraryCore.Database.Models;
|
using SharedLibraryCore.Database.Models;
|
||||||
using System.Linq.Expressions;
|
|
||||||
using SharedLibraryCore.Objects;
|
using SharedLibraryCore.Objects;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using System;
|
||||||
using SharedLibraryCore.Dtos;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using static SharedLibraryCore.Database.Models.EFClient;
|
using static SharedLibraryCore.Database.Models.EFClient;
|
||||||
|
|
||||||
namespace SharedLibraryCore.Services
|
namespace SharedLibraryCore.Services
|
||||||
@ -21,55 +17,28 @@ namespace SharedLibraryCore.Services
|
|||||||
{
|
{
|
||||||
using (var context = new DatabaseContext())
|
using (var context = new DatabaseContext())
|
||||||
{
|
{
|
||||||
bool hasExistingAlias = false;
|
|
||||||
// get all aliases by IP
|
|
||||||
var aliases = await context.Aliases
|
|
||||||
.Include(a => a.Link)
|
|
||||||
.Where(a => a.IPAddress == entity.IPAddress)
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
// see if they have a matching IP + Name but new NetworkId
|
|
||||||
var existingAlias = aliases.FirstOrDefault(a => a.Name == entity.Name);
|
|
||||||
// if existing alias matches link them
|
|
||||||
EFAliasLink aliasLink = existingAlias?.Link;
|
|
||||||
// if no exact matches find the first IP that matches
|
|
||||||
aliasLink = aliasLink ?? aliases.FirstOrDefault()?.Link;
|
|
||||||
// if no exact or IP matches, create new link
|
|
||||||
aliasLink = aliasLink ?? new EFAliasLink()
|
|
||||||
{
|
|
||||||
Active = true,
|
|
||||||
};
|
|
||||||
|
|
||||||
// this has to be set here because we can't evalute it properly later
|
|
||||||
hasExistingAlias = existingAlias != null;
|
|
||||||
|
|
||||||
// if no existing alias create new alias
|
|
||||||
existingAlias = existingAlias ?? new EFAlias()
|
|
||||||
{
|
|
||||||
Active = true,
|
|
||||||
DateAdded = DateTime.UtcNow,
|
|
||||||
IPAddress = entity.IPAddress,
|
|
||||||
Link = aliasLink,
|
|
||||||
Name = entity.Name,
|
|
||||||
};
|
|
||||||
|
|
||||||
var client = new EFClient()
|
var client = new EFClient()
|
||||||
{
|
{
|
||||||
Active = true,
|
Level = Permission.User,
|
||||||
// set the level to the level of the existing client if they have the same IP + Name but new NetworkId
|
|
||||||
// fixme: issues?
|
|
||||||
Level = hasExistingAlias ?
|
|
||||||
(await context.Clients.Where(c => c.AliasLinkId == existingAlias.LinkId)
|
|
||||||
.OrderByDescending(c => c.Level)
|
|
||||||
.FirstOrDefaultAsync())?.Level ?? Permission.User :
|
|
||||||
Permission.User,
|
|
||||||
FirstConnection = DateTime.UtcNow,
|
FirstConnection = DateTime.UtcNow,
|
||||||
Connections = 1,
|
Connections = 1,
|
||||||
LastConnection = DateTime.UtcNow,
|
LastConnection = DateTime.UtcNow,
|
||||||
Masked = false,
|
Masked = false,
|
||||||
NetworkId = entity.NetworkId,
|
NetworkId = entity.NetworkId,
|
||||||
AliasLink = aliasLink,
|
AliasLink = new EFAliasLink()
|
||||||
CurrentAlias = existingAlias,
|
{
|
||||||
|
Active = false
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
client.CurrentAlias = new Alias()
|
||||||
|
{
|
||||||
|
Name = entity.Name,
|
||||||
|
Link = client.AliasLink,
|
||||||
|
DateAdded = DateTime.UtcNow,
|
||||||
|
// the first time a client is created, we may not have their ip,
|
||||||
|
// so we create a temporary alias
|
||||||
|
Active = false
|
||||||
};
|
};
|
||||||
|
|
||||||
context.Clients.Add(client);
|
context.Clients.Add(client);
|
||||||
@ -79,6 +48,101 @@ namespace SharedLibraryCore.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task UpdateAlias(EFClient entity)
|
||||||
|
{
|
||||||
|
using (var context = new DatabaseContext())
|
||||||
|
{
|
||||||
|
context.Attach(entity);
|
||||||
|
|
||||||
|
string name = entity.Name;
|
||||||
|
int? ip = entity.IPAddress;
|
||||||
|
|
||||||
|
bool hasExistingAlias = false;
|
||||||
|
|
||||||
|
// get all aliases by IP
|
||||||
|
var aliases = await context.Aliases
|
||||||
|
.Include(a => a.Link)
|
||||||
|
.Where(a => a.IPAddress != null && a.IPAddress == ip)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
// see if they have a matching IP + Name but new NetworkId
|
||||||
|
var existingAlias = aliases.FirstOrDefault(a => a.Name == name);
|
||||||
|
// if existing alias matches link them
|
||||||
|
EFAliasLink aliasLink = existingAlias?.Link;
|
||||||
|
// if no exact matches find the first IP that matches
|
||||||
|
aliasLink = aliasLink ?? aliases.FirstOrDefault()?.Link;
|
||||||
|
// if no exact or IP matches, create new link
|
||||||
|
aliasLink = aliasLink ?? new EFAliasLink();
|
||||||
|
|
||||||
|
// this has to be set here because we can't evalute it properly later
|
||||||
|
hasExistingAlias = existingAlias != null;
|
||||||
|
|
||||||
|
if (hasExistingAlias && !entity.AliasLink.Active)
|
||||||
|
{
|
||||||
|
// we want to delete the temporary alias
|
||||||
|
context.Entry(entity.CurrentAlias).State = EntityState.Deleted;
|
||||||
|
entity.CurrentAlias = null;
|
||||||
|
|
||||||
|
// we want to delete the temporary alias link
|
||||||
|
context.Entry(entity.AliasLink).State = EntityState.Deleted;
|
||||||
|
entity.AliasLink = null;
|
||||||
|
|
||||||
|
// they have an existing alias so assign it
|
||||||
|
entity.CurrentAlias = existingAlias;
|
||||||
|
entity.AliasLink = aliasLink;
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the temporary alias to permanent one
|
||||||
|
else if (!entity.AliasLink.Active)
|
||||||
|
{
|
||||||
|
// we want to track the current alias and link
|
||||||
|
var alias = context.Update(entity.CurrentAlias).Entity;
|
||||||
|
var _aliasLink = context.Update(entity.AliasLink).Entity;
|
||||||
|
|
||||||
|
alias.Active = true;
|
||||||
|
alias.IPAddress = ip;
|
||||||
|
alias.Name = name;
|
||||||
|
_aliasLink.Active = true;
|
||||||
|
|
||||||
|
existingAlias = alias;
|
||||||
|
aliasLink = _aliasLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no existing alias create new alias
|
||||||
|
existingAlias = existingAlias ?? new EFAlias()
|
||||||
|
{
|
||||||
|
DateAdded = DateTime.UtcNow,
|
||||||
|
IPAddress = ip,
|
||||||
|
Link = aliasLink,
|
||||||
|
Name = name,
|
||||||
|
};
|
||||||
|
|
||||||
|
var iqExistingPermission = context.Clients.Where(c => c.AliasLinkId == existingAlias.LinkId)
|
||||||
|
.OrderByDescending(client => client.Level)
|
||||||
|
.Select(c => new EFClient() { Level = c.Level });
|
||||||
|
|
||||||
|
entity.Level = hasExistingAlias ?
|
||||||
|
(await iqExistingPermission.FirstOrDefaultAsync())?.Level ?? Permission.User :
|
||||||
|
Permission.User;
|
||||||
|
#if DEBUG
|
||||||
|
string sql = iqExistingPermission.AsQueryable().ToSql();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (entity.CurrentAlias != existingAlias ||
|
||||||
|
entity.AliasLink != aliasLink)
|
||||||
|
{
|
||||||
|
entity.CurrentAlias = existingAlias;
|
||||||
|
entity.AliasLink = aliasLink;
|
||||||
|
|
||||||
|
context.Update(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<EFClient> Delete(EFClient entity)
|
public async Task<EFClient> Delete(EFClient entity)
|
||||||
{
|
{
|
||||||
using (var context = new DatabaseContext())
|
using (var context = new DatabaseContext())
|
||||||
@ -132,13 +196,17 @@ namespace SharedLibraryCore.Services
|
|||||||
var foundClient = await iqClient.FirstOrDefaultAsync();
|
var foundClient = await iqClient.FirstOrDefaultAsync();
|
||||||
|
|
||||||
if (foundClient == null)
|
if (foundClient == null)
|
||||||
|
{
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
foundClient.Client.LinkedAccounts = new Dictionary<int, long>();
|
foundClient.Client.LinkedAccounts = new Dictionary<int, long>();
|
||||||
// todo: find out the best way to do this
|
// todo: find out the best way to do this
|
||||||
// I'm doing this here because I don't know the best way to have multiple awaits in the query
|
// I'm doing this here because I don't know the best way to have multiple awaits in the query
|
||||||
foreach (var linked in foundClient.LinkedAccounts)
|
foreach (var linked in foundClient.LinkedAccounts)
|
||||||
|
{
|
||||||
foundClient.Client.LinkedAccounts.Add(linked.ClientId, linked.NetworkId);
|
foundClient.Client.LinkedAccounts.Add(linked.ClientId, linked.NetworkId);
|
||||||
|
}
|
||||||
|
|
||||||
return foundClient.Client;
|
return foundClient.Client;
|
||||||
}
|
}
|
||||||
@ -168,7 +236,7 @@ namespace SharedLibraryCore.Services
|
|||||||
var client = context.Clients
|
var client = context.Clients
|
||||||
.Include(c => c.AliasLink)
|
.Include(c => c.AliasLink)
|
||||||
.Include(c => c.CurrentAlias)
|
.Include(c => c.CurrentAlias)
|
||||||
.Single(e => e.ClientId == entity.ClientId);
|
.First(e => e.ClientId == entity.ClientId);
|
||||||
|
|
||||||
// if their level has been changed
|
// if their level has been changed
|
||||||
if (entity.Level != client.Level)
|
if (entity.Level != client.Level)
|
||||||
@ -191,7 +259,7 @@ namespace SharedLibraryCore.Services
|
|||||||
{
|
{
|
||||||
client.CurrentAlias = new EFAlias()
|
client.CurrentAlias = new EFAlias()
|
||||||
{
|
{
|
||||||
Active = true,
|
Active = entity.CurrentAlias.IPAddress.HasValue ? true : false,
|
||||||
DateAdded = DateTime.UtcNow,
|
DateAdded = DateTime.UtcNow,
|
||||||
IPAddress = entity.CurrentAlias.IPAddress,
|
IPAddress = entity.CurrentAlias.IPAddress,
|
||||||
Name = entity.CurrentAlias.Name,
|
Name = entity.CurrentAlias.Name,
|
||||||
@ -202,6 +270,8 @@ namespace SharedLibraryCore.Services
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
client.CurrentAliasId = entity.CurrentAliasId;
|
client.CurrentAliasId = entity.CurrentAliasId;
|
||||||
|
client.IPAddress = entity.IPAddress;
|
||||||
|
client.Name = entity.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set remaining non-navigation properties that may have been updated
|
// set remaining non-navigation properties that may have been updated
|
||||||
@ -219,7 +289,10 @@ namespace SharedLibraryCore.Services
|
|||||||
|
|
||||||
// this is set so future updates don't trigger a new alias add
|
// this is set so future updates don't trigger a new alias add
|
||||||
if (entity.CurrentAlias.AliasId == 0)
|
if (entity.CurrentAlias.AliasId == 0)
|
||||||
|
{
|
||||||
entity.CurrentAlias.AliasId = client.CurrentAlias.AliasId;
|
entity.CurrentAlias.AliasId = client.CurrentAlias.AliasId;
|
||||||
|
}
|
||||||
|
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,24 +301,27 @@ namespace SharedLibraryCore.Services
|
|||||||
public async Task<IList<EFClient>> GetOwners()
|
public async Task<IList<EFClient>> GetOwners()
|
||||||
{
|
{
|
||||||
using (var context = new DatabaseContext())
|
using (var context = new DatabaseContext())
|
||||||
|
{
|
||||||
return await context.Clients
|
return await context.Clients
|
||||||
.Where(c => c.Level == Permission.Owner)
|
.Where(c => c.Level == Permission.Owner)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IList<ClientInfo>> GetPrivilegedClients()
|
public async Task<List<EFClient>> GetPrivilegedClients()
|
||||||
{
|
{
|
||||||
using (var context = new DatabaseContext(disableTracking: true))
|
using (var context = new DatabaseContext(disableTracking: true))
|
||||||
{
|
{
|
||||||
var iqClients = from client in context.Clients
|
var iqClients = from client in context.Clients
|
||||||
where client.Level >= Permission.Trusted
|
where client.Level >= Permission.Trusted
|
||||||
where client.Active
|
where client.Active
|
||||||
select new ClientInfo()
|
select new EFClient()
|
||||||
{
|
{
|
||||||
|
CurrentAlias = client.CurrentAlias,
|
||||||
ClientId = client.ClientId,
|
ClientId = client.ClientId,
|
||||||
Name = client.CurrentAlias.Name,
|
Level = client.Level,
|
||||||
LinkId = client.AliasLinkId,
|
Password = client.Password,
|
||||||
Level = client.Level
|
PasswordSalt = client.PasswordSalt
|
||||||
};
|
};
|
||||||
|
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
@ -294,20 +370,16 @@ namespace SharedLibraryCore.Services
|
|||||||
public async Task<int> GetTotalClientsAsync()
|
public async Task<int> GetTotalClientsAsync()
|
||||||
{
|
{
|
||||||
using (var context = new DatabaseContext(true))
|
using (var context = new DatabaseContext(true))
|
||||||
|
{
|
||||||
return await context.Clients
|
return await context.Clients
|
||||||
.CountAsync();
|
.CountAsync();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Task<EFClient> CreateProxy()
|
public Task<EFClient> CreateProxy()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<int> GetTotalPlayTime()
|
|
||||||
{
|
|
||||||
using (var context = new DatabaseContext(true))
|
|
||||||
return await context.Clients.SumAsync(c => c.TotalConnectionTime);
|
|
||||||
}
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ namespace SharedLibraryCore.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<EFPenalty>> GetActivePenaltiesAsync(int linkId, int ip = 0)
|
public async Task<List<EFPenalty>> GetActivePenaltiesAsync(int linkId, int? ip = null)
|
||||||
{
|
{
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ namespace SharedLibraryCore.Services
|
|||||||
{
|
{
|
||||||
var iqPenalties = context.Penalties
|
var iqPenalties = context.Penalties
|
||||||
.Where(p => p.LinkId == linkId ||
|
.Where(p => p.LinkId == linkId ||
|
||||||
p.Link.Children.Any(a => a.IPAddress == ip))
|
ip.HasValue ? p.Link.Children.Any(a => a.IPAddress == ip) : false)
|
||||||
.Where(p => p.Type == Penalty.PenaltyType.TempBan ||
|
.Where(p => p.Type == Penalty.PenaltyType.TempBan ||
|
||||||
p.Type == Penalty.PenaltyType.Ban ||
|
p.Type == Penalty.PenaltyType.Ban ||
|
||||||
p.Type == Penalty.PenaltyType.Flag)
|
p.Type == Penalty.PenaltyType.Flag)
|
||||||
|
@ -1,21 +1,18 @@
|
|||||||
using System;
|
using Microsoft.EntityFrameworkCore.Query;
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
using SharedLibraryCore.Objects;
|
|
||||||
using static SharedLibraryCore.Server;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
using Microsoft.EntityFrameworkCore.Query;
|
|
||||||
using Microsoft.EntityFrameworkCore.Query.Internal;
|
using Microsoft.EntityFrameworkCore.Query.Internal;
|
||||||
using Microsoft.EntityFrameworkCore.Storage;
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
using SharedLibraryCore.Database.Models;
|
using SharedLibraryCore.Database.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static SharedLibraryCore.Server;
|
||||||
|
|
||||||
namespace SharedLibraryCore
|
namespace SharedLibraryCore
|
||||||
{
|
{
|
||||||
@ -28,14 +25,20 @@ namespace SharedLibraryCore
|
|||||||
#endif
|
#endif
|
||||||
public static Encoding EncodingType;
|
public static Encoding EncodingType;
|
||||||
public static Localization.Layout CurrentLocalization = new Localization.Layout(new Dictionary<string, string>());
|
public static Localization.Layout CurrentLocalization = new Localization.Layout(new Dictionary<string, string>());
|
||||||
public static EFClient IW4MAdminClient(Server server = null) => new EFClient()
|
public static EFClient IW4MAdminClient(Server server = null)
|
||||||
|
{
|
||||||
|
return new EFClient()
|
||||||
{
|
{
|
||||||
ClientId = 1,
|
ClientId = 1,
|
||||||
State = EFClient.ClientState.Connected,
|
State = EFClient.ClientState.Connected,
|
||||||
Level = EFClient.Permission.Console,
|
Level = EFClient.Permission.Console,
|
||||||
CurrentServer = server,
|
CurrentServer = server,
|
||||||
|
CurrentAlias = new EFAlias()
|
||||||
|
{
|
||||||
Name = "IW4MAdmin"
|
Name = "IW4MAdmin"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static string HttpRequest(string location, string header, string headerValue)
|
public static string HttpRequest(string location, string header, string headerValue)
|
||||||
{
|
{
|
||||||
@ -64,7 +67,9 @@ namespace SharedLibraryCore
|
|||||||
public static String RemoveWords(this string str, int num)
|
public static String RemoveWords(this string str, int num)
|
||||||
{
|
{
|
||||||
if (str == null || str.Length == 0)
|
if (str == null || str.Length == 0)
|
||||||
|
{
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
String newStr = String.Empty;
|
String newStr = String.Empty;
|
||||||
String[] tmp = str.Split(' ');
|
String[] tmp = str.Split(' ');
|
||||||
@ -72,8 +77,10 @@ namespace SharedLibraryCore
|
|||||||
for (int i = 0; i < tmp.Length; i++)
|
for (int i = 0; i < tmp.Length; i++)
|
||||||
{
|
{
|
||||||
if (i >= num)
|
if (i >= num)
|
||||||
|
{
|
||||||
newStr += tmp[i] + ' ';
|
newStr += tmp[i] + ' ';
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return newStr;
|
return newStr;
|
||||||
}
|
}
|
||||||
@ -105,9 +112,13 @@ namespace SharedLibraryCore
|
|||||||
String lookingFor = str.ToLower();
|
String lookingFor = str.ToLower();
|
||||||
|
|
||||||
for (EFClient.Permission Perm = EFClient.Permission.User; Perm < EFClient.Permission.Console; Perm++)
|
for (EFClient.Permission Perm = EFClient.Permission.User; Perm < EFClient.Permission.Console; Perm++)
|
||||||
|
{
|
||||||
if (lookingFor.Contains(Perm.ToString().ToLower())
|
if (lookingFor.Contains(Perm.ToString().ToLower())
|
||||||
|| lookingFor.Contains(CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{Perm.ToString().ToUpper()}"].ToLower()))
|
|| lookingFor.Contains(CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{Perm.ToString().ToUpper()}"].ToLower()))
|
||||||
|
{
|
||||||
return Perm;
|
return Perm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return EFClient.Permission.Banned;
|
return EFClient.Permission.Banned;
|
||||||
}
|
}
|
||||||
@ -120,7 +131,10 @@ namespace SharedLibraryCore
|
|||||||
public static String StripColors(this string str)
|
public static String StripColors(this string str)
|
||||||
{
|
{
|
||||||
if (str == null)
|
if (str == null)
|
||||||
|
{
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
str = Regex.Replace(str, @"(\^+((?![a-z]|[A-Z]).){0,1})+", "");
|
str = Regex.Replace(str, @"(\^+((?![a-z]|[A-Z]).){0,1})+", "");
|
||||||
string str2 = Regex.Match(str, @"(^\/+.*$)|(^.*\/+$)")
|
string str2 = Regex.Match(str, @"(^\/+.*$)|(^.*\/+$)")
|
||||||
.Value
|
.Value
|
||||||
@ -161,7 +175,10 @@ namespace SharedLibraryCore
|
|||||||
return $"^{colorCode}{localizedLevel ?? level.ToString()}";
|
return $"^{colorCode}{localizedLevel ?? level.ToString()}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToLocalizedLevelName(this EFClient.Permission perm) => CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{perm.ToString().ToUpper()}"];
|
public static string ToLocalizedLevelName(this EFClient.Permission perm)
|
||||||
|
{
|
||||||
|
return CurrentLocalization.LocalizationIndex[$"GLOBAL_PERMISSION_{perm.ToString().ToUpper()}"];
|
||||||
|
}
|
||||||
|
|
||||||
public static String ProcessMessageToken(this Server server, IList<Helpers.MessageToken> tokens, String str)
|
public static String ProcessMessageToken(this Server server, IList<Helpers.MessageToken> tokens, String str)
|
||||||
{
|
{
|
||||||
@ -174,8 +191,10 @@ namespace SharedLibraryCore
|
|||||||
var found = tokens.FirstOrDefault(t => t.Name.ToLower() == Identifier.ToLower());
|
var found = tokens.FirstOrDefault(t => t.Name.ToLower() == Identifier.ToLower());
|
||||||
|
|
||||||
if (found != null)
|
if (found != null)
|
||||||
|
{
|
||||||
str = str.Replace(Match, found.Process(server));
|
str = str.Replace(Match, found.Process(server));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@ -245,11 +264,17 @@ namespace SharedLibraryCore
|
|||||||
{
|
{
|
||||||
str = str.Substring(0, Math.Min(str.Length, 16));
|
str = str.Substring(0, Math.Min(str.Length, 16));
|
||||||
if (Int64.TryParse(str, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long id))
|
if (Int64.TryParse(str, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out long id))
|
||||||
|
{
|
||||||
return id;
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
var bot = Regex.Match(str, @"bot[0-9]+").Value;
|
var bot = Regex.Match(str, @"bot[0-9]+").Value;
|
||||||
if (!string.IsNullOrEmpty(bot))
|
if (!string.IsNullOrEmpty(bot))
|
||||||
|
{
|
||||||
// should set their GUID to the negation of their 1 based index (-1 - -18)
|
// should set their GUID to the negation of their 1 based index (-1 - -18)
|
||||||
return -(Convert.ToInt64(bot.Substring(3)) + 1);
|
return -(Convert.ToInt64(bot.Substring(3)) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
return long.MinValue;
|
return long.MinValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,9 +285,9 @@ namespace SharedLibraryCore
|
|||||||
return ip == null ? int.MaxValue : BitConverter.ToInt32(ip.GetAddressBytes(), 0);
|
return ip == null ? int.MaxValue : BitConverter.ToInt32(ip.GetAddressBytes(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ConvertIPtoString(this int ip)
|
public static string ConvertIPtoString(this int? ip)
|
||||||
{
|
{
|
||||||
return new System.Net.IPAddress(BitConverter.GetBytes(ip)).ToString();
|
return !ip.HasValue ? "" : new System.Net.IPAddress(BitConverter.GetBytes(ip.Value)).ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String GetTimePassed(DateTime start)
|
public static String GetTimePassed(DateTime start)
|
||||||
@ -282,19 +307,28 @@ namespace SharedLibraryCore
|
|||||||
if (Elapsed.TotalMinutes < 120)
|
if (Elapsed.TotalMinutes < 120)
|
||||||
{
|
{
|
||||||
if (Elapsed.TotalMinutes < 1.5)
|
if (Elapsed.TotalMinutes < 1.5)
|
||||||
|
{
|
||||||
return $"1 {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_MINUTES"]}{ago}";
|
return $"1 {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_MINUTES"]}{ago}";
|
||||||
|
}
|
||||||
|
|
||||||
return Math.Round(Elapsed.TotalMinutes, 0) + $" {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_MINUTES"]}{ago}";
|
return Math.Round(Elapsed.TotalMinutes, 0) + $" {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_MINUTES"]}{ago}";
|
||||||
}
|
}
|
||||||
if (Elapsed.TotalHours <= 24)
|
if (Elapsed.TotalHours <= 24)
|
||||||
{
|
{
|
||||||
if (Elapsed.TotalHours < 1.5)
|
if (Elapsed.TotalHours < 1.5)
|
||||||
|
{
|
||||||
return $"1 {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]}{ago}";
|
return $"1 {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]}{ago}";
|
||||||
|
}
|
||||||
|
|
||||||
return Math.Round(Elapsed.TotalHours, 0) + $" { CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]}{ago}";
|
return Math.Round(Elapsed.TotalHours, 0) + $" { CurrentLocalization.LocalizationIndex["GLOBAL_TIME_HOURS"]}{ago}";
|
||||||
}
|
}
|
||||||
if (Elapsed.TotalDays <= 90)
|
if (Elapsed.TotalDays <= 90)
|
||||||
{
|
{
|
||||||
if (Elapsed.TotalDays < 1.5)
|
if (Elapsed.TotalDays < 1.5)
|
||||||
|
{
|
||||||
return $"1 {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_DAYS"]}{ago}";
|
return $"1 {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_DAYS"]}{ago}";
|
||||||
|
}
|
||||||
|
|
||||||
return Math.Round(Elapsed.TotalDays, 0) + $" {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_DAYS"]}{ago}";
|
return Math.Round(Elapsed.TotalDays, 0) + $" {CurrentLocalization.LocalizationIndex["GLOBAL_TIME_DAYS"]}{ago}";
|
||||||
}
|
}
|
||||||
if (Elapsed.TotalDays <= 365)
|
if (Elapsed.TotalDays <= 365)
|
||||||
@ -310,19 +344,39 @@ namespace SharedLibraryCore
|
|||||||
public static Game GetGame(string gameName)
|
public static Game GetGame(string gameName)
|
||||||
{
|
{
|
||||||
if (gameName.Contains("IW4"))
|
if (gameName.Contains("IW4"))
|
||||||
|
{
|
||||||
return Game.IW4;
|
return Game.IW4;
|
||||||
|
}
|
||||||
|
|
||||||
if (gameName.Contains("CoD4"))
|
if (gameName.Contains("CoD4"))
|
||||||
|
{
|
||||||
return Game.IW3;
|
return Game.IW3;
|
||||||
|
}
|
||||||
|
|
||||||
if (gameName.Contains("COD_WaW"))
|
if (gameName.Contains("COD_WaW"))
|
||||||
|
{
|
||||||
return Game.T4;
|
return Game.T4;
|
||||||
|
}
|
||||||
|
|
||||||
if (gameName.Contains("COD_T5_S"))
|
if (gameName.Contains("COD_T5_S"))
|
||||||
|
{
|
||||||
return Game.T5;
|
return Game.T5;
|
||||||
|
}
|
||||||
|
|
||||||
if (gameName.Contains("T5M"))
|
if (gameName.Contains("T5M"))
|
||||||
|
{
|
||||||
return Game.T5M;
|
return Game.T5M;
|
||||||
|
}
|
||||||
|
|
||||||
if (gameName.Contains("IW5"))
|
if (gameName.Contains("IW5"))
|
||||||
|
{
|
||||||
return Game.IW5;
|
return Game.IW5;
|
||||||
|
}
|
||||||
|
|
||||||
if (gameName.Contains("COD_T6_S"))
|
if (gameName.Contains("COD_T6_S"))
|
||||||
|
{
|
||||||
return Game.T6M;
|
return Game.T6M;
|
||||||
|
}
|
||||||
|
|
||||||
return Game.UKN;
|
return Game.UKN;
|
||||||
}
|
}
|
||||||
@ -337,7 +391,9 @@ namespace SharedLibraryCore
|
|||||||
var expressionMatch = Regex.Match(input, @"([0-9]+)(\w+)");
|
var expressionMatch = Regex.Match(input, @"([0-9]+)(\w+)");
|
||||||
|
|
||||||
if (!expressionMatch.Success) // fallback to default tempban length of 1 hour
|
if (!expressionMatch.Success) // fallback to default tempban length of 1 hour
|
||||||
|
{
|
||||||
return new TimeSpan(1, 0, 0);
|
return new TimeSpan(1, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
char lengthDenote = expressionMatch.Groups[2].ToString()[0];
|
char lengthDenote = expressionMatch.Groups[2].ToString()[0];
|
||||||
int length = Int32.Parse(expressionMatch.Groups[1].ToString());
|
int length = Int32.Parse(expressionMatch.Groups[1].ToString());
|
||||||
@ -377,52 +433,42 @@ namespace SharedLibraryCore
|
|||||||
var loc = CurrentLocalization.LocalizationIndex;
|
var loc = CurrentLocalization.LocalizationIndex;
|
||||||
|
|
||||||
if (span.TotalMinutes < 60)
|
if (span.TotalMinutes < 60)
|
||||||
|
{
|
||||||
return $"{span.Minutes} {loc["GLOBAL_TIME_MINUTES"]}";
|
return $"{span.Minutes} {loc["GLOBAL_TIME_MINUTES"]}";
|
||||||
|
}
|
||||||
else if (span.Hours >= 1 && span.TotalHours < 24)
|
else if (span.Hours >= 1 && span.TotalHours < 24)
|
||||||
|
{
|
||||||
return $"{span.Hours} {loc["GLOBAL_TIME_HOURS"]}";
|
return $"{span.Hours} {loc["GLOBAL_TIME_HOURS"]}";
|
||||||
|
}
|
||||||
else if (span.TotalDays >= 1 && span.TotalDays < 7)
|
else if (span.TotalDays >= 1 && span.TotalDays < 7)
|
||||||
|
{
|
||||||
return $"{span.Days} {loc["GLOBAL_TIME_DAYS"]}";
|
return $"{span.Days} {loc["GLOBAL_TIME_DAYS"]}";
|
||||||
|
}
|
||||||
else if (span.TotalDays >= 7 && span.TotalDays < 90)
|
else if (span.TotalDays >= 7 && span.TotalDays < 90)
|
||||||
|
{
|
||||||
return $"{Math.Round(span.Days / 7.0, 0)} {loc["GLOBAL_TIME_WEEKS"]}";
|
return $"{Math.Round(span.Days / 7.0, 0)} {loc["GLOBAL_TIME_WEEKS"]}";
|
||||||
|
}
|
||||||
else if (span.TotalDays >= 90 && span.TotalDays < 365)
|
else if (span.TotalDays >= 90 && span.TotalDays < 365)
|
||||||
|
{
|
||||||
return $"{Math.Round(span.Days / 30.0, 0)} {loc["GLOBAL_TIME_MONTHS"]}";
|
return $"{Math.Round(span.Days / 30.0, 0)} {loc["GLOBAL_TIME_MONTHS"]}";
|
||||||
|
}
|
||||||
else if (span.TotalDays >= 365 && span.TotalDays < 36500)
|
else if (span.TotalDays >= 365 && span.TotalDays < 36500)
|
||||||
|
{
|
||||||
return $"{Math.Round(span.Days / 365.0, 0)} {loc["GLOBAL_TIME_YEARS"]}";
|
return $"{Math.Round(span.Days / 365.0, 0)} {loc["GLOBAL_TIME_YEARS"]}";
|
||||||
|
}
|
||||||
else if (span.TotalDays >= 36500)
|
else if (span.TotalDays >= 36500)
|
||||||
|
{
|
||||||
return loc["GLOBAL_TIME_FOREVER"];
|
return loc["GLOBAL_TIME_FOREVER"];
|
||||||
|
}
|
||||||
|
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EFClient AsEFClient(this Database.Models.EFClient client)
|
public static bool IsPrivileged(this EFClient p)
|
||||||
{
|
{
|
||||||
return client == null ? null : new EFClient()
|
return p.Level > EFClient.Permission.User;
|
||||||
{
|
|
||||||
Active = client.Active,
|
|
||||||
AliasLink = client.AliasLink,
|
|
||||||
AliasLinkId = client.AliasLinkId,
|
|
||||||
ClientId = client.ClientId,
|
|
||||||
ClientNumber = -1,
|
|
||||||
FirstConnection = client.FirstConnection,
|
|
||||||
Connections = client.Connections,
|
|
||||||
NetworkId = client.NetworkId,
|
|
||||||
TotalConnectionTime = client.TotalConnectionTime,
|
|
||||||
Masked = client.Masked,
|
|
||||||
Name = client.CurrentAlias.Name,
|
|
||||||
IPAddress = client.CurrentAlias.IPAddress,
|
|
||||||
Level = client.Level,
|
|
||||||
LastConnection = client.LastConnection == DateTime.MinValue ? DateTime.UtcNow : client.LastConnection,
|
|
||||||
CurrentAlias = client.CurrentAlias,
|
|
||||||
CurrentAliasId = client.CurrentAlias.AliasId,
|
|
||||||
// todo: make sure this is up to date
|
|
||||||
IsBot = client.IPAddress == int.MinValue,
|
|
||||||
Password = client.Password,
|
|
||||||
PasswordSalt = client.PasswordSalt
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsPrivileged(this EFClient p) => p.Level > EFClient.Permission.User;
|
|
||||||
|
|
||||||
public static bool PromptBool(string question)
|
public static bool PromptBool(string question)
|
||||||
{
|
{
|
||||||
Console.Write($"{question}? [y/n]: ");
|
Console.Write($"{question}? [y/n]: ");
|
||||||
@ -474,7 +520,9 @@ namespace SharedLibraryCore
|
|||||||
int.TryParse(lineSplit[cIDPos].Trim(), out pID);
|
int.TryParse(lineSplit[cIDPos].Trim(), out pID);
|
||||||
|
|
||||||
if (pID == -1) // special case similar to mod_suicide
|
if (pID == -1) // special case similar to mod_suicide
|
||||||
|
{
|
||||||
int.TryParse(lineSplit[2], out pID);
|
int.TryParse(lineSplit[2], out pID);
|
||||||
|
}
|
||||||
|
|
||||||
return pID;
|
return pID;
|
||||||
}
|
}
|
||||||
@ -489,8 +537,10 @@ namespace SharedLibraryCore
|
|||||||
{
|
{
|
||||||
dict = new Dictionary<string, string>();
|
dict = new Dictionary<string, string>();
|
||||||
for (int i = 0; i < values.Length; i += 2)
|
for (int i = 0; i < values.Length; i += 2)
|
||||||
|
{
|
||||||
dict.Add(values[i], values[i + 1]);
|
dict.Add(values[i], values[i + 1]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
@ -518,15 +568,30 @@ namespace SharedLibraryCore
|
|||||||
return cmdLine.Length > 1 ? cmdLine[1] : cmdLine[0];
|
return cmdLine.Length > 1 ? cmdLine[1] : cmdLine[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToBase64UrlSafeString(this string src) => Convert.ToBase64String(src.Select(c => Convert.ToByte(c)).ToArray()).Replace('+', '-').Replace('/', '_');
|
public static string ToBase64UrlSafeString(this string src)
|
||||||
|
{
|
||||||
|
return Convert.ToBase64String(src.Select(c => Convert.ToByte(c)).ToArray()).Replace('+', '-').Replace('/', '_');
|
||||||
|
}
|
||||||
|
|
||||||
public static Task<Dvar<T>> GetDvarAsync<T>(this Server server, string dvarName) => server.RconParser.GetDvarAsync<T>(server.RemoteConnection, dvarName);
|
public static Task<Dvar<T>> GetDvarAsync<T>(this Server server, string dvarName)
|
||||||
|
{
|
||||||
|
return server.RconParser.GetDvarAsync<T>(server.RemoteConnection, dvarName);
|
||||||
|
}
|
||||||
|
|
||||||
public static Task SetDvarAsync(this Server server, string dvarName, object dvarValue) => server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
|
public static Task SetDvarAsync(this Server server, string dvarName, object dvarValue)
|
||||||
|
{
|
||||||
|
return server.RconParser.SetDvarAsync(server.RemoteConnection, dvarName, dvarValue);
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<string[]> ExecuteCommandAsync(this Server server, string commandName) => await server.RconParser.ExecuteCommandAsync(server.RemoteConnection, commandName);
|
public static async Task<string[]> ExecuteCommandAsync(this Server server, string commandName)
|
||||||
|
{
|
||||||
|
return await server.RconParser.ExecuteCommandAsync(server.RemoteConnection, commandName);
|
||||||
|
}
|
||||||
|
|
||||||
public static Task<List<EFClient>> GetStatusAsync(this Server server) => server.RconParser.GetStatusAsync(server.RemoteConnection);
|
public static Task<List<EFClient>> GetStatusAsync(this Server server)
|
||||||
|
{
|
||||||
|
return server.RconParser.GetStatusAsync(server.RemoteConnection);
|
||||||
|
}
|
||||||
|
|
||||||
public static async Task<Dictionary<string, string>> GetInfoAsync(this Server server)
|
public static async Task<Dictionary<string, string>> GetInfoAsync(this Server server)
|
||||||
{
|
{
|
||||||
@ -535,7 +600,10 @@ namespace SharedLibraryCore
|
|||||||
{
|
{
|
||||||
response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO);
|
response = await server.RemoteConnection.SendQueryAsync(RCon.StaticHelpers.QueryType.GET_INFO);
|
||||||
if (response.Length == 2)
|
if (response.Length == 2)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
await Task.Delay(RCon.StaticHelpers.FloodProtectionInterval);
|
await Task.Delay(RCon.StaticHelpers.FloodProtectionInterval);
|
||||||
}
|
}
|
||||||
return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue();
|
return response.FirstOrDefault(r => r[0] == '\\')?.DictionaryFromKeyValue();
|
||||||
@ -548,7 +616,10 @@ namespace SharedLibraryCore
|
|||||||
return double.Parse(version) / 1000.0;
|
return double.Parse(version) / 1000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetVersionAsString() => Assembly.GetCallingAssembly().GetName().Version.ToString();
|
public static string GetVersionAsString()
|
||||||
|
{
|
||||||
|
return Assembly.GetCallingAssembly().GetName().Version.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG == true
|
#if DEBUG == true
|
||||||
|
|
||||||
|
@ -57,13 +57,6 @@ namespace WebfrontCore.Controllers
|
|||||||
Client.ClientId = Convert.ToInt32(base.User.Claims.First(c => c.Type == ClaimTypes.Sid).Value);
|
Client.ClientId = Convert.ToInt32(base.User.Claims.First(c => c.Type == ClaimTypes.Sid).Value);
|
||||||
Client.Level = (EFClient.Permission)Enum.Parse(typeof(EFClient.Permission), User.Claims.First(c => c.Type == ClaimTypes.Role).Value);
|
Client.Level = (EFClient.Permission)Enum.Parse(typeof(EFClient.Permission), User.Claims.First(c => c.Type == ClaimTypes.Role).Value);
|
||||||
Client.CurrentAlias = new EFAlias() { Name = User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value };
|
Client.CurrentAlias = new EFAlias() { Name = User.Claims.First(c => c.Type == ClaimTypes.NameIdentifier).Value };
|
||||||
var stillExists = Manager.GetPrivilegedClients()[Client.ClientId];
|
|
||||||
|
|
||||||
// this happens if their level has been updated
|
|
||||||
if (stillExists.Level != Client.Level)
|
|
||||||
{
|
|
||||||
Client.Level = stillExists.Level;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (InvalidOperationException)
|
catch (InvalidOperationException)
|
||||||
@ -78,11 +71,13 @@ namespace WebfrontCore.Controllers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// give the local host full access
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Client.ClientId = 1;
|
Client.ClientId = 1;
|
||||||
Client.Level = EFClient.Permission.Console;
|
Client.Level = EFClient.Permission.Console;
|
||||||
Client.CurrentAlias = new EFAlias() { Name = "IW4MAdmin" };
|
Client.CurrentAlias = new EFAlias() { Name = "IW4MAdmin" };
|
||||||
|
Authorized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Authorized = Client.ClientId >= 0;
|
Authorized = Client.ClientId >= 0;
|
||||||
|
@ -121,7 +121,7 @@ namespace WebfrontCore.Controllers
|
|||||||
{
|
{
|
||||||
var admins = (await Manager.GetClientService().GetPrivilegedClients())
|
var admins = (await Manager.GetClientService().GetPrivilegedClients())
|
||||||
.OrderByDescending(a => a.Level)
|
.OrderByDescending(a => a.Level)
|
||||||
.GroupBy(a => a.LinkId).Select(a => a.First());
|
.GroupBy(a => a.AliasLinkId).Select(a => a.First());
|
||||||
|
|
||||||
var adminsDict = new Dictionary<EFClient.Permission, IList<ClientInfo>>();
|
var adminsDict = new Dictionary<EFClient.Permission, IList<ClientInfo>>();
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@model Dictionary<SharedLibraryCore.Objects.Player.Permission, IList<SharedLibraryCore.Dtos.ClientInfo>>
|
@model Dictionary<SharedLibraryCore.Database.Models.EFClient.Permission, IList<SharedLibraryCore.Dtos.ClientInfo>>
|
||||||
|
|
||||||
<h4 class="pb-2 text-center ">@ViewBag.Title</h4>
|
<h4 class="pb-2 text-center ">@ViewBag.Title</h4>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user