Merge branch 'general-devel' into fragments

This commit is contained in:
Lucas Nicodemus 2017-12-06 21:14:45 -07:00
commit 4e3cd00848
8 changed files with 438 additions and 203 deletions

View file

@ -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)

View file

@ -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);
}
}
}

View file

@ -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;
}
}
}

View file

@ -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)

View file

@ -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

View file

@ -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");
}

View file

@ -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
{

View file

@ -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)
{