From 4c4a86ed213e2f7206735e95b49280691ff9714e Mon Sep 17 00:00:00 2001 From: Valtos Date: Mon, 25 Sep 2023 09:35:45 +0200 Subject: [PATCH 01/14] pizdos --- SS14.Admin/LoginHandler.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SS14.Admin/LoginHandler.cs b/SS14.Admin/LoginHandler.cs index 2d12474..23844e1 100644 --- a/SS14.Admin/LoginHandler.cs +++ b/SS14.Admin/LoginHandler.cs @@ -47,6 +47,12 @@ public async Task HandleTokenValidated(TokenValidatedContext ctx) } var flags = AdminHelper.GetStringFlags(adminData); + + if(!flags.Contains("BAN")) { + ctx.Response.Redirect(_linkGenerator.GetUriByPage(ctx.HttpContext, "/LoginFailed")!); + ctx.HandleResponse(); + return; + } foreach (var flag in flags) { From 9c44deb1353c6342bfb9058e3ea232b269308cef Mon Sep 17 00:00:00 2001 From: EnefFlow Date: Mon, 25 Sep 2023 17:08:37 +0300 Subject: [PATCH 02/14] check for Ban flag on ban --- SS14.Admin/Helpers/BanHelper.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/SS14.Admin/Helpers/BanHelper.cs b/SS14.Admin/Helpers/BanHelper.cs index e5b28a6..995115a 100644 --- a/SS14.Admin/Helpers/BanHelper.cs +++ b/SS14.Admin/Helpers/BanHelper.cs @@ -3,6 +3,7 @@ using System.Net; using Content.Server.Database; using Microsoft.EntityFrameworkCore; +using SS14.Admin.Admins; namespace SS14.Admin.Helpers; @@ -174,6 +175,22 @@ public sealed class BanJoin where TBan: IBanCommon where T } ban.BanningAdmin = _httpContext.HttpContext!.User.Claims.GetUserId(); + + try + { + var adminData = _dbContext.Admin.First(a => a.UserId == ban.BanningAdmin); + var flags = AdminHelper.GetFlags(adminData); + if ((flags & AdminFlags.Ban) == 0) + { + return "Error: Admin doesn't have Ban flag."; + } + } + catch (Exception e) + { + _logger.LogError(e, "Unable to get admin flags"); + return "Error: Unknown error occured while getting admin data.";; + } + ban.Reason = reason; ban.BanTime = DateTime.UtcNow; return null; From 9fbcc6c001edf1be18b1df86d7687f7826f0fb60 Mon Sep 17 00:00:00 2001 From: HitPanda <104197232+EnefFlow@users.noreply.github.com> Date: Mon, 25 Sep 2023 17:35:14 +0300 Subject: [PATCH 03/14] Update Ban flag check in BanHelper.cs --- SS14.Admin/Helpers/BanHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SS14.Admin/Helpers/BanHelper.cs b/SS14.Admin/Helpers/BanHelper.cs index 995115a..d93fece 100644 --- a/SS14.Admin/Helpers/BanHelper.cs +++ b/SS14.Admin/Helpers/BanHelper.cs @@ -180,7 +180,7 @@ public sealed class BanJoin where TBan: IBanCommon where T { var adminData = _dbContext.Admin.First(a => a.UserId == ban.BanningAdmin); var flags = AdminHelper.GetFlags(adminData); - if ((flags & AdminFlags.Ban) == 0) + if ((flags & AdminFlags.Ban) != flags) { return "Error: Admin doesn't have Ban flag."; } From 4dd434a8710e3680e428eac8621232f005ee8003 Mon Sep 17 00:00:00 2001 From: HitPanda <104197232+EnefFlow@users.noreply.github.com> Date: Mon, 25 Sep 2023 17:54:36 +0300 Subject: [PATCH 04/14] Comment out BAN flag check in LoginHandler.cs --- SS14.Admin/LoginHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SS14.Admin/LoginHandler.cs b/SS14.Admin/LoginHandler.cs index 23844e1..b9e6dd1 100644 --- a/SS14.Admin/LoginHandler.cs +++ b/SS14.Admin/LoginHandler.cs @@ -46,13 +46,13 @@ public async Task HandleTokenValidated(TokenValidatedContext ctx) return; } - var flags = AdminHelper.GetStringFlags(adminData); + /*var flags = AdminHelper.GetStringFlags(adminData); if(!flags.Contains("BAN")) { ctx.Response.Redirect(_linkGenerator.GetUriByPage(ctx.HttpContext, "/LoginFailed")!); ctx.HandleResponse(); return; - } + }*/ foreach (var flag in flags) { From d5294b0a57d79246ad7f6f1f887c8bac2cc52ba1 Mon Sep 17 00:00:00 2001 From: HitPanda <104197232+EnefFlow@users.noreply.github.com> Date: Mon, 25 Sep 2023 17:59:45 +0300 Subject: [PATCH 05/14] Quick fix for last commit --- SS14.Admin/LoginHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SS14.Admin/LoginHandler.cs b/SS14.Admin/LoginHandler.cs index b9e6dd1..98306ba 100644 --- a/SS14.Admin/LoginHandler.cs +++ b/SS14.Admin/LoginHandler.cs @@ -46,9 +46,9 @@ public async Task HandleTokenValidated(TokenValidatedContext ctx) return; } - /*var flags = AdminHelper.GetStringFlags(adminData); + var flags = AdminHelper.GetStringFlags(adminData); - if(!flags.Contains("BAN")) { + /*if(!flags.Contains("BAN")) { ctx.Response.Redirect(_linkGenerator.GetUriByPage(ctx.HttpContext, "/LoginFailed")!); ctx.HandleResponse(); return; From a08d03d164f426b216610c238ae185d18c3bb963 Mon Sep 17 00:00:00 2001 From: HitPanda <104197232+EnefFlow@users.noreply.github.com> Date: Mon, 25 Sep 2023 18:15:57 +0300 Subject: [PATCH 06/14] Update LoginFailed.cshtml --- SS14.Admin/Pages/LoginFailed.cshtml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SS14.Admin/Pages/LoginFailed.cshtml b/SS14.Admin/Pages/LoginFailed.cshtml index 1925bd4..2de9730 100644 --- a/SS14.Admin/Pages/LoginFailed.cshtml +++ b/SS14.Admin/Pages/LoginFailed.cshtml @@ -5,6 +5,6 @@ ViewData["Title"] = "Error"; } -

Failed to log in

-

You are not a server administrator

+

Ошибка входа

+

Вы не являетесь администратором сервера.

From 9390d5dc3ed436d7902561b1bb13455eaed413e7 Mon Sep 17 00:00:00 2001 From: Valtos Date: Mon, 18 Dec 2023 18:19:21 +0300 Subject: [PATCH 07/14] FUCK --- .gitmodules | 3 --- SS14 | 1 - 2 files changed, 4 deletions(-) delete mode 160000 SS14 diff --git a/.gitmodules b/.gitmodules index 20cf79a..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "SS14"] - path = SS14 - url = https://github.com/space-wizards/space-station-14.git diff --git a/SS14 b/SS14 deleted file mode 160000 index 9025cca..0000000 --- a/SS14 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9025ccaa9d06cfaaefe95fb650dd109cb8a9f37f From 7083ad45ad97c95824bd3ed98bb7c426ebb4ee96 Mon Sep 17 00:00:00 2001 From: Valtos Date: Mon, 18 Dec 2023 18:20:54 +0300 Subject: [PATCH 08/14] Add submodul xyu --- .gitmodules | 3 +++ SS14 | 1 + 2 files changed, 4 insertions(+) create mode 160000 SS14 diff --git a/.gitmodules b/.gitmodules index e69de29..b4cf96b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "SS14"] + path = SS14 + url = https://github.com/frosty-dev/ss14-new diff --git a/SS14 b/SS14 new file mode 160000 index 0000000..2660813 --- /dev/null +++ b/SS14 @@ -0,0 +1 @@ +Subproject commit 2660813d11a4ca4b501840990e506430f8a2d7b0 From 177045e15c657079f8cdea0abe87a09c752d4bc6 Mon Sep 17 00:00:00 2001 From: Valtos Date: Mon, 18 Dec 2023 18:25:37 +0300 Subject: [PATCH 09/14] unfuck admin --- SS14.Admin/Helpers/BanHelper.cs | 8 ++++---- SS14.Admin/Helpers/SearchHelper.cs | 2 +- SS14.Admin/Pages/Bans/Hits.cshtml | 2 +- SS14.Admin/Pages/Bans/Index.cshtml.cs | 4 ++-- SS14.Admin/Pages/RoleBans/Index.cshtml.cs | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/SS14.Admin/Helpers/BanHelper.cs b/SS14.Admin/Helpers/BanHelper.cs index d93fece..9bdd138 100644 --- a/SS14.Admin/Helpers/BanHelper.cs +++ b/SS14.Admin/Helpers/BanHelper.cs @@ -46,7 +46,7 @@ private IQueryable> CreateBanJoin(DbSet b.Unban) .LeftJoin(_dbContext.Player, - ban => ban.PlayerUserId, player => player.UserId, + ban => ban.UserId, player => player.UserId, (ban, player) => new { ban, player }) .LeftJoin(_dbContext.Player, ban => ban.ban.BanningAdmin, admin => admin.UserId, @@ -126,13 +126,13 @@ public sealed class BanJoin where TBan: IBanCommon where T nameOrUid = nameOrUid.Trim(); if (Guid.TryParse(nameOrUid, out var guid)) { - ban.PlayerUserId = guid; + ban.UserId = guid; } else { try { - ban.PlayerUserId = await FindPlayerGuidByNameAsync(nameOrUid); + ban.UserId = await FindPlayerGuidByNameAsync(nameOrUid); } catch (Exception e) { @@ -140,7 +140,7 @@ public sealed class BanJoin where TBan: IBanCommon where T return "Error: Unknown error occured fetching user ID from auth server."; } - if (ban.PlayerUserId == null) + if (ban.UserId == null) { return $"Error: Unable to find user with name {nameOrUid}"; } diff --git a/SS14.Admin/Helpers/SearchHelper.cs b/SS14.Admin/Helpers/SearchHelper.cs index bb5446f..e92ae01 100644 --- a/SS14.Admin/Helpers/SearchHelper.cs +++ b/SS14.Admin/Helpers/SearchHelper.cs @@ -45,7 +45,7 @@ public static IQueryable SearchConnectionLog(IQueryable b.Ban.PlayerUserId == guid); + CombineSearch(ref expr, b => b.Ban.UserId == guid); if (IPHelper.TryParseCidr(search, out var cidr)) CombineSearch(ref expr, b => EF.Functions.ContainsOrEqual(cidr, b.Ban.Address!.Value)); diff --git a/SS14.Admin/Pages/Bans/Hits.cshtml b/SS14.Admin/Pages/Bans/Hits.cshtml index 14eff28..52bec62 100644 --- a/SS14.Admin/Pages/Bans/Hits.cshtml +++ b/SS14.Admin/Pages/Bans/Hits.cshtml @@ -14,7 +14,7 @@
Name:
@Model.Ban.Player?.LastSeenUserName
User ID:
-
@Model.Ban.Ban.PlayerUserId
+
@Model.Ban.Ban.UserId
@if (User.IsInRole("ADMIN")) {
IP:
diff --git a/SS14.Admin/Pages/Bans/Index.cshtml.cs b/SS14.Admin/Pages/Bans/Index.cshtml.cs index af477d9..8204d6f 100644 --- a/SS14.Admin/Pages/Bans/Index.cshtml.cs +++ b/SS14.Admin/Pages/Bans/Index.cshtml.cs @@ -101,7 +101,7 @@ public static async Task LoadSortBanTableData( var sortState = Helpers.SortState.Build(bans); sortState.AddColumn("name", p => p.Player!.LastSeenUserName); sortState.AddColumn("ip", p => p.Ban.Address); - sortState.AddColumn("uid", p => p.Ban.PlayerUserId); + sortState.AddColumn("uid", p => p.Ban.UserId); sortState.AddColumn("time", p => p.Ban.BanTime, SortOrder.Descending); // sortState.AddColumn("expire_time", p => p.ban.Unban == null ? p.ban.ExpirationTime : p.ban.Unban!.UnbanTime); sortState.AddColumn("admin", p => p.Admin!.LastSeenUserName); @@ -124,7 +124,7 @@ await pagination.LoadLinqAsync(bans, e => e.Select(b => return new Ban( b.Ban.Id, b.Player, - b.Ban.PlayerUserId?.ToString(), + b.Ban.UserId?.ToString(), b.Ban.Address?.FormatCidr(), b.Ban.HWId is { } h ? Convert.ToBase64String(h) : null, b.Ban.Reason, diff --git a/SS14.Admin/Pages/RoleBans/Index.cshtml.cs b/SS14.Admin/Pages/RoleBans/Index.cshtml.cs index a3b4579..b268ea3 100644 --- a/SS14.Admin/Pages/RoleBans/Index.cshtml.cs +++ b/SS14.Admin/Pages/RoleBans/Index.cshtml.cs @@ -100,7 +100,7 @@ public static async Task LoadSortBanTableData( var sortState = Helpers.SortState.Build(bans); sortState.AddColumn("name", p => p.Player!.LastSeenUserName); sortState.AddColumn("ip", p => p.Ban.Address); - sortState.AddColumn("uid", p => p.Ban.PlayerUserId); + sortState.AddColumn("uid", p => p.Ban.UserId); sortState.AddColumn("time", p => p.Ban.BanTime, SortOrder.Descending); // sortState.AddColumn("expire_time", p => p.ban.Unban == null ? p.ban.ExpirationTime : p.ban.Unban!.UnbanTime); sortState.AddColumn("admin", p => p.Admin!.LastSeenUserName); @@ -123,7 +123,7 @@ await pagination.LoadLinqAsync(bans, e => e.Select(b => return new RoleBan( b.Ban.Id, b.Player, - b.Ban.PlayerUserId?.ToString(), + b.Ban.UserId?.ToString(), b.Ban.Address?.FormatCidr(), b.Ban.HWId is { } h ? Convert.ToBase64String(h) : null, b.Ban.Reason, From 108ce45dae9b89f228b5ae6d5fa3bdf4ac785e3b Mon Sep 17 00:00:00 2001 From: Valtosin Date: Tue, 13 Feb 2024 05:42:14 +0000 Subject: [PATCH 10/14] yes --- SS14 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SS14 b/SS14 index 2660813..2d82ec5 160000 --- a/SS14 +++ b/SS14 @@ -1 +1 @@ -Subproject commit 2660813d11a4ca4b501840990e506430f8a2d7b0 +Subproject commit 2d82ec58d2c346b135001835c5255bd385fb9b7a From a93591d6149047da7459574d91e0a0b0665cadc6 Mon Sep 17 00:00:00 2001 From: Valtosin Date: Tue, 13 Feb 2024 05:52:25 +0000 Subject: [PATCH 11/14] FUCK --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 20cf79a..21001dd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "SS14"] path = SS14 - url = https://github.com/space-wizards/space-station-14.git + url = https://github.com/frosty-dev/ss14-core From ee0b2d9787f56b0e60a0e8da42682ee5fa86a122 Mon Sep 17 00:00:00 2001 From: Valtosin Date: Tue, 13 Feb 2024 05:58:21 +0000 Subject: [PATCH 12/14] FUCKFUCK --- SS14 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SS14 b/SS14 index 2d82ec5..5b4164e 160000 --- a/SS14 +++ b/SS14 @@ -1 +1 @@ -Subproject commit 2d82ec58d2c346b135001835c5255bd385fb9b7a +Subproject commit 5b4164e1181d4f32e3459388e94484ffc61fa42d From e954537a1f893550bbd7a1daada56ad4e4530bcf Mon Sep 17 00:00:00 2001 From: Valtosin Date: Tue, 13 Feb 2024 06:03:15 +0000 Subject: [PATCH 13/14] FUCKFUFFSEUJID --- SS14.Admin/Helpers/SearchHelper.cs | 2 +- SS14.Admin/Pages/Bans/Index.cshtml.cs | 6 +++--- SS14.Admin/Pages/RoleBans/Index.cshtml.cs | 6 +++--- SS14.Admin/Pages/Tables/BansTable.cshtml | 4 ++-- SS14.Admin/Pages/Tables/RoleBansTable.cshtml | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/SS14.Admin/Helpers/SearchHelper.cs b/SS14.Admin/Helpers/SearchHelper.cs index 11284c9..e64d2db 100644 --- a/SS14.Admin/Helpers/SearchHelper.cs +++ b/SS14.Admin/Helpers/SearchHelper.cs @@ -46,7 +46,7 @@ public static IQueryable SearchConnectionLog(IQueryable b.Ban.UserId == guid); + CombineSearch(ref expr, b => b.Ban.PlayerUserId == guid); if (IPHelper.TryParseCidr(search, out var cidr)) CombineSearch(ref expr, b => EF.Functions.ContainsOrEqual(cidr, b.Ban.Address!.Value)); diff --git a/SS14.Admin/Pages/Bans/Index.cshtml.cs b/SS14.Admin/Pages/Bans/Index.cshtml.cs index 8204d6f..1f45b4f 100644 --- a/SS14.Admin/Pages/Bans/Index.cshtml.cs +++ b/SS14.Admin/Pages/Bans/Index.cshtml.cs @@ -101,7 +101,7 @@ public static async Task LoadSortBanTableData( var sortState = Helpers.SortState.Build(bans); sortState.AddColumn("name", p => p.Player!.LastSeenUserName); sortState.AddColumn("ip", p => p.Ban.Address); - sortState.AddColumn("uid", p => p.Ban.UserId); + sortState.AddColumn("uid", p => p.Ban.PlayerUserId); sortState.AddColumn("time", p => p.Ban.BanTime, SortOrder.Descending); // sortState.AddColumn("expire_time", p => p.ban.Unban == null ? p.ban.ExpirationTime : p.ban.Unban!.UnbanTime); sortState.AddColumn("admin", p => p.Admin!.LastSeenUserName); @@ -124,7 +124,7 @@ await pagination.LoadLinqAsync(bans, e => e.Select(b => return new Ban( b.Ban.Id, b.Player, - b.Ban.UserId?.ToString(), + b.Ban.PlayerUserId?.ToString(), b.Ban.Address?.FormatCidr(), b.Ban.HWId is { } h ? Convert.ToBase64String(h) : null, b.Ban.Reason, @@ -142,7 +142,7 @@ await pagination.LoadLinqAsync(bans, e => e.Select(b => public sealed record Ban( int Id, Player? Player, - string? UserId, + string? PlayerUserId, string? Address, string? Hwid, string Reason, diff --git a/SS14.Admin/Pages/RoleBans/Index.cshtml.cs b/SS14.Admin/Pages/RoleBans/Index.cshtml.cs index b268ea3..bc83692 100644 --- a/SS14.Admin/Pages/RoleBans/Index.cshtml.cs +++ b/SS14.Admin/Pages/RoleBans/Index.cshtml.cs @@ -100,7 +100,7 @@ public static async Task LoadSortBanTableData( var sortState = Helpers.SortState.Build(bans); sortState.AddColumn("name", p => p.Player!.LastSeenUserName); sortState.AddColumn("ip", p => p.Ban.Address); - sortState.AddColumn("uid", p => p.Ban.UserId); + sortState.AddColumn("uid", p => p.Ban.PlayerUserId); sortState.AddColumn("time", p => p.Ban.BanTime, SortOrder.Descending); // sortState.AddColumn("expire_time", p => p.ban.Unban == null ? p.ban.ExpirationTime : p.ban.Unban!.UnbanTime); sortState.AddColumn("admin", p => p.Admin!.LastSeenUserName); @@ -123,7 +123,7 @@ await pagination.LoadLinqAsync(bans, e => e.Select(b => return new RoleBan( b.Ban.Id, b.Player, - b.Ban.UserId?.ToString(), + b.Ban.PlayerUserId?.ToString(), b.Ban.Address?.FormatCidr(), b.Ban.HWId is { } h ? Convert.ToBase64String(h) : null, b.Ban.Reason, @@ -141,7 +141,7 @@ await pagination.LoadLinqAsync(bans, e => e.Select(b => public sealed record RoleBan( int Id, Player? Player, - string? UserId, + string? PlayerUserId, string? Address, string? Hwid, string Reason, diff --git a/SS14.Admin/Pages/Tables/BansTable.cshtml b/SS14.Admin/Pages/Tables/BansTable.cshtml index bbab314..3867193 100644 --- a/SS14.Admin/Pages/Tables/BansTable.cshtml +++ b/SS14.Admin/Pages/Tables/BansTable.cshtml @@ -66,10 +66,10 @@
} } - @if (ban.UserId != null) + @if (ban.PlayerUserId != null) { - GUID: @ban.UserId + GUID: @ban.PlayerUserId } diff --git a/SS14.Admin/Pages/Tables/RoleBansTable.cshtml b/SS14.Admin/Pages/Tables/RoleBansTable.cshtml index b89d6aa..55c3cd0 100644 --- a/SS14.Admin/Pages/Tables/RoleBansTable.cshtml +++ b/SS14.Admin/Pages/Tables/RoleBansTable.cshtml @@ -67,10 +67,10 @@
} } - @if (ban.UserId != null) + @if (ban.PlayerUserId != null) { - GUID: @ban.UserId + GUID: @ban.PlayerUserId } From ec05165418bfe13fa170b30378e6e18c5bd2f286 Mon Sep 17 00:00:00 2001 From: Valtos Date: Sat, 17 Feb 2024 12:18:16 +0300 Subject: [PATCH 14/14] =?UTF-8?q?=D0=B3=D0=BE=D0=B2=D0=BD=D0=B8=D1=89?= =?UTF-8?q?=D0=B5=20=D0=B1=D0=BB=D1=8F=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SS14.Admin/wwwroot/css/site.css | 5 +++++ SS14.Admin/wwwroot/favicon.ico | Bin 67646 -> 236 bytes 2 files changed, 5 insertions(+) diff --git a/SS14.Admin/wwwroot/css/site.css b/SS14.Admin/wwwroot/css/site.css index f7fd0ad..32e8086 100644 --- a/SS14.Admin/wwwroot/css/site.css +++ b/SS14.Admin/wwwroot/css/site.css @@ -19,6 +19,10 @@ for details on configuring this project to bundle and minify static web assets. --color-filter-type: #F78764; } +* { + border-radius: 0 !important; +} + a.navbar-brand { white-space: normal; text-align: center; @@ -91,6 +95,7 @@ html { body { /* Margin bottom by footer height */ margin-bottom: 60px; + font-family: Roboto, sans-serif; } .footer { position: absolute; diff --git a/SS14.Admin/wwwroot/favicon.ico b/SS14.Admin/wwwroot/favicon.ico index cb02feb3c5f6dbd094d1da81b921bc06c428d6a5..f011ce929b08da0408c5063f7a2cdb60b73f4717 100644 GIT binary patch literal 236 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