diff --git a/Application/IW4MServer.cs b/Application/IW4MServer.cs index 916b11423..f8000731e 100644 --- a/Application/IW4MServer.cs +++ b/Application/IW4MServer.cs @@ -82,11 +82,7 @@ namespace IW4MAdmin }; Manager.GetEventHandler().AddEvent(e); - - if (client.IPAddress != null) - { - await client.OnJoin(client.IPAddress); - } + await client.OnJoin(client.IPAddress); } catch (Exception ex) @@ -186,6 +182,9 @@ namespace IW4MAdmin { if (E.Type == GameEvent.EventType.ChangePermission) { + var newPermission = (EFClient.Permission)E.Extra; + E.Target.Level = newPermission; + if (!E.Target.IsPrivileged()) { // remove banned or demoted privileged user @@ -196,6 +195,8 @@ namespace IW4MAdmin { Manager.GetPrivilegedClients()[E.Target.ClientId] = E.Target; } + + await Manager.GetClientService().Update(E.Target); } else if (E.Type == GameEvent.EventType.PreConnect) @@ -611,6 +612,17 @@ namespace IW4MAdmin if (ConnectionErrors > 0) { Logger.WriteVerbose($"{loc["MANAGER_CONNECTION_REST"]} {IP}:{Port}"); + + var _event = new GameEvent() + { + Type = GameEvent.EventType.ConnectionRestored, + Owner = this, + Origin = Utilities.IW4MAdminClient(this), + Target = Utilities.IW4MAdminClient(this) + }; + + Manager.GetEventHandler().AddEvent(_event); + Throttled = false; } @@ -625,6 +637,19 @@ namespace IW4MAdmin { Logger.WriteError($"{e.Message} {IP}:{Port}, {loc["SERVER_ERROR_POLLING"]}"); Logger.WriteDebug($"Internal Exception: {e.Data["internal_exception"]}"); + + var _event = new GameEvent() + { + Type = GameEvent.EventType.ConnectionLost, + Owner = this, + Origin = Utilities.IW4MAdminClient(this), + Target = Utilities.IW4MAdminClient(this), + Extra = e, + Data = ConnectionErrors.ToString() + }; + + Manager.GetEventHandler().AddEvent(_event); + Throttled = true; } return true; diff --git a/Plugins/Stats/Controllers/StatsController.cs b/Plugins/Stats/Controllers/StatsController.cs index 0ea8df0aa..88160efa3 100644 --- a/Plugins/Stats/Controllers/StatsController.cs +++ b/Plugins/Stats/Controllers/StatsController.cs @@ -16,8 +16,8 @@ namespace IW4MAdmin.Plugins.Stats.Web.Controllers [HttpGet] public IActionResult TopPlayersAsync() { - ViewBag.Title = Utilities.CurrentLocalization.LocalizationIndex.Set["WEBFRONT_STATS_INDEX_TITLE"]; - ViewBag.Description = Utilities.CurrentLocalization.LocalizationIndex.Set["WEBFRONT_STATS_INDEX_DESC"]; + ViewBag.Title = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_STATS_INDEX_TITLE"]; + ViewBag.Description = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_STATS_INDEX_DESC"]; ViewBag.Servers = Manager.GetServers().Select(_server => new ServerInfo() { Name = _server.Hostname, ID = _server.EndPoint }); return View("Index"); diff --git a/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml b/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml index 66cac6315..39f4ae8eb 100644 --- a/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml +++ b/Plugins/Web/StatsWeb/Views/Stats/Components/TopPlayers/_List.cshtml @@ -28,7 +28,7 @@ @if (Model.Count == 0) { -
@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex.Set["PLUGINS_STATS_TEXT_NOQUALIFY"]
+
@SharedLibraryCore.Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_NOQUALIFY"]
} @foreach (var stat in Model) { diff --git a/SharedLibraryCore/Commands/NativeCommands.cs b/SharedLibraryCore/Commands/NativeCommands.cs index a49396cab..3417cc6f6 100644 --- a/SharedLibraryCore/Commands/NativeCommands.cs +++ b/SharedLibraryCore/Commands/NativeCommands.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using SharedLibraryCore.Database; using SharedLibraryCore.Database.Models; -using SharedLibraryCore.Events; using SharedLibraryCore.Objects; using SharedLibraryCore.Services; using System; @@ -18,7 +17,7 @@ namespace SharedLibraryCore.Commands public class CQuit : Command { public CQuit() : - base("quit", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_QUIT_DESC"], "q", EFClient.Permission.Owner, false) + base("quit", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_QUIT_DESC"], "q", EFClient.Permission.Owner, false) { } public override Task ExecuteAsync(GameEvent E) @@ -30,32 +29,15 @@ namespace SharedLibraryCore.Commands public class COwner : Command { public COwner() : - base("owner", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_DESC"], "iamgod", EFClient.Permission.User, false) + base("owner", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_DESC"], "iamgod", EFClient.Permission.User, false) { } public override async Task ExecuteAsync(GameEvent E) { - if ((await (E.Owner.Manager.GetClientService() as ClientService).GetOwners()).Count == 0) + if (await (E.Owner.Manager.GetClientService() as ClientService).GetOwnerCount() == 0 && + !E.Target.SetLevel(EFClient.Permission.Owner, Utilities.IW4MAdminClient(E.Owner)).Failed) { - var oldPermission = E.Origin.Level; - E.Origin.Level = EFClient.Permission.Owner; E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_OWNER_SUCCESS"]); - 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 { @@ -67,7 +49,7 @@ namespace SharedLibraryCore.Commands public class CWarn : Command { public CWarn() : - base("warn", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARN_DESC"], "w", EFClient.Permission.Trusted, true, new CommandArgument[] + base("warn", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARN_DESC"], "w", EFClient.Permission.Trusted, true, new CommandArgument[] { new CommandArgument() { @@ -96,7 +78,7 @@ namespace SharedLibraryCore.Commands public class CWarnClear : Command { public CWarnClear() : - base("warnclear", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARNCLEAR_DESC"], "wc", EFClient.Permission.Trusted, true, new CommandArgument[] + base("warnclear", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WARNCLEAR_DESC"], "wc", EFClient.Permission.Trusted, true, new CommandArgument[] { new CommandArgument() { @@ -120,7 +102,7 @@ namespace SharedLibraryCore.Commands public class CKick : Command { public CKick() : - base("kick", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_DESC"], "k", EFClient.Permission.Moderator, true, new CommandArgument[] + base("kick", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_KICK_DESC"], "k", EFClient.Permission.Moderator, true, new CommandArgument[] { new CommandArgument() { @@ -146,7 +128,7 @@ namespace SharedLibraryCore.Commands public class CSay : Command { public CSay() : - base("say", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SAY_DESC"], "s", EFClient.Permission.Moderator, false, new CommandArgument[] + base("say", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SAY_DESC"], "s", EFClient.Permission.Moderator, false, new CommandArgument[] { new CommandArgument() { @@ -166,7 +148,7 @@ namespace SharedLibraryCore.Commands public class CTempBan : Command { public CTempBan() : - base("tempban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_DESC"], "tb", EFClient.Permission.Administrator, true, new CommandArgument[] + base("tempban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_TEMPBAN_DESC"], "tb", EFClient.Permission.Administrator, true, new CommandArgument[] { new CommandArgument() { @@ -214,7 +196,7 @@ namespace SharedLibraryCore.Commands public class CBan : Command { public CBan() : - base("ban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_DESC"], "b", EFClient.Permission.SeniorAdmin, true, new CommandArgument[] + base("ban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BAN_DESC"], "b", EFClient.Permission.SeniorAdmin, true, new CommandArgument[] { new CommandArgument() { @@ -240,7 +222,7 @@ namespace SharedLibraryCore.Commands public class CUnban : Command { public CUnban() : - base("unban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_DESC"], "ub", EFClient.Permission.SeniorAdmin, true, new CommandArgument[] + base("unban", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNBAN_DESC"], "ub", EFClient.Permission.SeniorAdmin, true, new CommandArgument[] { new CommandArgument() { @@ -273,7 +255,7 @@ namespace SharedLibraryCore.Commands public class CWhoAmI : Command { public CWhoAmI() : - base("whoami", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WHO_DESC"], "who", EFClient.Permission.User, false) + base("whoami", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_WHO_DESC"], "who", EFClient.Permission.User, false) { } public override Task ExecuteAsync(GameEvent E) @@ -288,7 +270,7 @@ namespace SharedLibraryCore.Commands public class CList : Command { public CList() : - base("list", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_LIST_DESC"], "l", EFClient.Permission.Moderator, false) + base("list", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_LIST_DESC"], "l", EFClient.Permission.Moderator, false) { } public override Task ExecuteAsync(GameEvent E) @@ -307,11 +289,11 @@ namespace SharedLibraryCore.Commands // todo: make this better :) if (P.Masked) { - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor( EFClient.Permission.User, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces( EFClient.Permission.SeniorAdmin.ToString().Length - EFClient.Permission.User.ToString().Length)); + playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(EFClient.Permission.User, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces(EFClient.Permission.SeniorAdmin.ToString().Length - EFClient.Permission.User.ToString().Length)); } else { - playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(P.Level, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces( EFClient.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); + playerList.AppendFormat("[^3{0}^7]{3}[^3{1}^7] {2}", Utilities.ConvertLevelToColor(P.Level, P.ClientPermission.Name), P.ClientNumber, P.Name, Utilities.GetSpaces(EFClient.Permission.SeniorAdmin.ToString().Length - P.Level.ToString().Length)); } if (count == 2 || E.Owner.GetClientsAsList().Count == 1) @@ -339,7 +321,7 @@ namespace SharedLibraryCore.Commands public class CHelp : Command { public CHelp() : - base("help", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_HELP_DESC"], "h", EFClient.Permission.User, false, new CommandArgument[] + base("help", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_HELP_DESC"], "h", EFClient.Permission.User, false, new CommandArgument[] { new CommandArgument() { @@ -404,7 +386,7 @@ namespace SharedLibraryCore.Commands public class CFastRestart : Command { public CFastRestart() : - base("fastrestart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FASTRESTART_DESC"], "fr", EFClient.Permission.Moderator, false) + base("fastrestart", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FASTRESTART_DESC"], "fr", EFClient.Permission.Moderator, false) { } public override async Task ExecuteAsync(GameEvent E) @@ -420,7 +402,7 @@ namespace SharedLibraryCore.Commands public class CMapRotate : Command { public CMapRotate() : - base("maprotate", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAPROTATE_DESC"], "mr", EFClient.Permission.Administrator, false) + base("maprotate", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAPROTATE_DESC"], "mr", EFClient.Permission.Administrator, false) { } public override async Task ExecuteAsync(GameEvent E) @@ -437,7 +419,7 @@ namespace SharedLibraryCore.Commands public class CSetLevel : Command { public CSetLevel() : - base("setlevel", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_DESC"], "sl", EFClient.Permission.Moderator, true, new CommandArgument[] + base("setlevel", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_DESC"], "sl", EFClient.Permission.Moderator, true, new CommandArgument[] { new CommandArgument() { @@ -452,50 +434,54 @@ namespace SharedLibraryCore.Commands }) { } - public override async Task ExecuteAsync(GameEvent E) + public override Task ExecuteAsync(GameEvent E) { + + EFClient.Permission oldPerm = E.Target.Level; + EFClient.Permission newPerm = Utilities.MatchPermission(E.Data); + if (E.Target == E.Origin) { E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_SELF"]); - return; + return Task.CompletedTask; } - EFClient.Permission oldPerm = E.Target.Level; - EFClient.Permission newPerm = Utilities.MatchPermission(E.Data); - if (newPerm == EFClient.Permission.Owner && + else if (newPerm == EFClient.Permission.Owner && !E.Owner.Manager.GetApplicationSettings().Configuration().EnableMultipleOwners) { + // only one owner is allowed E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_OWNER"]); - return; + return Task.CompletedTask; } - if (E.Origin.Level < EFClient.Permission.Owner && + else if (E.Origin.Level < EFClient.Permission.Owner && !E.Owner.Manager.GetApplicationSettings().Configuration().EnableSteppedHierarchy) { + // only the owner is allowed to set levels E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_STEPPEDDISABLED"]} ^5{E.Target.Name}"); - return; + return Task.CompletedTask; } - if (newPerm >= E.Origin.Level) + else if (E.Origin.Level <= newPerm && + E.Origin.Level < EFClient.Permission.Owner) { - if (E.Origin.Level < EFClient.Permission.Owner) - { - E.Origin.Tell(string.Format(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_LEVELTOOHIGH"], E.Target.Name, (E.Origin.Level - 1).ToString())); - return; - } + // can't promote a client to higher than your current perms + E.Origin.Tell(string.Format(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_LEVELTOOHIGH"], E.Target.Name, (E.Origin.Level - 1).ToString())); + return Task.CompletedTask; } - else if (newPerm > EFClient.Permission.Banned) + else if (newPerm > EFClient.Permission.Banned) { var ActiveClient = E.Owner.Manager.GetActiveClients() .FirstOrDefault(p => p.NetworkId == E.Target.NetworkId); if (ActiveClient != null) { - ActiveClient.Level = newPerm; - await E.Owner.Manager.GetClientService().Update(ActiveClient); + ActiveClient.SetLevel(newPerm, E.Origin); + // inform the client that they were promoted + // we don't really want to tell them if they're demoted haha if (newPerm > oldPerm) { ActiveClient.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_SUCCESS_TARGET"]} {newPerm}"); @@ -504,26 +490,11 @@ namespace SharedLibraryCore.Commands else { - E.Target.Level = newPerm; - await E.Owner.Manager.GetClientService().Update(E.Target); + E.Target.SetLevel(newPerm, E.Origin); } - var e = new GameEvent() - { - Origin = E.Origin, - Target = E.Target, - Owner = E.Owner, - Type = GameEvent.EventType.ChangePermission, - Extra = new Change() - { - PreviousValue = oldPerm.ToString(), - NewValue = newPerm.ToString() - } - }; - - E.Owner.Manager.GetEventHandler().AddEvent(e); - - var _ = newPerm < oldPerm ? + // inform the origin that the client has been updated + _ = newPerm < oldPerm ? E.Origin.Tell($"{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_DEMOTE_SUCCESS"]} {E.Target.Name}") : E.Origin.Tell($"{E.Target.Name} {Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_SUCCESS"]}"); } @@ -532,13 +503,15 @@ namespace SharedLibraryCore.Commands { E.Origin.Tell(Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETLEVEL_FAIL"]); } + + return Task.CompletedTask; } } public class CUsage : Command { public CUsage() : - base("usage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_USAGE_DESC"], "us", EFClient.Permission.Moderator, false) + base("usage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_USAGE_DESC"], "us", EFClient.Permission.Moderator, false) { } public override Task ExecuteAsync(GameEvent E) @@ -551,7 +524,7 @@ namespace SharedLibraryCore.Commands public class CUptime : Command { public CUptime() : - base("uptime", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UPTIME_DESC"], "up", EFClient.Permission.Moderator, false) + base("uptime", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UPTIME_DESC"], "up", EFClient.Permission.Moderator, false) { } public override Task ExecuteAsync(GameEvent E) @@ -566,13 +539,13 @@ namespace SharedLibraryCore.Commands public class CListAdmins : Command { public CListAdmins() : - base("admins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ADMINS_DESC"], "a", EFClient.Permission.User, false) + base("admins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ADMINS_DESC"], "a", EFClient.Permission.User, false) { } public static string OnlineAdmins(Server S) { var onlineAdmins = S.GetClientsAsList() - .Where(p => p.Level > EFClient.Permission.Flagged) + .Where(p => p.Level > EFClient.Permission.Flagged) .Where(p => !p.Masked) .Select(p => $"[^3{Utilities.ConvertLevelToColor(p.Level, p.ClientPermission.Name)}^7] {p.Name}"); @@ -595,7 +568,7 @@ namespace SharedLibraryCore.Commands public class CLoadMap : Command { public CLoadMap() : - base("map", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAP_DESC"], "m", EFClient.Permission.Administrator, false, new CommandArgument[] + base("map", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MAP_DESC"], "m", EFClient.Permission.Administrator, false, new CommandArgument[] { new CommandArgument() { @@ -628,7 +601,7 @@ namespace SharedLibraryCore.Commands public class CFindPlayer : Command { public CFindPlayer() : - base("find", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FIND_DESC"], "f", EFClient.Permission.Administrator, false, new CommandArgument[] + base("find", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FIND_DESC"], "f", EFClient.Permission.Administrator, false, new CommandArgument[] { new CommandArgument() { @@ -672,7 +645,7 @@ namespace SharedLibraryCore.Commands public class CListRules : Command { public CListRules() : - base("rules", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RULES_DESC"], "r", EFClient.Permission.User, false) + base("rules", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RULES_DESC"], "r", EFClient.Permission.User, false) { } public override Task ExecuteAsync(GameEvent E) @@ -707,7 +680,7 @@ namespace SharedLibraryCore.Commands public class CPrivateMessage : Command { public CPrivateMessage() : - base("privatemessage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PM_DESC"], "pm", EFClient.Permission.User, true, new CommandArgument[] + base("privatemessage", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PM_DESC"], "pm", EFClient.Permission.User, true, new CommandArgument[] { new CommandArgument() { @@ -734,7 +707,7 @@ namespace SharedLibraryCore.Commands public class CFlag : Command { public CFlag() : - base("flag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_DESC"], "fp", EFClient.Permission.Moderator, true, new CommandArgument[] + base("flag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_FLAG_DESC"], "fp", EFClient.Permission.Moderator, true, new CommandArgument[] { new CommandArgument() { @@ -776,7 +749,7 @@ namespace SharedLibraryCore.Commands public class CUnflag : Command { public CUnflag() : - base("unflag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_DESC"], "uf", EFClient.Permission.Moderator, true, new CommandArgument[] + base("unflag", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_UNFLAG_DESC"], "uf", EFClient.Permission.Moderator, true, new CommandArgument[] { new CommandArgument() { @@ -814,7 +787,7 @@ namespace SharedLibraryCore.Commands public class CReport : Command { public CReport() : - base("report", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_DESC"], "rep", EFClient.Permission.User, true, new CommandArgument[] + base("report", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORT_DESC"], "rep", EFClient.Permission.User, true, new CommandArgument[] { new CommandArgument() { @@ -885,7 +858,7 @@ namespace SharedLibraryCore.Commands public class CListReports : Command { public CListReports() : - base("reports", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORTS_DESC"], "reps", EFClient.Permission.Moderator, false, new CommandArgument[] + base("reports", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_REPORTS_DESC"], "reps", EFClient.Permission.Moderator, false, new CommandArgument[] { new CommandArgument() { @@ -922,7 +895,7 @@ namespace SharedLibraryCore.Commands public class CMask : Command { public CMask() : - base("mask", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MASK_DESC"], "hide", EFClient.Permission.Moderator, false) + base("mask", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_MASK_DESC"], "hide", EFClient.Permission.Moderator, false) { } public override async Task ExecuteAsync(GameEvent E) @@ -945,7 +918,7 @@ namespace SharedLibraryCore.Commands public class CListBanInfo : Command { public CListBanInfo() : - base("baninfo", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BANINFO_DESC"], "bi", EFClient.Permission.Moderator, true, new CommandArgument[] + base("baninfo", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_BANINFO_DESC"], "bi", EFClient.Permission.Moderator, true, new CommandArgument[] { new CommandArgument() { @@ -978,7 +951,7 @@ namespace SharedLibraryCore.Commands public class CListAlias : Command { public CListAlias() : - base("alias", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ALIAS_DESC"], "known", EFClient.Permission.Moderator, true, new CommandArgument[] + base("alias", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_ALIAS_DESC"], "known", EFClient.Permission.Moderator, true, new CommandArgument[] { new CommandArgument() { @@ -1012,7 +985,7 @@ namespace SharedLibraryCore.Commands public class CExecuteRCON : Command { public CExecuteRCON() : - base("rcon", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RCON_DESC"], "rcon", EFClient.Permission.Owner, false, new CommandArgument[] + base("rcon", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_RCON_DESC"], "rcon", EFClient.Permission.Owner, false, new CommandArgument[] { new CommandArgument() { @@ -1040,7 +1013,7 @@ namespace SharedLibraryCore.Commands public class CPlugins : Command { public CPlugins() : - base("plugins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PLUGINS_DESC"], "p", EFClient.Permission.Administrator, false) + base("plugins", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PLUGINS_DESC"], "p", EFClient.Permission.Administrator, false) { } public override Task ExecuteAsync(GameEvent E) @@ -1057,7 +1030,7 @@ namespace SharedLibraryCore.Commands public class CIP : Command { public CIP() : - base("getexternalip", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_IP_DESC"], "ip", EFClient.Permission.User, false) + base("getexternalip", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_IP_DESC"], "ip", EFClient.Permission.User, false) { } public override Task ExecuteAsync(GameEvent E) @@ -1069,7 +1042,7 @@ namespace SharedLibraryCore.Commands public class CPruneAdmins : Command { - public CPruneAdmins() : base("prune", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PRUNE_DESC"], "pa", EFClient.Permission.Owner, false, new CommandArgument[] + public CPruneAdmins() : base("prune", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PRUNE_DESC"], "pa", EFClient.Permission.Owner, false, new CommandArgument[] { new CommandArgument() { @@ -1108,10 +1081,10 @@ namespace SharedLibraryCore.Commands { var lastActive = DateTime.UtcNow.AddDays(-inactiveDays); inactiveUsers = await context.Clients - .Where(c => c.Level > EFClient.Permission.Flagged && c.Level <= EFClient.Permission.Moderator) + .Where(c => c.Level > EFClient.Permission.Flagged && c.Level <= EFClient.Permission.Moderator) .Where(c => c.LastConnection < lastActive) .ToListAsync(); - inactiveUsers.ForEach(c => c.Level = EFClient.Permission.User); + inactiveUsers.ForEach(c => c.Level = EFClient.Permission.User); await context.SaveChangesAsync(); } E.Origin.Tell($"^5{inactiveUsers.Count} ^7{Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PRUNE_SUCCESS"]}"); @@ -1120,7 +1093,7 @@ namespace SharedLibraryCore.Commands public class CSetPassword : Command { - public CSetPassword() : base("setpassword", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETPASSWORD_DESC"], "sp", EFClient.Permission.Moderator, false, new CommandArgument[] + public CSetPassword() : base("setpassword", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_SETPASSWORD_DESC"], "sp", EFClient.Permission.Moderator, false, new CommandArgument[] { new CommandArgument() { @@ -1154,7 +1127,7 @@ namespace SharedLibraryCore.Commands public class CKillServer : Command { - public CKillServer() : base("killserver", "kill the game server", "kill", EFClient.Permission.Administrator, false) + public CKillServer() : base("killserver", "kill the game server", "kill", EFClient.Permission.Administrator, false) { } @@ -1236,7 +1209,7 @@ namespace SharedLibraryCore.Commands public class CPing : Command { - public CPing() : base("ping", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_DESC"], "pi", EFClient.Permission.User, false, new CommandArgument[] + public CPing() : base("ping", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_PING_DESC"], "pi", EFClient.Permission.User, false, new CommandArgument[] { new CommandArgument() { @@ -1277,7 +1250,7 @@ namespace SharedLibraryCore.Commands public class CSetGravatar : Command { - public CSetGravatar() : base("setgravatar", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GRAVATAR_DESC"], "sg", EFClient.Permission.User, false, new CommandArgument[] + public CSetGravatar() : base("setgravatar", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_GRAVATAR_DESC"], "sg", EFClient.Permission.User, false, new CommandArgument[] { new CommandArgument() { @@ -1341,7 +1314,7 @@ namespace SharedLibraryCore.Commands /// public class CNextMap : Command { - public CNextMap() : base("nextmap", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_NEXTMAP_DESC"], "nm", EFClient.Permission.User, false) { } + public CNextMap() : base("nextmap", Utilities.CurrentLocalization.LocalizationIndex["COMMANDS_NEXTMAP_DESC"], "nm", EFClient.Permission.User, false) { } public static async Task GetNextMap(Server s) { string mapRotation = (await s.GetDvarAsync("sv_mapRotation")).Value.ToLower(); diff --git a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs index 1daeb4bdb..fb2873721 100644 --- a/SharedLibraryCore/Configuration/ApplicationConfiguration.cs +++ b/SharedLibraryCore/Configuration/ApplicationConfiguration.cs @@ -33,6 +33,7 @@ namespace SharedLibraryCore.Configuration public List AutoMessages { get; set; } public List GlobalRules { get; set; } public List Maps { get; set; } + public List DisallowedClientNames { get; set; } public IBaseConfiguration Generate() { @@ -61,6 +62,13 @@ namespace SharedLibraryCore.Configuration } RConPollRate = 5000; + DisallowedClientNames = new List() + { + "Unknown Soldier", + "UnknownSoldier", + "CHEATER", + "VickNet" + }; return this; } diff --git a/SharedLibraryCore/Dtos/PenaltyInfo.cs b/SharedLibraryCore/Dtos/PenaltyInfo.cs index 458653865..9f51eedba 100644 --- a/SharedLibraryCore/Dtos/PenaltyInfo.cs +++ b/SharedLibraryCore/Dtos/PenaltyInfo.cs @@ -20,5 +20,7 @@ namespace SharedLibraryCore.Dtos public string TimePunished { get; set; } public string TimeRemaining { get; set; } public bool Expired { get; set; } + public string IPAddress { get; set; } + public ulong NetworkId { get; set; } } } diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs index f068336d1..a77eb427a 100644 --- a/SharedLibraryCore/Events/GameEvent.cs +++ b/SharedLibraryCore/Events/GameEvent.cs @@ -85,6 +85,14 @@ namespace SharedLibraryCore /// a client's information was updated /// Update, + /// + /// connection was lost to a server (the server has not responded after a number of attempts) + /// + ConnectionLost, + /// + /// connection was restored to a server (the server began responding again) + /// + ConnectionRestored, // events "generated" by clients /// @@ -167,6 +175,10 @@ namespace SharedLibraryCore /// team info printed out by game script /// JoinTeam = 304, + /// + /// used for community generated plugin events + /// + Other } static long NextEventId; diff --git a/SharedLibraryCore/Objects/EFClient.cs b/SharedLibraryCore/Objects/EFClient.cs index 966871c5e..c29bc29ca 100644 --- a/SharedLibraryCore/Objects/EFClient.cs +++ b/SharedLibraryCore/Objects/EFClient.cs @@ -3,6 +3,7 @@ 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 @@ -377,7 +378,7 @@ namespace SharedLibraryCore.Database.Models /// reason for the unban /// client performing the unban /// - public GameEvent Unban(String unbanReason, EFClient sender) + public GameEvent Unban(string unbanReason, EFClient sender) { var e = new GameEvent() { @@ -399,6 +400,32 @@ namespace SharedLibraryCore.Database.Models return e; } + /// + /// sets the level of the client + /// + /// new permission to set client to + /// user performing the set level + /// + public GameEvent SetLevel(Permission permission, EFClient sender) + { + var e = new GameEvent() + { + Type = GameEvent.EventType.ChangePermission, + Extra = permission, + Origin = sender, + Target = this, + Owner = sender.CurrentServer + }; + + if (this.Level > sender.Level) + { + e.FailReason = GameEvent.EventFailReason.Permission; + } + + sender.CurrentServer.Manager.GetEventHandler().AddEvent(e); + return e; + } + /// /// Handles any client related logic on connection /// @@ -416,9 +443,9 @@ namespace SharedLibraryCore.Database.Models return; } - if (Name == "Unknown Soldier" || - Name == "UnknownSoldier" || - Name == "CHEATER") + 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)); @@ -453,92 +480,121 @@ namespace SharedLibraryCore.Database.Models await CurrentServer.Manager.GetClientService().Update(this); } - public async Task OnJoin(int? ipAddress) + public async Task OnJoin(int? ipAddress) { CurrentServer.Logger.WriteDebug($"Start join for {this}::{ipAddress}::{Level.ToString()}"); - - IPAddress = ipAddress; - var loc = Utilities.CurrentLocalization.LocalizationIndex; - var autoKickClient = Utilities.IW4MAdminClient(CurrentServer); if (ipAddress != null) { - // todo: remove this in a few weeks because it's just temporary for server forwarding - if (IPAddressString == "66.150.121.184" || IPAddressString == "62.210.178.177") - { - Kick($"Your favorite servers are outdated. Please remove and re-add this server. ({CurrentServer.Hostname})", autoKickClient); - return false; - } + IPAddress = ipAddress; await CurrentServer.Manager.GetClientService().UpdateAlias(this); } + // we want to run any non GUID based logic here OnConnect(); - await CurrentServer.Manager.GetClientService().Update(this); - CurrentServer.Logger.WriteDebug($"OnConnect finished for {this}"); + if (await CanConnect(ipAddress) && IPAddress != null) + { + var e = new GameEvent() + { + Type = GameEvent.EventType.Join, + Origin = this, + Target = this, + Owner = CurrentServer + }; - #region CLIENT_BAN + CurrentServer.Manager.GetEventHandler().AddEvent(e); + + await CurrentServer.Manager.GetClientService().Update(this); + } + + else + { + CurrentServer.Logger.WriteDebug($"Client {this} is not allowed to join the server"); + } + + CurrentServer.Logger.WriteDebug($"OnJoin finished for {this}"); + } + + private async Task 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) { CurrentServer.Logger.WriteDebug($"Kicking {this} because they are banned"); - var ban = ReceivedPenalties.FirstOrDefault(_penalty => _penalty.Expires == null && _penalty.Active); + var profileBan = ReceivedPenalties.FirstOrDefault(_penalty => _penalty.Expires == null && _penalty.Active); - if (ban == null) + if (profileBan == null) { // this is from the old system before bans were applied to all accounts - ban = (await CurrentServer.Manager + profileBan = (await CurrentServer.Manager .GetPenaltyService() .GetActivePenaltiesAsync(AliasLinkId)) .FirstOrDefault(_penalty => _penalty.Type == Penalty.PenaltyType.Ban); - CurrentServer.Logger.WriteError($"Client {this} is banned, but no penalty exists for their 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 (ban.AutomatedOffense != null) + if (profileBan.AutomatedOffense != null) { autoKickClient.AdministeredPenalties?.Add(new EFPenalty() { - AutomatedOffense = ban.AutomatedOffense + AutomatedOffense = profileBan.AutomatedOffense }); } // this is a reban of the new GUID and IP - Ban($"{ban.Offense}", autoKickClient, false); + Ban($"{profileBan.Offense}", autoKickClient, false); return false; } - Kick($"{loc["SERVER_BAN_PREV"]} {ban?.Offense}", autoKickClient); - return false; - } - - var tempBan = ReceivedPenalties.FirstOrDefault(_penalty => _penalty.Type == Penalty.PenaltyType.TempBan && _penalty.Expires > DateTime.UtcNow && _penalty.Active); - // they have an active tempban tied to their GUID - if (tempBan != null) - { - CurrentServer.Logger.WriteDebug($"Kicking {this} because they are temporarily banned"); - Kick($"{loc["SERVER_TB_REMAIN"]} ({(tempBan.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient); + Kick($"{loc["SERVER_BAN_PREV"]} {profileBan?.Offense}", autoKickClient); return false; } #endregion + #region CLIENT_GUID_TEMPBAN + else + { + var profileTempBan = ReceivedPenalties.FirstOrDefault(_penalty => _penalty.Type == Penalty.PenaltyType.TempBan && _penalty.Active); + + // 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 + + #region CLIENT_LINKED_BAN // 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); - var currentBan = activePenalties.FirstOrDefault(p => p.Type == Penalty.PenaltyType.Ban); + var tempBan = activePenalties.FirstOrDefault(_penalty => _penalty.Type == Penalty.PenaltyType.TempBan); - var currentAutoFlag = activePenalties.Where(p => p.Type == Penalty.PenaltyType.Flag && p.PunisherId == 1) - .Where(p => p.Active) - .OrderByDescending(p => p.When) - .FirstOrDefault(); - - // remove their auto flag status after a week - if (Level == Permission.Flagged && - currentAutoFlag != null && - (DateTime.UtcNow - currentAutoFlag.When).TotalDays > 7) + // they have an active tempban tied to their AliasLink + if (tempBan != null) { - Level = Permission.User; + CurrentServer.Logger.WriteDebug($"Kicking {this} because their AliasLink is temporarily banned"); + Kick($"{loc["SERVER_TB_REMAIN"]} ({(tempBan.Expires.Value - DateTime.UtcNow).TimeSpanText()} {loc["WEBFRONT_PENALTY_TEMPLATE_REMAINING"]})", autoKickClient); + return false; } + var currentBan = activePenalties.FirstOrDefault(p => p.Type == Penalty.PenaltyType.Ban); + + // they have a perm ban tied to their AliasLink if (currentBan != null) { CurrentServer.Logger.WriteInfo($"Banned client {this} trying to evade..."); @@ -567,18 +623,23 @@ namespace SharedLibraryCore.Database.Models return false; } + #endregion else { - var e = new GameEvent() - { - Type = GameEvent.EventType.Join, - Origin = this, - Target = this, - Owner = CurrentServer - }; + var currentAutoFlag = activePenalties + .Where(p => p.Type == Penalty.PenaltyType.Flag && p.PunisherId == 1) + .OrderByDescending(p => p.When) + .FirstOrDefault(); + + // remove their auto flag status after a week + if (Level == Permission.Flagged && + currentAutoFlag != null && + (DateTime.UtcNow - currentAutoFlag.When).TotalDays > 7) + { + Level = Permission.User; + } - CurrentServer.Manager.GetEventHandler().AddEvent(e); return true; } } diff --git a/SharedLibraryCore/Services/ChangeHistoryService.cs b/SharedLibraryCore/Services/ChangeHistoryService.cs index ac1089886..808c0cf18 100644 --- a/SharedLibraryCore/Services/ChangeHistoryService.cs +++ b/SharedLibraryCore/Services/ChangeHistoryService.cs @@ -45,7 +45,6 @@ namespace SharedLibraryCore.Services OriginEntityId = e.Origin.ClientId, TargetEntityId = e.Target?.ClientId ?? 0, Comment = "Executed command", - PreviousValue = "", CurrentValue = e.Message, TypeOfChange = EFChangeHistory.ChangeType.Command }; @@ -56,8 +55,7 @@ namespace SharedLibraryCore.Services OriginEntityId = e.Origin.ClientId, TargetEntityId = e.Target.ClientId, TypeOfChange = EFChangeHistory.ChangeType.Permission, - PreviousValue = ((Change)e.Extra).PreviousValue, - CurrentValue = ((Change)e.Extra).NewValue + CurrentValue = ((EFClient.Permission)e.Extra).ToString() }; break; default: diff --git a/SharedLibraryCore/Services/ClientService.cs b/SharedLibraryCore/Services/ClientService.cs index 981c27e8a..6ff6699f3 100644 --- a/SharedLibraryCore/Services/ClientService.cs +++ b/SharedLibraryCore/Services/ClientService.cs @@ -21,7 +21,6 @@ namespace SharedLibraryCore.Services { Level = Permission.User, FirstConnection = DateTime.UtcNow, - Connections = 1, LastConnection = DateTime.UtcNow, Masked = false, NetworkId = entity.NetworkId, @@ -356,11 +355,25 @@ namespace SharedLibraryCore.Services } } + /// + /// retrieves the number of owners + /// (client level is owner) + /// + /// + public async Task GetOwnerCount() + { + using (var ctx = new DatabaseContext(true)) + { + return await ctx.Clients.AsNoTracking() + .CountAsync(_client => _client.Level == Permission.Owner); + } + } + public async Task> GetPrivilegedClients() { using (var context = new DatabaseContext(disableTracking: true)) { - var iqClients = from client in context.Clients + var iqClients = from client in context.Clients.AsNoTracking() where client.Level >= Permission.Trusted where client.Active select new EFClient() diff --git a/WebfrontCore/Controllers/BaseController.cs b/WebfrontCore/Controllers/BaseController.cs index 02225beb1..80c0902cf 100644 --- a/WebfrontCore/Controllers/BaseController.cs +++ b/WebfrontCore/Controllers/BaseController.cs @@ -77,7 +77,7 @@ namespace WebfrontCore.Controllers } - catch (System.Collections.Generic.KeyNotFoundException) + catch (KeyNotFoundException) { // force the "banned" client to be signed out HttpContext.SignOutAsync().Wait(5000); diff --git a/WebfrontCore/Controllers/ClientController.cs b/WebfrontCore/Controllers/ClientController.cs index d012735fe..9fe100188 100644 --- a/WebfrontCore/Controllers/ClientController.cs +++ b/WebfrontCore/Controllers/ClientController.cs @@ -135,8 +135,8 @@ namespace WebfrontCore.Controllers public async Task PrivilegedAsync() { var admins = (await Manager.GetClientService().GetPrivilegedClients()) - .GroupBy(a => a.AliasLinkId).Where(_clients => _clients.FirstOrDefault(_client => _client.LastConnection == _clients.Max(c => c.LastConnection)) != null) - .Select(_client => _client.First()) + .GroupBy(a => a.AliasLinkId) + .Select(_client => _client.OrderByDescending(_c => _c.LastConnection).First()) .OrderByDescending(_client => _client.Level); var adminsDict = new Dictionary>(); diff --git a/WebfrontCore/Controllers/PenaltyController.cs b/WebfrontCore/Controllers/PenaltyController.cs index 2a7c8bb93..b5e1fe59e 100644 --- a/WebfrontCore/Controllers/PenaltyController.cs +++ b/WebfrontCore/Controllers/PenaltyController.cs @@ -33,30 +33,42 @@ namespace WebfrontCore.Controllers })); } + /// + /// retrieves all permanent bans ordered by ban date + /// if request is authorized, it will include the client's ip address. + /// + /// public async Task PublicAsync() { - IList penalties; + IList penalties; using (var ctx = new DatabaseContext(disableTracking: true)) { - penalties = await ctx.Penalties + // todo: this seems like it's pulling unnecessary info from LINQ to entities. + var iqPenalties = ctx.Penalties .Where(p => p.Type == SharedLibraryCore.Objects.Penalty.PenaltyType.Ban && p.Active) - .ToListAsync(); + .OrderByDescending(_penalty => _penalty.When) + .Select(p => new PenaltyInfo() + { + Id = p.PenaltyId, + OffenderId = p.OffenderId, + Offense = p.Offense, + PunisherId = p.PunisherId, + Type = p.Type.ToString(), + TimePunished = p.When.ToString(), + TimeRemaining = "", + AutomatedOffense = Authorized ? p.AutomatedOffense : "", + NetworkId = (ulong)p.Offender.NetworkId, + IPAddress = Authorized ? p.Offender.IPAddressString : "" + }); +#if DEBUG == true + var querySql = iqPenalties.ToSql(); +#endif + + penalties = await iqPenalties.ToListAsync(); } - var penaltiesDto = penalties.Select(p => new PenaltyInfo() - { - Id = p.PenaltyId, - OffenderId = p.OffenderId, - Offense = p.Offense, - PunisherId = p.PunisherId, - Type = p.Type.ToString(), - TimePunished = p.When.ToString(), - TimeRemaining = "", - AutomatedOffense = p.AutomatedOffense - }).ToList(); - - return Json(penaltiesDto); + return Json(penalties); } } } diff --git a/WebfrontCore/Views/Client/Profile/Index.cshtml b/WebfrontCore/Views/Client/Profile/Index.cshtml index 7710770fb..028aae786 100644 --- a/WebfrontCore/Views/Client/Profile/Index.cshtml +++ b/WebfrontCore/Views/Client/Profile/Index.cshtml @@ -6,37 +6,23 @@ string gravatarUrl = Model.Meta.FirstOrDefault(m => m.Key == "GravatarEmail")?.Value; bool isTempBanned = Model.ActivePenaltyType == "TempBan"; } -
-
+
+
@if (string.IsNullOrEmpty(gravatarUrl)) { @shortCode }
-
-
@Model.Name
-
+
+
+
@Model.Name
@Model.Level @(isTempBanned ? $"({loc["WEBFRONT_PROFILE_TEMPBAN"]})" : "")
-
- @loc["WEBFRONT_PROFILE_PLAYER"] @Model.TimePlayed @loc["GLOBAL_TIME_HOURS"] -
-
- @loc["WEBFRONT_PROFILE_FSEEN"] @Model.FirstSeen @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"] -
-
- @loc["WEBFRONT_PROFILE_LSEEN"] @Model.LastSeen @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"] -
-
-
-
-
- @if (ViewBag.Authorized) - { -
-
+ @if (ViewBag.Authorized) + { +
@if (Model.LevelInt != -1) { @@ -81,10 +67,27 @@ }
-
-
+ + } +
+ @*
+ +
+ @loc["WEBFRONT_PROFILE_PLAYER"] @Model.TimePlayed @loc["GLOBAL_TIME_HOURS"]
- } +
+ @loc["WEBFRONT_PROFILE_FSEEN"] @Model.FirstSeen @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"] +
+
+ @loc["WEBFRONT_PROFILE_LSEEN"] @Model.LastSeen @loc["WEBFRONT_PENALTY_TEMPLATE_AGO"] +
+
+
+
+
+ +
+
*@
@@ -100,7 +103,7 @@ diff --git a/WebfrontCore/wwwroot/css/profile.css b/WebfrontCore/wwwroot/css/profile.css index 7fa514abb..0beab182e 100644 --- a/WebfrontCore/wwwroot/css/profile.css +++ b/WebfrontCore/wwwroot/css/profile.css @@ -146,13 +146,12 @@ } #profile_avatar { - height: 10.5rem; - width: 10.5rem; + } .profile-shortcode { - font-size: 10.5rem; - line-height: 10.5rem; + font-size: 5rem; + line-height: 5rem; color: white; }