Skip to content

Commit

Permalink
Add the Capability to mass ban players based on .tsv files (#59)
Browse files Browse the repository at this point in the history
* Add the Capability to mass ban players based on .tsv files

* I SWEAR TO GOD IT DELKETES THE .NAME EVERY TIME ADASDASDASDSAD

* small changes

* fixes

* check for header and error if its not there

* package shit

* tsv record

---------

Co-authored-by: Geekyhobo <[email protected]>
  • Loading branch information
Geekyhobo and Geekyhobo authored Jul 27, 2024
1 parent e5030a4 commit 8b608c2
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .idea/.idea.SS14.Admin/.idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="CsvHelper" Version="30.0.1" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.6" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
Expand Down
79 changes: 79 additions & 0 deletions SS14.Admin/Pages/Bans/CreateMassBan.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
@page
@model SS14.Admin.Pages.Bans.CreateMassBanModel

@{
ViewData["Title"] = "Create New Mass Ban";
}

<partial name="Shared/StatusMessageAlert" />

<div class="container mt-4">
<h1 class="text-center">Create New Mass Ban</h1>

<div class="alert alert-info">
<strong>TSV Format Explanation:</strong>
<p>TSV is a CSV using tabs instead of commas. The fields are:</p>
<ul>
<li><strong>user_id</strong> (user guid)</li>
<li><strong>address</strong> (ip address/CIDR)</li>
<li><strong>hwid</strong> (base64 encoded hwid)</li>
<li><strong>reason</strong> (string to use as ban reason)</li>
<li><strong>datacenter</strong> (bool to set DC ban exemption flag)</li>
<li><strong>blacklisted_range</strong> (bool to set blacklisted range ban exemption flag)</li>
</ul>
</div>

<div class="card">
<div class="card-body">
<form method="post" enctype="multipart/form-data" id="uploadForm">
<div class="form-group">
<label for="file" class="form-label">Choose a .TSV file to Upload:</label>
<input type="file" class="form-control" id="file" name="file" required>
</div>
<div class="mt-2">
<button type="button" class="btn btn-primary" id="unbanButton" onclick="showConfirmation()">Ban</button>
</div>
<div class="mt-2" id="confirmationButton" style="display: none;">
<button type="submit" class="btn btn-danger">Are you sure?</button>
</div>
</form>
</div>
</div>
</div>

@if (!ModelState.IsValid)
{
<div class="alert alert-danger mt-3" role="alert">
<ul>
@foreach (var modelState in ViewData.ModelState.Values)
{
foreach (var error in modelState.Errors)
{
<li>@error.ErrorMessage</li>
}
}
</ul>
</div>
}

@if (TempData["StatusMessage"] != null)
{
<div class="alert alert-success mt-3" role="alert">
@TempData["StatusMessage"]
</div>
}

@section Scripts {
<script>
function showConfirmation() {
const confirmationButton = document.getElementById('confirmationButton');
const unbanButton = document.getElementById('unbanButton');
confirmationButton.style.display = 'block';
unbanButton.style.display = 'none';
setTimeout(function() {
confirmationButton.style.display = 'none';
unbanButton.style.display = 'block';
}, 3000); // Revert after 3 seconds
}
</script>
}
133 changes: 133 additions & 0 deletions SS14.Admin/Pages/Bans/CreateMassBan.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
using System.Globalization;
using Content.Server.Database;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using SS14.Admin.Helpers;
using CsvHelper;

namespace SS14.Admin.Pages.Bans
{
[Authorize(Roles = "MASSBAN")]
[ValidateAntiForgeryToken]
public class CreateMassBanModel : PageModel
{
private readonly PostgresServerDbContext _dbContext;
private readonly BanHelper _banHelper;

public CreateMassBanModel(PostgresServerDbContext dbContext, BanHelper banHelper)
{
_dbContext = dbContext;
_banHelper = banHelper;
}

public int BanCount { get; private set; }

public record TsvEntry(
string UserId,
string Address,
string Hwid,
string Reason,
bool Datacenter,
bool BlacklistedRange
);

public async Task<IActionResult> OnPostAsync(IFormFile file)
{
if (file == null || file.Length <= 0)
{
ModelState.AddModelError(string.Empty, "Please select a file.");
return Page();
}

if (!file.FileName.EndsWith(".tsv", StringComparison.OrdinalIgnoreCase))
{
ModelState.AddModelError(string.Empty, "Only TSV files are allowed.");
return Page();
}

try
{
using var stream = new StreamReader(file.OpenReadStream());
var entries = ParseTsv(stream);

foreach (var entry in entries)
{
var ExemptFlags = BanExemptions.GetExemptionFromForm(Request.Form);

var ban = new ServerBan();

var ipAddr = entry.Address;
var hwid = entry.Hwid;

ban.ExemptFlags = ExemptFlags;
// ban.AutoDelete = Input.AutoDelete; // Uncomment and use if necessary
//ban.Hidden = Input.Hidden;
//ban.Severity = Input.Severity;

var error = await _banHelper.FillBanCommon(
ban,
entry.UserId,
ipAddr,
hwid,
0, // Assuming lengthMinutes is always 0 for mass bans for now
entry.Reason);

if (error != null)
{
ModelState.AddModelError(string.Empty, error);
return Page();
}

_dbContext.Ban.Add(ban);
}

await _dbContext.SaveChangesAsync();

TempData["StatusMessage"] = $"{entries.Count} ban(s) created successfully.";
return RedirectToPage("./Index");
}
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, $"An error occurred: {ex.Message}");
return Page();
}
}

private List<TsvEntry> ParseTsv(StreamReader reader)
{
var records = new List<TsvEntry>();

var config = new CsvHelper.Configuration.CsvConfiguration(CultureInfo.InvariantCulture)
{
Delimiter = "\t", // Specify tab as the delimiter
HasHeaderRecord = true, // TSV files have a header row
MissingFieldFound = null // Ignore missing fields
};

using (var csvReader = new CsvReader(reader, config))
{
if (!csvReader.Read() || !csvReader.ReadHeader())
{
throw new InvalidDataException("The TSV file is missing a header.");
}

while (csvReader.Read())
{
var record = new TsvEntry(
csvReader.GetField<string>("user_id"),
csvReader.GetField<string>("address"),
csvReader.GetField<string>("hwid"),
csvReader.GetField<string>("reason"),
csvReader.GetField<bool>("datacenter"),
csvReader.GetField<bool>("blacklisted_range")
);
records.Add(record);
BanCount += 1;
}
}

return records;
}
}
}
1 change: 1 addition & 0 deletions SS14.Admin/Pages/Bans/Hits.cshtml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@page "{ban}"
@using SS14.Admin.Helpers
@using SS14.Admin.Pages.Tables
@using Microsoft.AspNetCore.Mvc.TagHelpers
@model SS14.Admin.Pages.Bans.Hits

@{
Expand Down
5 changes: 5 additions & 0 deletions SS14.Admin/Pages/Bans/Index.cshtml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@page
@using SS14.Admin.Pages.Tables
@using SS14.Admin.Helpers
@using Microsoft.AspNetCore.Mvc.TagHelpers
@model SS14.Admin.Pages.BansModel

@{
Expand All @@ -19,6 +20,10 @@
{
<a class="btn btn-primary" asp-page="./Create">Create new ban</a>
}
@if (User.IsInRole("MASSBAN"))
{
<a class="btn btn-primary" asp-page="./CreateMassBan">Create new Mass Ban</a>
}
</div>


Expand Down
1 change: 1 addition & 0 deletions SS14.Admin/SS14.Admin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CsvHelper" />
<PackageReference Include="JetBrains.Annotations" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
Expand Down

0 comments on commit 8b608c2

Please sign in to comment.