fix: Adds server access with protected accounts (#915)

Adds a configuration file to specify protected accounts:
_Distribution/Configuration/server-access.json_
```json
{
  "newPasswordOnReset": false,
  "protectedAccounts": ["admin"]
}
```

Protected accounts are unbanned and reset to `AccessLevel.Owner` upon login.

The option `newPasswordOnReset` will create a new password for a protected account if it needs to be reset. The password is a random GUID and logged to the console.

_**Note:**_ If your player character was accidentally modified, simply make a new character to fix the old one.
This commit is contained in:
Kamron Batman 2022-01-10 23:14:55 -08:00 committed by GitHub
parent 51169ddbb0
commit fc51b60cc1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 108 additions and 5 deletions

View file

@ -241,13 +241,15 @@ namespace Server.Misc
{
res = DeleteResultType.CharBeingPlayed;
}
else if (RestrictDeletion && Core.Now < m.Created + DeleteDelay)
else if (acct.AccessLevel == AccessLevel.Player && RestrictDeletion && Core.Now < m.Created + DeleteDelay)
{
res = DeleteResultType.CharTooYoung;
}
else if (m.AccessLevel == AccessLevel.Player &&
// Don't need to check current location, if netstate is null, they're logged out
else if (
m.AccessLevel == AccessLevel.Player &&
Region.Find(m.LogoutLocation, m.LogoutMap).IsPartOf<JailRegion>()
) // Don't need to check current location, if netstate is null, they're logged out
)
{
res = DeleteResultType.BadRequest;
}
@ -265,7 +267,6 @@ namespace Server.Misc
state.SendCharacterDeleteResult(res);
state.SendCharacterListUpdate(acct);
}
public static bool CanCreate(IPAddress ip) =>

View file

@ -27,6 +27,9 @@ namespace Server.Misc
a.AccessLevel = AccessLevel.Owner;
Console.WriteLine("Account created.");
ServerAccess.AddProtectedAccount(a, true);
Console.WriteLine("Added {0} to the protected accounts list.", a.Username);
}
else
{

View file

@ -10,7 +10,7 @@ namespace Server.Network
{
// Delay in milliseconds
private static readonly int[] Delays = new int[0x100];
private static string ThrottlesConfiguration = "Configuration/throttles.json";
private const string ThrottlesConfiguration = "Configuration/throttles.json";
public static void Initialize()
{

View file

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json.Serialization;
using Server.Accounting;
using Server.Json;
using Server.Logging;
namespace Server.Misc;
public static class ServerAccess
{
private static readonly ILogger logger = LogFactory.GetLogger(typeof(ServerAccess));
private const string _serverAccessConfigurationPath = "Configuration/server-access.json";
public static ServerAccessConfiguration ServerAccessConfiguration { get; private set; }
public static void SaveConfiguration()
{
var path = Path.Join(Core.BaseDirectory, _serverAccessConfigurationPath);
JsonConfig.Serialize(path, ServerAccessConfiguration);
}
public static void AddProtectedAccount(Account acct, bool save = false)
{
ServerAccessConfiguration.ProtectedAccounts.Add(acct.Username.ToLower());
if (save)
{
SaveConfiguration();
}
}
public static void RemoveProtectedAccount(Account acct, bool save = false)
{
ServerAccessConfiguration.ProtectedAccounts.Remove(acct.Username.ToLower());
if (save)
{
SaveConfiguration();
}
}
public static void Configure()
{
var path = Path.Join(Core.BaseDirectory, _serverAccessConfigurationPath);
if (!File.Exists(path))
{
return;
}
ServerAccessConfiguration = JsonConfig.Deserialize<ServerAccessConfiguration>(path);
var protectedAccounts = string.Join(", ", ServerAccessConfiguration.ProtectedAccounts);
logger.Information("Protected accounts registered: {0}", protectedAccounts);
}
public static void Initialize()
{
EventSink.AccountLogin += EventSink_ResetProtectedAccount;
}
public static void EventSink_ResetProtectedAccount(AccountLoginEventArgs e)
{
var username = e.Username.ToLower();
if (!ServerAccessConfiguration.ProtectedAccounts.Contains(username))
{
return;
}
var account = Accounts.GetAccount(username);
if (account is not { Banned: true, AccessLevel: >= AccessLevel.Owner })
{
return;
}
account.Banned = false;
account.AccessLevel = AccessLevel.Owner;
logger.Warning("Protected account \"{0}\" has been reset.", username);
if (ServerAccessConfiguration.NewPasswordOnReset)
{
var password = Guid.NewGuid().ToString();
logger.Warning("Protected account \"{0}\" password reset to \"{1}\"", username, password);
account.SetPassword(password);
}
e.Accepted = true;
}
}
public record ServerAccessConfiguration
{
[JsonPropertyName("newPasswordOnReset")]
public bool NewPasswordOnReset { get; init; }
[JsonPropertyName("protectedAccounts")]
public HashSet<string> ProtectedAccounts { get; init; }
}