combined Penalty and EFPenalty
moved some classes around
This commit is contained in:
7
SharedLibraryCore/PartialEntities/EFAlias.cs
Normal file
7
SharedLibraryCore/PartialEntities/EFAlias.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace SharedLibraryCore.Database.Models
|
||||
{
|
||||
public partial class EFAlias
|
||||
{
|
||||
|
||||
}
|
||||
}
|
758
SharedLibraryCore/PartialEntities/EFClient.cs
Normal file
758
SharedLibraryCore/PartialEntities/EFClient.cs
Normal file
@ -0,0 +1,758 @@
|
||||
using SharedLibraryCore.Localization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharedLibraryCore.Database.Models
|
||||
{
|
||||
public partial class EFClient
|
||||
{
|
||||
public enum ClientState
|
||||
{
|
||||
/// <summary>
|
||||
/// represents when the client has been detected as joining
|
||||
/// by the log file, but has not be authenticated by RCon
|
||||
/// </summary>
|
||||
Connecting,
|
||||
/// <summary>
|
||||
/// represents when the client has been authenticated by RCon
|
||||
/// and validated by the database
|
||||
/// </summary>
|
||||
Connected,
|
||||
/// <summary>
|
||||
/// represents when the client is leaving (either through RCon or log file)
|
||||
/// </summary>
|
||||
Disconnecting,
|
||||
}
|
||||
|
||||
public enum Permission
|
||||
{
|
||||
/// <summary>
|
||||
/// client has been banned
|
||||
/// </summary>
|
||||
Banned = -1,
|
||||
/// <summary>
|
||||
/// default client state upon first connect
|
||||
/// </summary>
|
||||
User = 0,
|
||||
/// <summary>
|
||||
/// client has been flagged
|
||||
/// </summary>
|
||||
Flagged = 1,
|
||||
/// <summary>
|
||||
/// client is trusted
|
||||
/// </summary>
|
||||
Trusted = 2,
|
||||
/// <summary>
|
||||
/// client is a moderator
|
||||
/// </summary>
|
||||
Moderator = 3,
|
||||
/// <summary>
|
||||
/// client is an administrator
|
||||
/// </summary>
|
||||
Administrator = 4,
|
||||
/// <summary>
|
||||
/// client is a senior administrator
|
||||
/// </summary>
|
||||
SeniorAdmin = 5,
|
||||
/// <summary>
|
||||
/// client is a owner
|
||||
/// </summary>
|
||||
Owner = 6,
|
||||
/// <summary>
|
||||
/// not used
|
||||
/// </summary>
|
||||
Creator = 7,
|
||||
/// <summary>
|
||||
/// reserved for default account
|
||||
/// </summary>
|
||||
Console = 8
|
||||
}
|
||||
|
||||
public EFClient()
|
||||
{
|
||||
ConnectionTime = DateTime.UtcNow;
|
||||
ClientNumber = -1;
|
||||
_additionalProperties = new Dictionary<string, object>
|
||||
{
|
||||
{ "_reportCount", 0 }
|
||||
};
|
||||
ReceivedPenalties = new List<EFPenalty>();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{CurrentAlias?.Name ?? "--"}::{NetworkId}";
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public virtual string Name
|
||||
{
|
||||
get { return CurrentAlias?.Name ?? "--"; }
|
||||
set { if (CurrentAlias != null) CurrentAlias.Name = value; }
|
||||
}
|
||||
[NotMapped]
|
||||
public virtual int? IPAddress
|
||||
{
|
||||
get { return CurrentAlias.IPAddress; }
|
||||
set { CurrentAlias.IPAddress = value; }
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public string IPAddressString => IPAddress.ConvertIPtoString();
|
||||
[NotMapped]
|
||||
public virtual IDictionary<int, long> LinkedAccounts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// send a message directly to the connected client
|
||||
/// </summary>
|
||||
/// <param name="message">message content to send to client</param>
|
||||
public GameEvent Tell(String message)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Message = message,
|
||||
Target = this,
|
||||
Owner = CurrentServer,
|
||||
Type = GameEvent.EventType.Tell,
|
||||
Data = message
|
||||
};
|
||||
|
||||
CurrentServer?.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// warn a client with given reason
|
||||
/// </summary>
|
||||
/// <param name="warnReason">reason for warn</param>
|
||||
/// <param name="sender">client performing the warn</param>
|
||||
public GameEvent Warn(String warnReason, EFClient sender)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Warn,
|
||||
Message = warnReason,
|
||||
Data = warnReason,
|
||||
Origin = sender,
|
||||
Target = this,
|
||||
Owner = sender.CurrentServer
|
||||
};
|
||||
|
||||
// enforce level restrictions
|
||||
if (Level > sender.Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Warnings++;
|
||||
}
|
||||
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// clear all warnings for a client
|
||||
/// </summary>
|
||||
/// <param name="sender">client performing the warn clear</param>
|
||||
/// <returns></returns>
|
||||
public GameEvent WarnClear(EFClient sender)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.WarnClear,
|
||||
Origin = sender,
|
||||
Target = this,
|
||||
Owner = sender.CurrentServer
|
||||
};
|
||||
|
||||
// enforce level restrictions
|
||||
if (sender.Level <= Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
return e;
|
||||
}
|
||||
|
||||
Warnings = 0;
|
||||
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// report a client for a given reason
|
||||
/// </summary>
|
||||
/// <param name="reportReason">reason for the report</param>
|
||||
/// <param name="sender">client performing the report</param>
|
||||
/// <returns></returns>
|
||||
public GameEvent Report(string reportReason, EFClient sender)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Report,
|
||||
Message = reportReason,
|
||||
Data = reportReason,
|
||||
Origin = sender,
|
||||
Target = this,
|
||||
Owner = sender.CurrentServer
|
||||
};
|
||||
|
||||
int reportCount = sender.GetAdditionalProperty<int>("_reportCount");
|
||||
|
||||
if (Level > sender.Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
}
|
||||
|
||||
else if (Equals(sender))
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Invalid;
|
||||
}
|
||||
|
||||
else if (reportCount > 2)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Throttle;
|
||||
}
|
||||
|
||||
else if (CurrentServer.Reports.Count(report => (report.Origin.NetworkId == sender.NetworkId &&
|
||||
report.Target.NetworkId == NetworkId)) > 0)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Exception;
|
||||
}
|
||||
|
||||
sender.SetAdditionalProperty("_reportCount", reportCount + 1);
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// flag a client for a given reason
|
||||
/// </summary>
|
||||
/// <param name="flagReason">reason for flagging</param>
|
||||
/// <param name="sender">client performing the flag</param>
|
||||
/// <returns>game event for the flag</returns>
|
||||
public GameEvent Flag(string flagReason, EFClient sender)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Flag,
|
||||
Origin = sender,
|
||||
Data = flagReason,
|
||||
Message = flagReason,
|
||||
Target = this,
|
||||
Owner = sender.CurrentServer
|
||||
};
|
||||
|
||||
if (Level >= sender.Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
}
|
||||
|
||||
else if (Level == Permission.Flagged)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Invalid;
|
||||
}
|
||||
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// unflag a client for a given reason
|
||||
/// </summary>
|
||||
/// <param name="unflagReason">reason to unflag a player for</param>
|
||||
/// <param name="sender">client performing the unflag</param>
|
||||
/// <returns>game event for the un flug</returns>
|
||||
public GameEvent Unflag(string unflagReason, EFClient sender)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Unflag,
|
||||
Origin = sender,
|
||||
Target = this,
|
||||
Data = unflagReason,
|
||||
Message = unflagReason,
|
||||
Owner = sender.CurrentServer
|
||||
};
|
||||
|
||||
if (sender.Level <= Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
}
|
||||
|
||||
else if (Level != Permission.Flagged)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Invalid;
|
||||
}
|
||||
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// kick a client for the given reason
|
||||
/// </summary>
|
||||
/// <param name="kickReason">reason to kick for</param>
|
||||
/// <param name="sender">client performing the kick</param>
|
||||
public GameEvent Kick(String kickReason, EFClient sender)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Kick,
|
||||
Message = kickReason,
|
||||
Target = this,
|
||||
Origin = sender,
|
||||
Data = kickReason,
|
||||
Owner = sender.CurrentServer
|
||||
};
|
||||
|
||||
// enforce level restrictions
|
||||
if (Level > sender.Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
}
|
||||
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// temporarily ban a client for the given time span
|
||||
/// </summary>
|
||||
/// <param name="tempbanReason">reason for the temp ban</param>
|
||||
/// <param name="banLength">how long the temp ban lasts</param>
|
||||
/// <param name="sender">client performing the tempban</param>
|
||||
public GameEvent TempBan(String tempbanReason, TimeSpan banLength, EFClient sender)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.TempBan,
|
||||
Message = tempbanReason,
|
||||
Data = tempbanReason,
|
||||
Origin = sender,
|
||||
Target = this,
|
||||
Extra = banLength,
|
||||
Owner = sender.CurrentServer
|
||||
};
|
||||
|
||||
// enforce level restrictions
|
||||
if (sender.Level <= Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
}
|
||||
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// permanently ban a client
|
||||
/// </summary>
|
||||
/// <param name="banReason">reason for the ban</param>
|
||||
/// <param name="sender">client performing the ban</param>
|
||||
public GameEvent Ban(String banReason, EFClient sender, bool isEvade)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Ban,
|
||||
Message = banReason,
|
||||
Data = banReason,
|
||||
Origin = sender,
|
||||
Target = this,
|
||||
Owner = sender.CurrentServer,
|
||||
Extra = isEvade
|
||||
};
|
||||
|
||||
// enforce level restrictions
|
||||
if (sender.Level <= Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
}
|
||||
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// unban a client
|
||||
/// </summary>
|
||||
/// <param name="unbanReason">reason for the unban</param>
|
||||
/// <param name="sender">client performing the unban</param>
|
||||
/// <returns></returns>
|
||||
public GameEvent Unban(string unbanReason, EFClient sender)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Unban,
|
||||
Message = unbanReason,
|
||||
Data = unbanReason,
|
||||
Origin = sender,
|
||||
Target = this,
|
||||
Owner = sender.CurrentServer
|
||||
};
|
||||
|
||||
// enforce level restrictions
|
||||
if (Level > sender.Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
}
|
||||
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sets the level of the client
|
||||
/// </summary>
|
||||
/// <param name="newPermission">new permission to set client to</param>
|
||||
/// <param name="sender">user performing the set level</param>
|
||||
/// <returns></returns>
|
||||
public GameEvent SetLevel(Permission newPermission, EFClient sender)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.ChangePermission,
|
||||
Extra = newPermission,
|
||||
Origin = sender,
|
||||
Target = this,
|
||||
Owner = sender.CurrentServer
|
||||
};
|
||||
|
||||
if (Level > sender.Level)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Permission;
|
||||
}
|
||||
|
||||
else if (Level == newPermission)
|
||||
{
|
||||
e.FailReason = GameEvent.EventFailReason.Invalid;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Level = newPermission;
|
||||
}
|
||||
|
||||
sender.CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
return e;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles any client related logic on connection
|
||||
/// </summary>
|
||||
public bool OnConnect()
|
||||
{
|
||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||
|
||||
LastConnection = DateTime.UtcNow;
|
||||
Connections += 1;
|
||||
|
||||
if (Name.Length < 3)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is too short");
|
||||
Kick(loc["SERVER_KICK_MINNAME"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CurrentServer.Manager.GetApplicationSettings().Configuration()
|
||||
.DisallowedClientNames
|
||||
?.Any(_name => Regex.IsMatch(Name, _name)) ?? false)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name is generic");
|
||||
Kick(loc["SERVER_KICK_GENERICNAME"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Name.Where(c => char.IsControl(c)).Count() > 0)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their name contains control characters");
|
||||
Kick(loc["SERVER_KICK_CONTROLCHARS"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
|
||||
// reserved slots stuff
|
||||
// todo: bots don't seem to honor party_maxplayers/sv_maxclients
|
||||
if (CurrentServer.MaxClients - (CurrentServer.GetClientsAsList().Count(_client => !_client.IsPrivileged() && !_client.IsBot)) < CurrentServer.ServerConfig.ReservedSlotNumber &&
|
||||
!this.IsPrivileged() &&
|
||||
CurrentServer.GetClientsAsList().Count <= CurrentServer.MaxClients &&
|
||||
CurrentServer.MaxClients != 0)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} their spot is reserved");
|
||||
Kick(loc["SERVER_KICK_SLOT_IS_RESERVED"], Utilities.IW4MAdminClient(CurrentServer));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task OnDisconnect()
|
||||
{
|
||||
State = ClientState.Disconnecting;
|
||||
TotalConnectionTime += ConnectionLength;
|
||||
LastConnection = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
await CurrentServer.Manager.GetClientService().Update(this);
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
{
|
||||
CurrentServer.Logger.WriteWarning($"Could not update disconnected player {this}");
|
||||
CurrentServer.Logger.WriteDebug(e.GetExceptionInfo());
|
||||
}
|
||||
}
|
||||
|
||||
public async Task OnJoin(int? ipAddress)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Start join for {this}::{ipAddress}::{Level.ToString()}");
|
||||
|
||||
if (ipAddress != null)
|
||||
{
|
||||
IPAddress = ipAddress;
|
||||
await CurrentServer.Manager.GetClientService().UpdateAlias(this);
|
||||
await CurrentServer.Manager.GetClientService().Update(this);
|
||||
|
||||
bool canConnect = await CanConnect(ipAddress);
|
||||
|
||||
if (canConnect)
|
||||
{
|
||||
var e = new GameEvent()
|
||||
{
|
||||
Type = GameEvent.EventType.Join,
|
||||
Origin = this,
|
||||
Target = this,
|
||||
Owner = CurrentServer
|
||||
};
|
||||
|
||||
CurrentServer.Manager.GetEventHandler().AddEvent(e);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Client {this} is not allowed to join the server");
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Client {this} does not have an IP yet");
|
||||
}
|
||||
|
||||
CurrentServer.Logger.WriteDebug($"OnJoin finished for {this}");
|
||||
}
|
||||
|
||||
private async Task<bool> CanConnect(int? ipAddress)
|
||||
{
|
||||
var loc = Utilities.CurrentLocalization.LocalizationIndex;
|
||||
var autoKickClient = Utilities.IW4MAdminClient(CurrentServer);
|
||||
|
||||
#region CLIENT_GUID_BAN
|
||||
// kick them as their level is banned
|
||||
if (Level == Permission.Banned)
|
||||
{
|
||||
var profileBan = ReceivedPenalties.FirstOrDefault(_penalty => _penalty.Expires == null && _penalty.Active && _penalty.Type == EFPenalty.PenaltyType.Ban);
|
||||
|
||||
if (profileBan == null)
|
||||
{
|
||||
// this is from the old system before bans were applied to all accounts
|
||||
profileBan = (await CurrentServer.Manager
|
||||
.GetPenaltyService()
|
||||
.GetActivePenaltiesAsync(AliasLinkId))
|
||||
.OrderByDescending(_penalty => _penalty.When)
|
||||
.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Ban);
|
||||
|
||||
CurrentServer.Logger.WriteWarning($"Client {this} is GUID banned, but no previous penalty exists for their ban");
|
||||
|
||||
if (profileBan == null)
|
||||
{
|
||||
profileBan = new EFPenalty() { Offense = loc["SERVER_BAN_UNKNOWN"] };
|
||||
CurrentServer.Logger.WriteWarning($"Client {this} is GUID banned, but we could not find the penalty on any linked accounts");
|
||||
}
|
||||
|
||||
// hack: re apply the automated offense to the reban
|
||||
if (profileBan.AutomatedOffense != null)
|
||||
{
|
||||
autoKickClient.AdministeredPenalties?.Add(new EFPenalty()
|
||||
{
|
||||
AutomatedOffense = profileBan.AutomatedOffense
|
||||
});
|
||||
}
|
||||
|
||||
// this is a reban of the new GUID and IP
|
||||
Ban($"{profileBan.Offense}", autoKickClient, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because they are banned");
|
||||
Kick(loc["SERVER_BAN_PREV"].FormatExt(profileBan?.Offense), autoKickClient);
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CLIENT_GUID_TEMPBAN
|
||||
else
|
||||
{
|
||||
var profileTempBan = ReceivedPenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.TempBan &&
|
||||
_penalty.Active &&
|
||||
_penalty.Expires > DateTime.UtcNow);
|
||||
|
||||
// they have an active tempban tied to their GUID
|
||||
if (profileTempBan != null)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Kicking {this} because their GUID is temporarily banned");
|
||||
Kick($"{loc["SERVER_TB_REMAIN"]} ({(profileTempBan.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
// we want to get any penalties that are tied to their IP or AliasLink (but not necessarily their GUID)
|
||||
var activePenalties = await CurrentServer.Manager.GetPenaltyService().GetActivePenaltiesAsync(AliasLinkId, ipAddress);
|
||||
|
||||
#region CLIENT_LINKED_BAN
|
||||
var currentBan = activePenalties.FirstOrDefault(p => p.Type == EFPenalty.PenaltyType.Ban);
|
||||
|
||||
// they have a perm ban tied to their AliasLink/profile
|
||||
if (currentBan != null)
|
||||
{
|
||||
CurrentServer.Logger.WriteInfo($"Banned client {this} trying to evade...");
|
||||
|
||||
// reban the "evading" guid
|
||||
if (Level != Permission.Banned)
|
||||
{
|
||||
CurrentServer.Logger.WriteInfo($"Banned client {this} connected using a new GUID");
|
||||
|
||||
// hack: re apply the automated offense to the reban
|
||||
if (currentBan.AutomatedOffense != null)
|
||||
{
|
||||
autoKickClient.AdministeredPenalties?.Add(new EFPenalty()
|
||||
{
|
||||
AutomatedOffense = currentBan.AutomatedOffense
|
||||
});
|
||||
}
|
||||
// this is a reban of the new GUID and IP
|
||||
Ban($"{currentBan.Offense}", autoKickClient, true);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CurrentServer.Logger.WriteError($"Banned client {this} is banned but, no ban penalty was found (2)");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CLIENT_LINKED_TEMPBAN
|
||||
var tempBan = activePenalties
|
||||
.OrderByDescending(_penalty => _penalty.When)
|
||||
.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.TempBan);
|
||||
|
||||
// they have an active tempban tied to their AliasLink
|
||||
if (tempBan != null)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Tempbanning {this} because their AliasLink is temporarily banned, but they are not");
|
||||
TempBan(tempBan.Offense, DateTime.UtcNow - (tempBan.Expires ?? DateTime.UtcNow), autoKickClient);
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CLIENT_LINKED_FLAG
|
||||
if (Level != Permission.Flagged)
|
||||
{
|
||||
var currentFlag = activePenalties.FirstOrDefault(_penalty => _penalty.Type == EFPenalty.PenaltyType.Flag);
|
||||
|
||||
if (currentFlag != null)
|
||||
{
|
||||
CurrentServer.Logger.WriteDebug($"Flagging {this} because their AliasLink is flagged, but they are not");
|
||||
Flag(currentFlag.Offense, autoKickClient);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
if (Level == Permission.Flagged)
|
||||
{
|
||||
var currentAutoFlag = activePenalties
|
||||
.Where(p => p.Type == EFPenalty.PenaltyType.Flag && p.PunisherId == 1)
|
||||
.OrderByDescending(p => p.When)
|
||||
.FirstOrDefault();
|
||||
|
||||
// remove their auto flag status after a week
|
||||
if (currentAutoFlag != null &&
|
||||
(DateTime.UtcNow - currentAutoFlag.When).TotalDays > 7)
|
||||
{
|
||||
CurrentServer.Logger.WriteInfo($"Unflagging {this} because the auto flag time has expired");
|
||||
Unflag(Utilities.CurrentLocalization.LocalizationIndex["SERVER_AUTOFLAG_UNFLAG"], autoKickClient);
|
||||
}
|
||||
}
|
||||
|
||||
return true && OnConnect();
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
readonly Dictionary<string, object> _additionalProperties;
|
||||
|
||||
public T GetAdditionalProperty<T>(string name)
|
||||
{
|
||||
return _additionalProperties.ContainsKey(name) ? (T)_additionalProperties[name] : default(T);
|
||||
}
|
||||
|
||||
public void SetAdditionalProperty(string name, object value)
|
||||
{
|
||||
if (_additionalProperties.ContainsKey(name))
|
||||
{
|
||||
_additionalProperties[name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_additionalProperties.Add(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
[NotMapped]
|
||||
public int ClientNumber { get; set; }
|
||||
[NotMapped]
|
||||
public int Ping { get; set; }
|
||||
[NotMapped]
|
||||
public int Warnings { get; set; }
|
||||
[NotMapped]
|
||||
public DateTime ConnectionTime { get; set; }
|
||||
[NotMapped]
|
||||
public int ConnectionLength => (int)(DateTime.UtcNow - ConnectionTime).TotalSeconds;
|
||||
[NotMapped]
|
||||
public Server CurrentServer { get; set; }
|
||||
[NotMapped]
|
||||
public int Score { get; set; }
|
||||
[NotMapped]
|
||||
public bool IsBot => NetworkId == -1;
|
||||
|
||||
[NotMapped]
|
||||
public ClientState State { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
// this is kinda dirty, but I need localizable level names
|
||||
public ClientPermission ClientPermission => new ClientPermission()
|
||||
{
|
||||
Level = Level,
|
||||
Name = Utilities.CurrentLocalization
|
||||
.LocalizationIndex[$"GLOBAL_PERMISSION_{Level.ToString().ToUpper()}"]
|
||||
};
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return ((EFClient)obj).NetworkId == this.NetworkId;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return IsBot ? ClientNumber : (int)NetworkId;
|
||||
}
|
||||
}
|
||||
}
|
21
SharedLibraryCore/PartialEntities/EFPenalty.cs
Normal file
21
SharedLibraryCore/PartialEntities/EFPenalty.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using SharedLibraryCore;
|
||||
|
||||
namespace SharedLibraryCore.Database.Models
|
||||
{
|
||||
public partial class EFPenalty
|
||||
{
|
||||
public enum PenaltyType
|
||||
{
|
||||
Report,
|
||||
Warning,
|
||||
Flag,
|
||||
Kick,
|
||||
TempBan,
|
||||
Ban,
|
||||
Unban,
|
||||
Any,
|
||||
Unflag
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user