-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the Capability to mass ban players based on .tsv files (#59)
* 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
Showing
7 changed files
with
221 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters