Merge branch 'general-devel' into fragments
This commit is contained in:
commit
4e3cd00848
8 changed files with 438 additions and 203 deletions
|
|
@ -14,9 +14,13 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
|
|||
* Added a warning notifying users of the minimum memory required to run TShock (@bartico6)
|
||||
* Added /group rename to allow changing group names (@ColinBohn, @ProfessorXZ)
|
||||
* Added /region rename and OnRegionRenamed hook (@koneko-nyan, @deadsurgeon42)
|
||||
* Rebuilt /ban add. New syntax is /ban add <target> [time] [reason] where target is the target online player, offline player, or IP; where time is the time format or 0 for permanent; and where [reason] is the reason. (@hakusaro)
|
||||
* Removed /ban addip and /ban addtemp. Now covered under /ban add. (@hakusaro)
|
||||
* Added /su, which temporarily elevates players with the tshock.su permission to super admin. In addition added, a new group, owner, that is suggested for new users to setup TShock with as opposed to superadmin. Finally, /su is implemented such that a 10 minute timeout will occur preventing people from just camping with it on. (@hakusaro)
|
||||
* Added /sudo, which runs a command as the superadmin group. If a user fails to execute a command but can sudo, they'll be told that they can override the permission check with sudo. Much better than just telling them to run /su and then re-run the command. (@hakusaro)
|
||||
|
||||
* Fixed /savessc not bothering to save ssc data for people who bypass ssc. (@hakusaro)
|
||||
* Default permission sets for new databases are more modern. (@hakusaro)
|
||||
* Added the ability to ban by account name instead of just banning a character name assuming its an account name. (@hakusaro)
|
||||
|
||||
## TShock 4.3.24
|
||||
* Updated OpenTerraria API to 1.3.5.3 (@DeathCradle)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ using Terraria.GameContent.Events;
|
|||
using Microsoft.Xna.Framework;
|
||||
using OTAPI.Tile;
|
||||
using TShockAPI.Localization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace TShockAPI
|
||||
{
|
||||
|
|
@ -1285,200 +1286,197 @@ namespace TShockAPI
|
|||
switch (subcmd)
|
||||
{
|
||||
case "add":
|
||||
#region Add ban
|
||||
#region Add Ban
|
||||
{
|
||||
if (args.Parameters.Count < 2)
|
||||
{
|
||||
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}ban add <player> [reason]", Specifier);
|
||||
args.Player.SendErrorMessage("Invalid command. Format: {0}ban add <player> [time] [reason]", Specifier);
|
||||
args.Player.SendErrorMessage("Example: {0}ban add Shank 10d Hacking and cheating", Specifier);
|
||||
args.Player.SendErrorMessage("Example: {0}ban add Ash", Specifier);
|
||||
args.Player.SendErrorMessage("Use the time 0 (zero) for a permanent ban.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Used only to notify if a ban was successful and who the ban was about
|
||||
bool success = false;
|
||||
string targetGeneralizedName = "";
|
||||
|
||||
// Effective ban target assignment
|
||||
List<TSPlayer> players = TShock.Utils.FindPlayer(args.Parameters[1]);
|
||||
string reason = args.Parameters.Count > 2 ? String.Join(" ", args.Parameters.Skip(2)) : "Misbehavior.";
|
||||
if (players.Count == 0)
|
||||
User offlineUser = TShock.Users.GetUserByName(args.Parameters[1]);
|
||||
|
||||
// Storage variable to determine if the command executor is the server console
|
||||
// If it is, we assume they have full control and let them override permission checks
|
||||
bool callerIsServerConsole = false;
|
||||
|
||||
if (args.Player is TSServerPlayer)
|
||||
{
|
||||
var user = TShock.Users.GetUserByName(args.Parameters[1]);
|
||||
if (user != null)
|
||||
{
|
||||
bool force = !args.Player.RealPlayer;
|
||||
|
||||
if (user.Name == args.Player.Name && !force)
|
||||
{
|
||||
args.Player.SendErrorMessage("You can't ban yourself!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TShock.Groups.GetGroupByName(user.Group).HasPermission(Permissions.immunetoban) && !force)
|
||||
args.Player.SendErrorMessage("You can't ban {0}!", user.Name);
|
||||
else
|
||||
{
|
||||
if (user.KnownIps == null)
|
||||
{
|
||||
args.Player.SendErrorMessage("Cannot ban {0} because they have no IPs to ban.", user.Name);
|
||||
return;
|
||||
}
|
||||
var knownIps = JsonConvert.DeserializeObject<List<string>>(user.KnownIps);
|
||||
TShock.Bans.AddBan(knownIps.Last(), user.Name, user.UUID, reason, false, args.Player.User.Name);
|
||||
if (String.IsNullOrWhiteSpace(args.Player.User.Name))
|
||||
{
|
||||
if (args.Silent)
|
||||
{
|
||||
args.Player.SendInfoMessage("{0} was {1}banned for '{2}'.", user.Name, force ? "Force " : "", reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSPlayer.All.SendInfoMessage("{0} was {1}banned for '{2}'.", user.Name, force ? "Force " : "", reason);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Silent)
|
||||
{
|
||||
args.Player.SendInfoMessage("{0}banned {1} for '{2}'.", force ? "Force " : "", user.Name, reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSPlayer.All.SendInfoMessage("{0} {1}banned {2} for '{3}'.", args.Player.Name, force ? "Force " : "", user.Name, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
args.Player.SendErrorMessage("Invalid player or account!");
|
||||
callerIsServerConsole = true;
|
||||
}
|
||||
else if (players.Count > 1)
|
||||
|
||||
// The ban reason the ban is going to have
|
||||
string banReason = "Unknown.";
|
||||
|
||||
// The default ban length
|
||||
// 0 is permanent ban, otherwise temp ban
|
||||
int banLengthInSeconds = 0;
|
||||
|
||||
// Figure out if param 2 is a time or 0 or garbage
|
||||
if (args.Parameters.Count >= 3)
|
||||
{
|
||||
bool parsedOkay = false;
|
||||
if (!(args.Parameters[2] == "0"))
|
||||
{
|
||||
parsedOkay = TShock.Utils.TryParseTime(args.Parameters[2], out banLengthInSeconds);
|
||||
} else {
|
||||
parsedOkay = true;
|
||||
}
|
||||
|
||||
if (!parsedOkay)
|
||||
{
|
||||
args.Player.SendErrorMessage("Invalid time format. Example: 10d+5h+3m-2s.");
|
||||
args.Player.SendErrorMessage("Use 0 (zero) for a permanent ban.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If a reason exists, use the given reason.
|
||||
if (args.Parameters.Count > 3)
|
||||
{
|
||||
banReason = String.Join(" ", args.Parameters.Skip(3));
|
||||
}
|
||||
|
||||
// Bad case: Players contains more than 1 person so we can't ban them
|
||||
if (players.Count > 1)
|
||||
{
|
||||
TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name));
|
||||
else
|
||||
{
|
||||
if (!TShock.Utils.Ban(players[0], reason, !args.Player.RealPlayer, args.Player.User.Name))
|
||||
args.Player.SendErrorMessage("You can't ban {0}!", players[0].Name);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
return;
|
||||
case "addip":
|
||||
#region Add IP ban
|
||||
{
|
||||
if (args.Parameters.Count < 2)
|
||||
{
|
||||
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}ban addip <ip> [reason]", Specifier);
|
||||
return;
|
||||
}
|
||||
|
||||
string ip = args.Parameters[1];
|
||||
string reason = args.Parameters.Count > 2
|
||||
? String.Join(" ", args.Parameters.GetRange(2, args.Parameters.Count - 2))
|
||||
: "Manually added IP address ban.";
|
||||
TShock.Bans.AddBan(ip, "", "", reason, false, args.Player.User.Name);
|
||||
args.Player.SendSuccessMessage("Banned IP {0}.", ip);
|
||||
}
|
||||
#endregion
|
||||
return;
|
||||
case "addtemp":
|
||||
#region Add temp ban
|
||||
{
|
||||
if (args.Parameters.Count < 3)
|
||||
// Good case: Online ban for matching character.
|
||||
if (players.Count == 1)
|
||||
{
|
||||
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}ban addtemp <player> <time> [reason]", Specifier);
|
||||
return;
|
||||
}
|
||||
TSPlayer target = players[0];
|
||||
|
||||
int time;
|
||||
if (!TShock.Utils.TryParseTime(args.Parameters[2], out time))
|
||||
{
|
||||
args.Player.SendErrorMessage("Invalid time string! Proper format: _d_h_m_s, with at least one time specifier.");
|
||||
args.Player.SendErrorMessage("For example, 1d and 10h-30m+2m are both valid time strings, but 2 is not.");
|
||||
return;
|
||||
}
|
||||
|
||||
string reason = args.Parameters.Count > 3
|
||||
? String.Join(" ", args.Parameters.Skip(3))
|
||||
: "Misbehavior.";
|
||||
|
||||
List<TSPlayer> players = TShock.Utils.FindPlayer(args.Parameters[1]);
|
||||
if (players.Count == 0)
|
||||
{
|
||||
var user = TShock.Users.GetUserByName(args.Parameters[1]);
|
||||
if (user != null)
|
||||
if (target.HasPermission(Permissions.immunetoban) && !callerIsServerConsole)
|
||||
{
|
||||
bool force = !args.Player.RealPlayer;
|
||||
if (TShock.Groups.GetGroupByName(user.Group).HasPermission(Permissions.immunetoban) && !force)
|
||||
args.Player.SendErrorMessage("You can't ban {0}!", user.Name);
|
||||
else
|
||||
{
|
||||
var knownIps = JsonConvert.DeserializeObject<List<string>>(user.KnownIps);
|
||||
TShock.Bans.AddBan(knownIps.Last(), user.Name, user.UUID, reason, false, args.Player.User.Name, DateTime.UtcNow.AddSeconds(time).ToString("s"));
|
||||
if (String.IsNullOrWhiteSpace(args.Player.User.Name))
|
||||
{
|
||||
if (args.Silent)
|
||||
{
|
||||
args.Player.SendInfoMessage("{0} was {1}banned for '{2}'.", user.Name, force ? "force " : "", reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSPlayer.All.SendInfoMessage("{0} was {1}banned for '{2}'.", user.Name, force ? "force " : "", reason);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Silent)
|
||||
{
|
||||
args.Player.SendInfoMessage("{0} was {1}banned for '{2}'.", user.Name, force ? "force " : "", reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSPlayer.All.SendInfoMessage("{0} {1}banned {2} for '{3}'.", args.Player.Name, force ? "force " : "", user.Name, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Player.SendErrorMessage("Invalid player or account!");
|
||||
}
|
||||
}
|
||||
else if (players.Count > 1)
|
||||
TShock.Utils.SendMultipleMatchError(args.Player, players.Select(p => p.Name));
|
||||
else
|
||||
{
|
||||
if (args.Player.RealPlayer && players[0].HasPermission(Permissions.immunetoban))
|
||||
{
|
||||
args.Player.SendErrorMessage("You can't ban {0}!", players[0].Name);
|
||||
args.Player.SendErrorMessage("Permission denied. Target {0} is immune to ban.", target.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (TShock.Bans.AddBan(players[0].IP, players[0].Name, players[0].UUID, reason,
|
||||
false, args.Player.Name, DateTime.UtcNow.AddSeconds(time).ToString("s")))
|
||||
targetGeneralizedName = target.Name;
|
||||
success = TShock.Bans.AddBan2(target.IP, target.Name, target.UUID, target.User.Name, banReason, false, args.Player.User.Name,
|
||||
banLengthInSeconds == 0 ? "" : DateTime.UtcNow.AddSeconds(banLengthInSeconds).ToString("s"));
|
||||
|
||||
// Since this is an online ban, we need to dc the player and tell them now.
|
||||
if (success)
|
||||
{
|
||||
players[0].Disconnect(String.Format("Banned: {0}", reason));
|
||||
string verb = args.Player.RealPlayer ? "Force " : "";
|
||||
if (args.Player.RealPlayer)
|
||||
if (args.Silent)
|
||||
{
|
||||
args.Player.SendSuccessMessage("{0}banned {1} for '{2}'", verb, players[0].Name, reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSPlayer.All.SendSuccessMessage("{0} {1}banned {2} for '{3}'", args.Player.Name, verb, players[0].Name, reason);
|
||||
}
|
||||
if (banLengthInSeconds == 0)
|
||||
{
|
||||
target.Disconnect(String.Format("Permanently banned for {0}", banReason));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Silent)
|
||||
{
|
||||
args.Player.SendSuccessMessage("{0}banned {1} for '{2}'", verb, players[0].Name, reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSPlayer.All.SendSuccessMessage("{0} was {1}banned for '{2}'", players[0].Name, verb, reason);
|
||||
}
|
||||
target.Disconnect(String.Format("Banned for {0} seconds for {1}", banLengthInSeconds, banReason));
|
||||
}
|
||||
}
|
||||
else
|
||||
args.Player.SendErrorMessage("Failed to ban {0}, check logs.", players[0].Name);
|
||||
}
|
||||
|
||||
// Case: Players & user are invalid, could be IP?
|
||||
// Note: Order matters. If this method is above the online player check,
|
||||
// This enables you to ban an IP even if the player exists in the database as a player.
|
||||
// You'll get two bans for the price of one, in theory, because both IP and user named IP will be banned.
|
||||
// ??? edge cases are weird, but this is going to happen
|
||||
// The only way around this is to either segregate off the IP code or do something else.
|
||||
if (players.Count == 0)
|
||||
{
|
||||
// If the target is a valid IP...
|
||||
string pattern = @"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
|
||||
Regex r = new Regex(pattern, RegexOptions.IgnoreCase);
|
||||
if (r.IsMatch(args.Parameters[1])) {
|
||||
targetGeneralizedName = "IP: " + args.Parameters[1];
|
||||
success = TShock.Bans.AddBan2(args.Parameters[1], "", "", "", banReason,
|
||||
false, args.Player.User.Name, banLengthInSeconds == 0 ? "" : DateTime.UtcNow.AddSeconds(banLengthInSeconds).ToString("s"));
|
||||
if (success && offlineUser != null)
|
||||
{
|
||||
args.Player.SendSuccessMessage("Target IP {0} was banned successfully.", targetGeneralizedName);
|
||||
args.Player.SendErrorMessage("Note: An account named with this IP address also exists.");
|
||||
args.Player.SendErrorMessage("Note: It will also be banned.");
|
||||
}
|
||||
} else {
|
||||
// Apparently there is no way to not IP ban someone
|
||||
// This means that where we would normally just ban a "character name" here
|
||||
// We can't because it requires some IP as a primary key.
|
||||
if (offlineUser == null)
|
||||
{
|
||||
args.Player.SendErrorMessage("Unable to ban target {0}.", args.Parameters[1]);
|
||||
args.Player.SendErrorMessage("Target is not a valid IP address, a valid online player, or a known offline user.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Case: Offline ban
|
||||
if (players.Count == 0 && offlineUser != null)
|
||||
{
|
||||
// Catch: we don't know an offline player's last login character name
|
||||
// This means that we're banning their *user name* on the assumption that
|
||||
// user name == character name
|
||||
// (which may not be true)
|
||||
// This needs to be fixed in a future implementation.
|
||||
targetGeneralizedName = offlineUser.Name;
|
||||
|
||||
if (TShock.Groups.GetGroupByName(offlineUser.Group).HasPermission(Permissions.immunetoban) &&
|
||||
!callerIsServerConsole)
|
||||
{
|
||||
args.Player.SendErrorMessage("Permission denied. Target {0} is immune to ban.", targetGeneralizedName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (offlineUser.KnownIps == null)
|
||||
{
|
||||
args.Player.SendErrorMessage("Unable to ban target {0} because they have no valid IP to ban.", targetGeneralizedName);
|
||||
return;
|
||||
}
|
||||
|
||||
string lastIP = JsonConvert.DeserializeObject<List<string>>(offlineUser.KnownIps).Last();
|
||||
|
||||
success =
|
||||
TShock.Bans.AddBan2(lastIP,
|
||||
"", offlineUser.UUID, offlineUser.Name, banReason, false, args.Player.User.Name,
|
||||
banLengthInSeconds == 0 ? "" : DateTime.UtcNow.AddSeconds(banLengthInSeconds).ToString("s"));
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
args.Player.SendSuccessMessage("{0} was successfully banned.", targetGeneralizedName);
|
||||
args.Player.SendInfoMessage("Length: {0}", banLengthInSeconds == 0 ? "Permanent." : banLengthInSeconds + " seconds.");
|
||||
args.Player.SendInfoMessage("Reason: {0}", banReason);
|
||||
if (!args.Silent)
|
||||
{
|
||||
if (banLengthInSeconds == 0)
|
||||
{
|
||||
TSPlayer.All.SendErrorMessage("{0} was permanently banned by {1} for: {2}",
|
||||
targetGeneralizedName, args.Player.User.Name, banReason);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSPlayer.All.SendErrorMessage("{0} was temp banned for {1} seconds by {2} for: {3}",
|
||||
targetGeneralizedName, banLengthInSeconds, args.Player.User.Name, banReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Player.SendErrorMessage("{0} was NOT banned due to a database error or other system problem.", targetGeneralizedName);
|
||||
args.Player.SendErrorMessage("If this player is online, they have NOT been kicked.");
|
||||
args.Player.SendErrorMessage("Check the system logs for details.");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endregion
|
||||
return;
|
||||
case "del":
|
||||
#region Delete ban
|
||||
{
|
||||
|
|
@ -1534,9 +1532,7 @@ namespace TShockAPI
|
|||
|
||||
var lines = new List<string>
|
||||
{
|
||||
"add <player> [reason] - Bans a player or user account if the player is not online.",
|
||||
"addip <ip> [reason] - Bans an IP.",
|
||||
"addtemp <player> <time> [reason] - Temporarily bans a player.",
|
||||
"add <target> <time> [reason] - Bans a player or user account if the player is not online.",
|
||||
"del <player> - Unbans a player.",
|
||||
"delip <ip> - Unbans an IP.",
|
||||
"list [page] - Lists all player bans.",
|
||||
|
|
@ -1636,7 +1632,7 @@ namespace TShockAPI
|
|||
{
|
||||
if (player != null && player.IsLoggedIn && !player.IgnoreActionsForClearingTrashCan)
|
||||
{
|
||||
TShock.CharacterDB.InsertPlayerData(player);
|
||||
TShock.CharacterDB.InsertPlayerData(player, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ namespace TShockAPI.DB
|
|||
new SqlColumn("Reason", MySqlDbType.Text),
|
||||
new SqlColumn("BanningUser", MySqlDbType.Text),
|
||||
new SqlColumn("Date", MySqlDbType.Text),
|
||||
new SqlColumn("Expiration", MySqlDbType.Text)
|
||||
new SqlColumn("Expiration", MySqlDbType.Text),
|
||||
new SqlColumn("AccountName", MySqlDbType.Text)
|
||||
);
|
||||
var creator = new SqlTableCreator(db,
|
||||
db.GetSqlType() == SqlType.Sqlite
|
||||
|
|
@ -75,7 +76,7 @@ namespace TShockAPI.DB
|
|||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE IP=@0", ip))
|
||||
{
|
||||
if (reader.Read())
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("AccountName"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -104,7 +105,7 @@ namespace TShockAPI.DB
|
|||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
banlist.Add(new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration")));
|
||||
banlist.Add(new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("AccountName"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration")));
|
||||
}
|
||||
|
||||
banlist.Sort(new BanComparer(sortMethod));
|
||||
|
|
@ -135,7 +136,33 @@ namespace TShockAPI.DB
|
|||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE " + namecol + "=@0", name))
|
||||
{
|
||||
if (reader.Read())
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("AccountName"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TShock.Log.Error(ex.ToString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a ban by account name (not player/character name).
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="casesensitive">Whether to check with case sensitivity.</param>
|
||||
/// <returns>The ban.</returns>
|
||||
public Ban GetBanByAccountName(string name, bool casesensitive = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
var namecol = casesensitive ? "AccountName" : "UPPER(AccountName)";
|
||||
if (!casesensitive)
|
||||
name = name.ToUpper();
|
||||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE " + namecol + "=@0", name))
|
||||
{
|
||||
if (reader.Read())
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("AccountName"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -157,7 +184,7 @@ namespace TShockAPI.DB
|
|||
using (var reader = database.QueryReader("SELECT * FROM Bans WHERE UUID=@0", uuid))
|
||||
{
|
||||
if (reader.Read())
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
return new Ban(reader.Get<string>("IP"), reader.Get<string>("Name"), reader.Get<string>("UUID"), reader.Get<string>("AccountName"), reader.Get<string>("Reason"), reader.Get<string>("BanningUser"), reader.Get<string>("Date"), reader.Get<string>("Expiration"));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -178,7 +205,24 @@ namespace TShockAPI.DB
|
|||
/// <param name="exceptions">If set to <c>true</c> enable throwing exceptions.</param>
|
||||
/// <param name="banner">Banner.</param>
|
||||
/// <param name="expiration">Expiration date.</param>
|
||||
[Obsolete("Use AddBan2 instead of AddBan.", true)]
|
||||
public bool AddBan(string ip, string name = "", string uuid = "", string reason = "", bool exceptions = false, string banner = "", string expiration = "")
|
||||
{
|
||||
return AddBan2(ip, name, uuid, "", reason, exceptions, banner, expiration);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a ban.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if ban was added, <c>false</c> otherwise.</returns>
|
||||
/// <param name="ip">Ip.</param>
|
||||
/// <param name="name">Name.</param>
|
||||
/// <param name="uuid">UUID.</param>
|
||||
/// <param name="reason">Reason.</param>
|
||||
/// <param name="exceptions">If set to <c>true</c> enable throwing exceptions.</param>
|
||||
/// <param name="banner">Banner.</param>
|
||||
/// <param name="expiration">Expiration date.</param>
|
||||
public bool AddBan2(string ip, string name = "", string uuid = "", string accountName = "", string reason = "", bool exceptions = false, string banner = "", string expiration = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -192,7 +236,7 @@ namespace TShockAPI.DB
|
|||
}
|
||||
else
|
||||
{
|
||||
return database.Query("INSERT INTO Bans (IP, Name, UUID, Reason, BanningUser, Date, Expiration) VALUES (@0, @1, @2, @3, @4, @5, @6);", ip, name, uuid, reason, banner, DateTime.UtcNow.ToString("s"), expiration) != 0;
|
||||
return database.Query("INSERT INTO Bans (IP, Name, UUID, Reason, BanningUser, Date, Expiration, AccountName) VALUES (@0, @1, @2, @3, @4, @5, @6, @7);", ip, name, uuid, reason, banner, DateTime.UtcNow.ToString("s"), expiration, accountName) != 0;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
@ -231,6 +275,26 @@ namespace TShockAPI.DB
|
|||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a ban by account name (not character/player name).
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if ban was removed, <c>false</c> otherwise.</returns>
|
||||
/// <param name="match">Match.</param>
|
||||
/// <param name="casesensitive">If set to <c>true</c> casesensitive.</param>
|
||||
public bool RemoveBanByAccountName(string match, bool casesensitive = true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var namecol = casesensitive ? "AccountName" : "UPPER(AccountName)";
|
||||
return database.Query("DELETE FROM Bans WHERE " + namecol + "=@0", casesensitive ? match : match.ToUpper()) != 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
TShock.Log.Error(ex.ToString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears bans.
|
||||
/// </summary>
|
||||
|
|
@ -380,6 +444,12 @@ namespace TShockAPI.DB
|
|||
/// <value>The UUID</value>
|
||||
public string UUID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the account name of the ban
|
||||
/// </summary>
|
||||
/// <value>The account name</value>
|
||||
public String AccountName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ban reason.
|
||||
/// </summary>
|
||||
|
|
@ -424,11 +494,12 @@ namespace TShockAPI.DB
|
|||
/// <param name="banner">Banner.</param>
|
||||
/// <param name="date">UTC ban date.</param>
|
||||
/// <param name="exp">Expiration time</param>
|
||||
public Ban(string ip, string name, string uuid, string reason, string banner, string date, string exp)
|
||||
public Ban(string ip, string name, string uuid, string accountName, string reason, string banner, string date, string exp)
|
||||
{
|
||||
IP = ip;
|
||||
Name = name;
|
||||
UUID = uuid;
|
||||
AccountName = accountName;
|
||||
Reason = reason;
|
||||
BanningUser = banner;
|
||||
Date = date;
|
||||
|
|
@ -454,10 +525,11 @@ namespace TShockAPI.DB
|
|||
IP = string.Empty;
|
||||
Name = string.Empty;
|
||||
UUID = string.Empty;
|
||||
AccountName = string.Empty;
|
||||
Reason = string.Empty;
|
||||
BanningUser = "";
|
||||
Date = "";
|
||||
Expiration = "";
|
||||
BanningUser = string.Empty;
|
||||
Date = string.Empty;
|
||||
Expiration = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,17 +156,17 @@ namespace TShockAPI.DB
|
|||
/// </summary>
|
||||
/// <param name="player">player to take data from</param>
|
||||
/// <returns>true if inserted successfully</returns>
|
||||
public bool InsertPlayerData(TSPlayer player)
|
||||
public bool InsertPlayerData(TSPlayer player, bool fromCommand = false)
|
||||
{
|
||||
PlayerData playerData = player.PlayerData;
|
||||
|
||||
if (!player.IsLoggedIn)
|
||||
return false;
|
||||
|
||||
if (player.HasPermission(Permissions.bypassssc))
|
||||
if (player.HasPermission(Permissions.bypassssc) && !fromCommand)
|
||||
{
|
||||
TShock.Log.ConsoleInfo("Skipping SSC Backup for " + player.User.Name); // Debug code
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetPlayerData(player, player.User.ID).exists)
|
||||
|
|
|
|||
|
|
@ -58,28 +58,121 @@ namespace TShockAPI.DB
|
|||
{
|
||||
// Add default groups if they don't exist
|
||||
AddDefaultGroup("guest", "",
|
||||
string.Join(",", Permissions.canbuild, Permissions.canregister, Permissions.canlogin, Permissions.canpartychat,
|
||||
Permissions.cantalkinthird, Permissions.canchat));
|
||||
string.Join(",",
|
||||
Permissions.canbuild,
|
||||
Permissions.canregister,
|
||||
Permissions.canlogin,
|
||||
Permissions.canpartychat,
|
||||
Permissions.cantalkinthird,
|
||||
Permissions.canchat));
|
||||
|
||||
AddDefaultGroup("default", "guest",
|
||||
string.Join(",", Permissions.warp, Permissions.canchangepassword, Permissions.canlogout));
|
||||
string.Join(",",
|
||||
Permissions.warp,
|
||||
Permissions.canchangepassword,
|
||||
Permissions.canlogout,
|
||||
Permissions.summonboss,
|
||||
Permissions.whisper,
|
||||
Permissions.wormhole,
|
||||
Permissions.canpaint));
|
||||
|
||||
AddDefaultGroup("newadmin", "default",
|
||||
string.Join(",", Permissions.kick, Permissions.editspawn, Permissions.reservedslot));
|
||||
AddDefaultGroup("vip", "default",
|
||||
string.Join(",",
|
||||
Permissions.reservedslot,
|
||||
Permissions.renamenpc,
|
||||
Permissions.startinvasion,
|
||||
Permissions.summonboss,
|
||||
Permissions.whisper,
|
||||
Permissions.wormhole));
|
||||
|
||||
AddDefaultGroup("newadmin", "vip",
|
||||
string.Join(",",
|
||||
Permissions.kick,
|
||||
Permissions.editspawn,
|
||||
Permissions.reservedslot,
|
||||
Permissions.annoy,
|
||||
Permissions.checkaccountinfo,
|
||||
Permissions.getpos,
|
||||
Permissions.mute,
|
||||
Permissions.rod,
|
||||
Permissions.savessc,
|
||||
Permissions.seeids,
|
||||
"tshock.world.time.*"));
|
||||
|
||||
AddDefaultGroup("admin", "newadmin",
|
||||
string.Join(",", Permissions.ban, Permissions.whitelist, "tshock.world.time.*", Permissions.spawnboss,
|
||||
Permissions.spawnmob, Permissions.managewarp, Permissions.time, Permissions.tp, Permissions.slap,
|
||||
Permissions.kill, Permissions.logs,
|
||||
Permissions.immunetokick, Permissions.tpothers));
|
||||
string.Join(",",
|
||||
Permissions.ban,
|
||||
Permissions.whitelist,
|
||||
Permissions.spawnboss,
|
||||
Permissions.spawnmob,
|
||||
Permissions.managewarp,
|
||||
Permissions.time,
|
||||
Permissions.tp,
|
||||
Permissions.slap,
|
||||
Permissions.kill,
|
||||
Permissions.logs,
|
||||
Permissions.immunetokick,
|
||||
Permissions.tpothers,
|
||||
Permissions.advaccountinfo,
|
||||
Permissions.broadcast,
|
||||
Permissions.home,
|
||||
Permissions.tpallothers,
|
||||
Permissions.tpallow,
|
||||
Permissions.tpnpc,
|
||||
Permissions.tppos,
|
||||
Permissions.tpsilent,
|
||||
Permissions.userinfo));
|
||||
|
||||
AddDefaultGroup("trustedadmin", "admin",
|
||||
string.Join(",", Permissions.maintenance, "tshock.cfg.*", "tshock.world.*", Permissions.butcher, Permissions.item, Permissions.give,
|
||||
Permissions.heal, Permissions.immunetoban, Permissions.usebanneditem));
|
||||
string.Join(",",
|
||||
Permissions.maintenance,
|
||||
"tshock.cfg.*",
|
||||
"tshock.world.*",
|
||||
Permissions.butcher,
|
||||
Permissions.item,
|
||||
Permissions.give,
|
||||
Permissions.heal,
|
||||
Permissions.immunetoban,
|
||||
Permissions.usebanneditem,
|
||||
Permissions.allowclientsideworldedit,
|
||||
Permissions.buff,
|
||||
Permissions.buffplayer,
|
||||
Permissions.clear,
|
||||
Permissions.clearangler,
|
||||
Permissions.godmode,
|
||||
Permissions.godmodeother,
|
||||
Permissions.ignoredamagecap,
|
||||
Permissions.ignorehp,
|
||||
Permissions.ignorekilltiledetection,
|
||||
Permissions.ignoreliquidsetdetection,
|
||||
Permissions.ignoremp,
|
||||
Permissions.ignorenoclipdetection,
|
||||
Permissions.ignorepaintdetection,
|
||||
Permissions.ignoreplacetiledetection,
|
||||
Permissions.ignoreprojectiledetection,
|
||||
Permissions.ignorestackhackdetection,
|
||||
Permissions.invade,
|
||||
Permissions.startdd2,
|
||||
Permissions.uploaddata,
|
||||
Permissions.uploadothersdata));
|
||||
|
||||
AddDefaultGroup("owner", "trustedadmin", string.Join(",", Permissions.su));
|
||||
|
||||
AddDefaultGroup("vip", "default", string.Join(",", Permissions.reservedslot));
|
||||
AddDefaultGroup("owner", "trustedadmin",
|
||||
string.Join(",",
|
||||
Permissions.su,
|
||||
Permissions.allowdroppingbanneditems,
|
||||
Permissions.antibuild,
|
||||
Permissions.canusebannedprojectiles,
|
||||
Permissions.canusebannedtiles,
|
||||
Permissions.managegroup,
|
||||
Permissions.manageitem,
|
||||
Permissions.manageprojectile,
|
||||
Permissions.manageregion,
|
||||
Permissions.managetile,
|
||||
Permissions.maxspawns,
|
||||
Permissions.serverinfo,
|
||||
Permissions.settempgroup,
|
||||
Permissions.spawnrate,
|
||||
Permissions.tpoverride));
|
||||
}
|
||||
|
||||
// Load Permissions from the DB
|
||||
|
|
|
|||
|
|
@ -645,7 +645,7 @@ namespace TShockAPI
|
|||
|
||||
try
|
||||
{
|
||||
TShock.Bans.AddBan(ip, name, "", args.Parameters["reason"], true, args.TokenData.Username);
|
||||
TShock.Bans.AddBan2(ip, name, "", "", args.Parameters["reason"], true, args.TokenData.Username);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -1022,7 +1022,7 @@ namespace TShockAPI
|
|||
|
||||
TSPlayer player = (TSPlayer)ret;
|
||||
var reason = null == args.Parameters["reason"] ? "Banned via web" : args.Parameters["reason"];
|
||||
TShock.Bans.AddBan(player.IP, player.Name, "", reason);
|
||||
TShock.Bans.AddBan2(player.IP, player.Name, "", "", reason);
|
||||
TShock.Utils.ForceKick(player, reason, false, true);
|
||||
return RestResponse("Player " + player.Name + " was banned");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -474,6 +474,28 @@ namespace TShockAPI
|
|||
|
||||
args.Player.User.KnownIps = JsonConvert.SerializeObject(KnownIps, Formatting.Indented);
|
||||
Users.UpdateLogin(args.Player.User);
|
||||
|
||||
Ban potentialBan = Bans.GetBanByAccountName(args.Player.User.Name);
|
||||
|
||||
if (potentialBan != null)
|
||||
{
|
||||
// A user just signed in successfully despite being banned by account name.
|
||||
// We should fix the ban database so that all of their ban info is up to date.
|
||||
Bans.AddBan2(args.Player.IP, args.Player.Name, args.Player.UUID, args.Player.User.Name,
|
||||
potentialBan.Reason, false, potentialBan.BanningUser, potentialBan.Expiration);
|
||||
|
||||
// And then get rid of them.
|
||||
if (potentialBan.Expiration == "")
|
||||
{
|
||||
Utils.ForceKick(args.Player, String.Format("Permanently banned by {0} for {1}", potentialBan.BanningUser
|
||||
,potentialBan.Reason), false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.ForceKick(args.Player, String.Format("Still banned by {0} for {1}", potentialBan.BanningUser,
|
||||
potentialBan.Reason), false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>OnAccountDelete - Internal hook fired on account delete.</summary>
|
||||
|
|
@ -1318,7 +1340,7 @@ namespace TShockAPI
|
|||
DateTime exp;
|
||||
if (!DateTime.TryParse(ban.Expiration, out exp))
|
||||
{
|
||||
player.Disconnect("You are banned forever: " + ban.Reason);
|
||||
player.Disconnect("Permanently banned for: " + ban.Reason);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -675,7 +675,7 @@ namespace TShockAPI
|
|||
string ip = player.IP;
|
||||
string uuid = player.UUID;
|
||||
string playerName = player.Name;
|
||||
TShock.Bans.AddBan(ip, playerName, uuid, reason, false, adminUserName);
|
||||
TShock.Bans.AddBan2(ip, playerName, uuid, "", reason, false, adminUserName);
|
||||
player.Disconnect(string.Format("Banned: {0}", reason));
|
||||
string verb = force ? "force " : "";
|
||||
if (string.IsNullOrWhiteSpace(adminUserName))
|
||||
|
|
@ -1204,6 +1204,7 @@ namespace TShockAPI
|
|||
Permissions.DumpDescriptions();
|
||||
ServerSideCharacters.ServerSideConfig.DumpDescriptions();
|
||||
RestManager.DumpDescriptions();
|
||||
DumpPermissionMatrix("PermissionMatrix.txt");
|
||||
DumpBuffs("BuffList.txt");
|
||||
DumpItems("Items-1_0.txt", -48, 235);
|
||||
DumpItems("Items-1_1.txt", 235, 604);
|
||||
|
|
@ -1212,6 +1213,7 @@ namespace TShockAPI
|
|||
DumpNPCs("NPCs.txt");
|
||||
DumpProjectiles("Projectiles.txt");
|
||||
DumpPrefixes("Prefixes.txt");
|
||||
|
||||
if (exit)
|
||||
{
|
||||
Environment.Exit(1);
|
||||
|
|
@ -1223,6 +1225,52 @@ namespace TShockAPI
|
|||
for(int i = 0; i < Main.recipe.Length; i++)
|
||||
Main.recipe[i] = new Recipe();
|
||||
}
|
||||
|
||||
// Dumps a matrix of all permissions and all groups in markdown format
|
||||
// Hard coded to default groups because apparently we have poor querying tools
|
||||
public void DumpPermissionMatrix(string path)
|
||||
{
|
||||
StringBuilder output = new StringBuilder();
|
||||
output.Append("|Permission|");
|
||||
|
||||
// Traverse to build group name list
|
||||
foreach (Group g in TShock.Groups.groups)
|
||||
{
|
||||
output.Append(g.Name);
|
||||
output.Append("|");
|
||||
}
|
||||
|
||||
output.AppendLine();
|
||||
output.Append("|-------|");
|
||||
|
||||
foreach (Group g in TShock.Groups.groups)
|
||||
{
|
||||
output.Append("-------|");
|
||||
}
|
||||
output.AppendLine();
|
||||
|
||||
foreach (var field in typeof(Permissions).GetFields().OrderBy(f => f.Name))
|
||||
{
|
||||
output.Append("|");
|
||||
output.Append((string) field.GetValue(null));
|
||||
output.Append("|");
|
||||
|
||||
foreach (Group g in TShock.Groups.groups)
|
||||
{
|
||||
if (g.HasPermission((string) field.GetValue(null)))
|
||||
{
|
||||
output.Append("✔|");
|
||||
}
|
||||
else
|
||||
{
|
||||
output.Append("|");
|
||||
}
|
||||
}
|
||||
output.AppendLine();
|
||||
}
|
||||
|
||||
File.WriteAllText(path, output.ToString());
|
||||
}
|
||||
|
||||
public void DumpBuffs(string path)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue