Players are verified when they're in the configured Steam group (public memberslistxml, refetched every 10 minutes, kept on failure) or have an unexpired override row in gv_verified, written by the web panel. Settings and data live in CS2-SimpleAdmin's MySQL database (gv_verified, gv_settings, gv_migrations), reached through its API. - css_gv_group <groupId64|0>, css_gv_enable, css_gv_disable (@css/root): verification runs only when enabled with a group set. - css_verify <target>: why a player is or isn't verified. Admin and above (by immunity from SimpleAdmin's groups) plus Guardian, unless admin_overrides.json says otherwise. - groupverify:api (shared/GroupVerifyApi): IsVerified, GetStatus, IsActive and OnVerifiedChanged. The API object lives in the shared assembly, so it survives hot reloads of GroupVerify.
81 lines
3.7 KiB
C#
81 lines
3.7 KiB
C#
namespace GroupVerify;
|
|
|
|
// The plugin's settings, from gv_settings. Immutable: a reload swaps in a new one.
|
|
internal sealed record Settings(
|
|
bool Enabled,
|
|
ulong GroupId64,
|
|
int RefreshMinutes,
|
|
int MinForcedRefreshSeconds,
|
|
int DbReloadSeconds,
|
|
TimeZoneInfo TimeZone,
|
|
string VerifyMinRank,
|
|
string[] VerifyExtraRanks)
|
|
{
|
|
// Written to gv_settings when missing. The rank defaults are our real SimpleAdmin groups (see
|
|
// the fork's Helper.StaffRanks and the web panel's site config). Only the names are set here:
|
|
// "Admin or higher" is decided by immunity read from sa_groups.
|
|
public static readonly (string Name, string Value)[] Defaults =
|
|
[
|
|
("enabled", "1"), // 0 turns verification off (css_gv_enable/css_gv_disable)
|
|
("group_id64", "0"), // the Steam group's 64-bit ID (103582791...); 0 turns verification off (css_gv_group)
|
|
("refresh_minutes", "10"), // how often the group's member list is fetched
|
|
("min_forced_refresh_seconds", "60"), // css_verify refetches/reloads only when older than this
|
|
("db_reload_seconds", "60"), // how often gv_verified and gv_settings are reread
|
|
("timezone", "UTC"), // must match CS2-SimpleAdmin's Timezone
|
|
("verify_min_rank", "#rank/admin"), // css_verify: this group's immunity or higher
|
|
("verify_extra_ranks", "#rank/guardian") // css_verify: these groups too, comma-separated
|
|
];
|
|
|
|
public static readonly Settings Default = Parse(new Dictionary<string, string>(), _ => { });
|
|
|
|
public static Settings Parse(IReadOnlyDictionary<string, string> values, Action<string> warn)
|
|
{
|
|
string Get(string name) =>
|
|
values.TryGetValue(name, out var value) ? value.Trim() : Defaults.First(d => d.Name == name).Value;
|
|
|
|
int GetInt(string name, int min)
|
|
{
|
|
if (int.TryParse(Get(name), out var value) && value >= min)
|
|
return value;
|
|
var fallback = int.Parse(Defaults.First(d => d.Name == name).Value);
|
|
warn($"gv_settings {name} must be a number of at least {min}; using {fallback}");
|
|
return fallback;
|
|
}
|
|
|
|
ulong groupId = 0;
|
|
var groupText = Get("group_id64");
|
|
if (groupText.Length > 0 && !ulong.TryParse(groupText, out groupId))
|
|
warn($"gv_settings group_id64 \"{groupText}\" isn't a 64-bit group ID; verification is off");
|
|
|
|
var timeZone = TimeZoneInfo.Utc;
|
|
var zoneName = Get("timezone");
|
|
try
|
|
{
|
|
timeZone = TimeZoneInfo.FindSystemTimeZoneById(zoneName);
|
|
}
|
|
catch (Exception ex) when (ex is TimeZoneNotFoundException or InvalidTimeZoneException)
|
|
{
|
|
warn($"gv_settings timezone \"{zoneName}\" isn't a known time zone; using UTC");
|
|
}
|
|
|
|
return new Settings(
|
|
Get("enabled") != "0",
|
|
groupId,
|
|
GetInt("refresh_minutes", 1),
|
|
GetInt("min_forced_refresh_seconds", 0),
|
|
GetInt("db_reload_seconds", 10),
|
|
timeZone,
|
|
Get("verify_min_rank"),
|
|
Get("verify_extra_ranks").Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries));
|
|
}
|
|
|
|
// Verification only runs when enabled with a group set; otherwise nobody is verified.
|
|
public bool Active => Enabled && GroupId64 != 0;
|
|
|
|
// Now as a wall-clock time in the database's time zone, to the second (MySQL rounds fractions).
|
|
public DateTime Now()
|
|
{
|
|
var now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZone);
|
|
return DateTime.SpecifyKind(now.AddTicks(-(now.Ticks % TimeSpan.TicksPerSecond)), DateTimeKind.Unspecified);
|
|
}
|
|
}
|