Persist deadmin to database, add admin suspension system (#34048)

This commit is contained in:
Pieter-Jan Briers
2025-01-15 00:46:45 +01:00
committed by GitHub
parent 47042cc8dd
commit c2e050ced0
15 changed files with 4284 additions and 25 deletions

View File

@@ -91,14 +91,29 @@ namespace Content.Server.Administration.Managers
_chat.SendAdminAnnouncement(Loc.GetString("admin-manager-self-de-admin-message", ("exAdminName", session.Name)));
_chat.DispatchServerMessage(session, Loc.GetString("admin-manager-became-normal-player-message"));
var plyData = session.ContentData()!;
plyData.ExplicitlyDeadminned = true;
UpdateDatabaseDeadminnedState(session, true);
reg.Data.Active = false;
SendPermsChangedEvent(session);
UpdateAdminStatus(session);
}
private async void UpdateDatabaseDeadminnedState(ICommonSession player, bool newState)
{
try
{
// NOTE: This function gets called if you deadmin/readmin from a transient admin status.
// (e.g. loginlocal)
// In which case there may not be a database record.
// The DB function handles this scenario fine, but it's worth noting.
await _dbManager.UpdateAdminDeadminnedAsync(player.UserId, newState);
}
catch (Exception e)
{
_sawmill.Error("Failed to save deadmin state to database for {Admin}", player.UserId);
}
}
public void Stealth(ICommonSession session)
{
if (!_admins.TryGetValue(session, out var reg))
@@ -151,8 +166,7 @@ namespace Content.Server.Administration.Managers
_chat.DispatchServerMessage(session, Loc.GetString("admin-manager-became-admin-message"));
var plyData = session.ContentData()!;
plyData.ExplicitlyDeadminned = false;
UpdateDatabaseDeadminnedState(session, false);
reg.Data.Active = true;
if (!reg.Data.Stealth)
@@ -208,13 +222,13 @@ namespace Content.Server.Administration.Managers
curAdmin.IsSpecialLogin = special;
curAdmin.RankId = rankId;
curAdmin.Data = aData;
}
if (!player.ContentData()!.ExplicitlyDeadminned)
{
aData.Active = true;
if (curAdmin.Data.Active)
{
aData.Active = true;
_chat.DispatchServerMessage(player, Loc.GetString("admin-manager-admin-permissions-updated-message"));
_chat.DispatchServerMessage(player, Loc.GetString("admin-manager-admin-permissions-updated-message"));
}
}
if (player.ContentData()!.Stealthed)
@@ -381,10 +395,8 @@ namespace Content.Server.Administration.Managers
if (session.ContentData()!.Stealthed)
reg.Data.Stealth = true;
if (!session.ContentData()!.ExplicitlyDeadminned)
if (reg.Data.Active)
{
reg.Data.Active = true;
if (_cfg.GetCVar(CCVars.AdminAnnounceLogin))
{
if (reg.Data.Stealth)
@@ -430,6 +442,7 @@ namespace Content.Server.Administration.Managers
{
Title = Loc.GetString("admin-manager-admin-data-host-title"),
Flags = AdminFlagsHelper.Everything,
Active = true,
};
return (data, null, true);
@@ -444,6 +457,12 @@ namespace Content.Server.Administration.Managers
return null;
}
if (dbData.Suspended)
{
// Suspended admins don't count.
return null;
}
var flags = AdminFlags.None;
if (dbData.AdminRank != null)
@@ -466,7 +485,8 @@ namespace Content.Server.Administration.Managers
var data = new AdminData
{
Flags = flags
Flags = flags,
Active = !dbData.Deadminned,
};
if (dbData.Title != null && _cfg.GetCVar(CCVars.AdminUseCustomNamesAdminRank))

View File

@@ -76,7 +76,8 @@ namespace Content.Server.Administration.UI
Title = p.a.Title,
RankId = p.a.AdminRankId,
UserId = new NetUserId(p.a.UserId),
UserName = p.lastUserName
UserName = p.lastUserName,
Suspended = p.a.Suspended,
}).ToArray(),
AdminRanks = _adminRanks.ToDictionary(a => a.Id, a => new PermissionsEuiState.AdminRankData
@@ -255,6 +256,7 @@ namespace Content.Server.Administration.UI
admin.Title = ua.Title;
admin.AdminRankId = ua.RankId;
admin.Flags = GenAdminFlagList(ua.PosFlags, ua.NegFlags);
admin.Suspended = ua.Suspended;
await _db.UpdateAdminAsync(admin);
@@ -335,7 +337,8 @@ namespace Content.Server.Administration.UI
Flags = GenAdminFlagList(ca.PosFlags, ca.NegFlags),
AdminRankId = ca.RankId,
UserId = userId.UserId,
Title = ca.Title
Title = ca.Title,
Suspended = ca.Suspended,
};
await _db.AddAdminAsync(admin);

View File

@@ -751,6 +751,20 @@ namespace Content.Server.Database
existing.Flags = admin.Flags;
existing.Title = admin.Title;
existing.AdminRankId = admin.AdminRankId;
existing.Deadminned = admin.Deadminned;
existing.Suspended = admin.Suspended;
await db.DbContext.SaveChangesAsync(cancel);
}
public async Task UpdateAdminDeadminnedAsync(NetUserId userId, bool deadminned, CancellationToken cancel)
{
await using var db = await GetDb(cancel);
var adminRecord = db.DbContext.Admin.Where(a => a.UserId == userId);
await adminRecord.ExecuteUpdateAsync(
set => set.SetProperty(p => p.Deadminned, deadminned),
cancellationToken: cancel);
await db.DbContext.SaveChangesAsync(cancel);
}

View File

@@ -217,6 +217,16 @@ namespace Content.Server.Database
Task AddAdminAsync(Admin admin, CancellationToken cancel = default);
Task UpdateAdminAsync(Admin admin, CancellationToken cancel = default);
/// <summary>
/// Update whether an admin has voluntarily deadminned.
/// </summary>
/// <remarks>
/// This does nothing if the player is not an admin.
/// </remarks>
/// <param name="userId">The user ID of the admin.</param>
/// <param name="deadminned">Whether the admin is deadminned or not.</param>
Task UpdateAdminDeadminnedAsync(NetUserId userId, bool deadminned, CancellationToken cancel = default);
Task RemoveAdminRankAsync(int rankId, CancellationToken cancel = default);
Task AddAdminRankAsync(AdminRank rank, CancellationToken cancel = default);
Task UpdateAdminRankAsync(AdminRank rank, CancellationToken cancel = default);
@@ -674,6 +684,12 @@ namespace Content.Server.Database
return RunDbCommand(() => _db.UpdateAdminAsync(admin, cancel));
}
public Task UpdateAdminDeadminnedAsync(NetUserId userId, bool deadminned, CancellationToken cancel = default)
{
DbWriteOpsMetric.Inc();
return RunDbCommand(() => _db.UpdateAdminDeadminnedAsync(userId, deadminned, cancel));
}
public Task RemoveAdminRankAsync(int rankId, CancellationToken cancel = default)
{
DbWriteOpsMetric.Inc();