Added support for renaming groups. Fixes #1420
This commit is contained in:
parent
623815b9f6
commit
02806a2429
3 changed files with 168 additions and 19 deletions
|
|
@ -4,6 +4,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
|
|||
|
||||
## Upcoming Changes
|
||||
* API: Added hooks for item, projectile and tile bans (@deadsurgeon42)
|
||||
* API: Changed `PlayerHooks` permission hook mechanisms to allow negation from hooks (@deadsurgeon42)
|
||||
* API: New WorldGrassSpread hook which shold allow corruption/crimson/hallow creep config options to work (@DeathCradle)
|
||||
* Fixed saving when one player is one the server and another one joins (@MarioE)
|
||||
* Fixed /spawnmob not spawning negative IDs (@MarioE)
|
||||
|
|
@ -11,9 +12,9 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin
|
|||
* Updated to new stat tracking system with more data so we can actually make informed software decisions (Jordan Coulam)
|
||||
* Fixed /time display at the end of Terraria hours (@koneko-nyan)
|
||||
* Added a warning notifying users of the minimum memory required to run TShock (@bartico6)
|
||||
* Added /group rename to allow changing group names (@ColinBohn, @ProfessorXZ)
|
||||
|
||||
## TShock 4.3.24
|
||||
* API: Changed `PlayerHooks` permission hook mechanisms to allow negation from hooks (@deadsurgeon42)
|
||||
* Updated OpenTerraria API to 1.3.5.3 (@DeathCradle)
|
||||
* Updated Terraria Server API to 1.3.5.3 (@WhiteXZ, @hakusaro)
|
||||
* Updated TShock core components to 1.3.5.3 (@hakusaro)
|
||||
|
|
|
|||
|
|
@ -2865,6 +2865,7 @@ namespace TShockAPI
|
|||
"add <name> <permissions...> - Adds a new group.",
|
||||
"addperm <group> <permissions...> - Adds permissions to a group.",
|
||||
"color <group> <rrr,ggg,bbb> - Changes a group's chat color.",
|
||||
"rename <group> <new name> - Changes a group's name.",
|
||||
"del <group> - Deletes a group.",
|
||||
"delperm <group> <permissions...> - Removes permissions from a group.",
|
||||
"list [page] - Lists groups.",
|
||||
|
|
@ -3074,6 +3075,29 @@ namespace TShockAPI
|
|||
}
|
||||
#endregion
|
||||
return;
|
||||
case "rename":
|
||||
#region Rename group
|
||||
{
|
||||
if (args.Parameters.Count != 3)
|
||||
{
|
||||
args.Player.SendErrorMessage("Invalid syntax! Proper syntax: {0}group rename <group> <new name>", Specifier);
|
||||
return;
|
||||
}
|
||||
|
||||
string group = args.Parameters[1];
|
||||
string newName = args.Parameters[2];
|
||||
try
|
||||
{
|
||||
string response = TShock.Groups.RenameGroup(group, newName);
|
||||
args.Player.SendSuccessMessage(response);
|
||||
}
|
||||
catch (GroupManagerException ex)
|
||||
{
|
||||
args.Player.SendErrorMessage(ex.Message);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
return;
|
||||
case "del":
|
||||
#region Delete group
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ using MySql.Data.MySqlClient;
|
|||
|
||||
namespace TShockAPI.DB
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the GroupManager, which is in charge of group management.
|
||||
/// </summary>
|
||||
public class GroupManager : IEnumerable<Group>
|
||||
{
|
||||
private IDbConnection database;
|
||||
|
|
@ -36,17 +39,17 @@ namespace TShockAPI.DB
|
|||
database = db;
|
||||
|
||||
var table = new SqlTable("GroupList",
|
||||
new SqlColumn("GroupName", MySqlDbType.VarChar, 32) {Primary = true},
|
||||
new SqlColumn("Parent", MySqlDbType.VarChar, 32),
|
||||
new SqlColumn("Commands", MySqlDbType.Text),
|
||||
new SqlColumn("ChatColor", MySqlDbType.Text),
|
||||
new SqlColumn("Prefix", MySqlDbType.Text),
|
||||
new SqlColumn("Suffix", MySqlDbType.Text)
|
||||
);
|
||||
new SqlColumn("GroupName", MySqlDbType.VarChar, 32) { Primary = true },
|
||||
new SqlColumn("Parent", MySqlDbType.VarChar, 32),
|
||||
new SqlColumn("Commands", MySqlDbType.Text),
|
||||
new SqlColumn("ChatColor", MySqlDbType.Text),
|
||||
new SqlColumn("Prefix", MySqlDbType.Text),
|
||||
new SqlColumn("Suffix", MySqlDbType.Text)
|
||||
);
|
||||
var creator = new SqlTableCreator(db,
|
||||
db.GetSqlType() == SqlType.Sqlite
|
||||
? (IQueryBuilder) new SqliteQueryCreator()
|
||||
: new MysqlQueryCreator());
|
||||
db.GetSqlType() == SqlType.Sqlite
|
||||
? (IQueryBuilder)new SqliteQueryCreator()
|
||||
: new MysqlQueryCreator());
|
||||
if (creator.EnsureTableStructure(table))
|
||||
{
|
||||
// Add default groups if they don't exist
|
||||
|
|
@ -85,7 +88,11 @@ namespace TShockAPI.DB
|
|||
AddGroup(name, parent, permissions, Group.defaultChatColor);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the given group exists.
|
||||
/// </summary>
|
||||
/// <param name="group">The group.</param>
|
||||
/// <returns><c>true</c> if it does; otherwise, <c>false</c>.</returns>
|
||||
public bool GroupExists(string group)
|
||||
{
|
||||
if (group == "superadmin")
|
||||
|
|
@ -99,11 +106,20 @@ namespace TShockAPI.DB
|
|||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the enumerator.
|
||||
/// </summary>
|
||||
/// <returns>The enumerator.</returns>
|
||||
public IEnumerator<Group> GetEnumerator()
|
||||
{
|
||||
return groups.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the group matching the specified name.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <returns>The group.</returns>
|
||||
public Group GetGroupByName(string name)
|
||||
{
|
||||
var ret = groups.Where(g => g.Name == name);
|
||||
|
|
@ -139,8 +155,8 @@ namespace TShockAPI.DB
|
|||
}
|
||||
|
||||
string query = (TShock.Config.StorageType.ToLower() == "sqlite")
|
||||
? "INSERT OR IGNORE INTO GroupList (GroupName, Parent, Commands, ChatColor) VALUES (@0, @1, @2, @3);"
|
||||
: "INSERT IGNORE INTO GroupList SET GroupName=@0, Parent=@1, Commands=@2, ChatColor=@3";
|
||||
? "INSERT OR IGNORE INTO GroupList (GroupName, Parent, Commands, ChatColor) VALUES (@0, @1, @2, @3);"
|
||||
: "INSERT IGNORE INTO GroupList SET GroupName=@0, Parent=@1, Commands=@2, ChatColor=@3";
|
||||
if (database.Query(query, name, parentname, permissions, chatcolor) == 1)
|
||||
{
|
||||
groups.Add(group);
|
||||
|
|
@ -200,6 +216,70 @@ namespace TShockAPI.DB
|
|||
group.Suffix = suffix;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renames the specified group.
|
||||
/// </summary>
|
||||
/// <param name="name">The group's name.</param>
|
||||
/// <param name="newName">The new name.</param>
|
||||
/// <returns>The response.</returns>
|
||||
public String RenameGroup(string name, string newName)
|
||||
{
|
||||
if (!GroupExists(name))
|
||||
{
|
||||
throw new GroupNotExistException(name);
|
||||
}
|
||||
|
||||
if (GroupExists(newName))
|
||||
{
|
||||
throw new GroupExistsException(newName);
|
||||
}
|
||||
|
||||
if (database.Query("UPDATE GroupList SET GroupName = @0 WHERE GroupName = @1", newName, name) == 1)
|
||||
{
|
||||
var oldGroup = GetGroupByName(name);
|
||||
var newGroup = new Group(newName, oldGroup.Parent, oldGroup.ChatColor, oldGroup.Permissions)
|
||||
{
|
||||
Prefix = oldGroup.Prefix,
|
||||
Suffix = oldGroup.Suffix
|
||||
};
|
||||
|
||||
groups.Remove(oldGroup);
|
||||
groups.Add(newGroup);
|
||||
// We need to check if the old group has been referenced as a parent and update those references accordingly
|
||||
database.Query("UPDATE GroupList SET Parent = @0 WHERE Parent = @1", newName, name);
|
||||
foreach (var group in groups.Where(g => g.Parent != null && g.Parent == oldGroup))
|
||||
{
|
||||
group.Parent = newGroup;
|
||||
}
|
||||
|
||||
if (TShock.Config.DefaultGuestGroupName == oldGroup.Name)
|
||||
{
|
||||
TShock.Config.DefaultGuestGroupName = newGroup.Name;
|
||||
Group.DefaultGroup = newGroup;
|
||||
}
|
||||
if (TShock.Config.DefaultRegistrationGroupName == oldGroup.Name)
|
||||
{
|
||||
TShock.Config.DefaultRegistrationGroupName = newGroup.Name;
|
||||
}
|
||||
|
||||
TShock.Config.Write(FileTools.ConfigPath);
|
||||
database.Query("UPDATE Users SET Usergroup = @0 WHERE Usergroup = @1", newName, name);
|
||||
foreach (var player in TShock.Players.Where(p => p?.Group == oldGroup))
|
||||
{
|
||||
player.Group = newGroup;
|
||||
}
|
||||
return $"Group \"{name}\" has been renamed to \"{newName}\".";
|
||||
}
|
||||
|
||||
throw new GroupManagerException($"Failed to rename group \"{name}\".");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified group.
|
||||
/// </summary>
|
||||
/// <param name="name">The group's name.</param>
|
||||
/// <param name="exceptions">Whether exceptions will be thrown in case something goes wrong.</param>
|
||||
/// <returns></returns>
|
||||
public String DeleteGroup(String name, bool exceptions = false)
|
||||
{
|
||||
if (!GroupExists(name))
|
||||
|
|
@ -214,12 +294,18 @@ namespace TShockAPI.DB
|
|||
groups.Remove(TShock.Utils.GetGroup(name));
|
||||
return "Group " + name + " has been deleted successfully.";
|
||||
}
|
||||
else if (exceptions)
|
||||
throw new GroupManagerException("Failed to delete group '" + name + ".'");
|
||||
|
||||
return "";
|
||||
if (exceptions)
|
||||
throw new GroupManagerException("Failed to delete group '" + name + ".'");
|
||||
return "Failed to delete group '" + name + ".'";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates the given permission list and adds permissions for the specified group accordingly.
|
||||
/// </summary>
|
||||
/// <param name="name">The group name.</param>
|
||||
/// <param name="permissions">The permission list.</param>
|
||||
/// <returns></returns>
|
||||
public String AddPermissions(String name, List<String> permissions)
|
||||
{
|
||||
if (!GroupExists(name))
|
||||
|
|
@ -237,6 +323,12 @@ namespace TShockAPI.DB
|
|||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates the given permission list and removes valid permissions for the specified group accordingly.
|
||||
/// </summary>
|
||||
/// <param name="name">The group name.</param>
|
||||
/// <param name="permissions">The permission list.</param>
|
||||
/// <returns></returns>
|
||||
public String DeletePermissions(String name, List<String> permissions)
|
||||
{
|
||||
if (!GroupExists(name))
|
||||
|
|
@ -254,12 +346,15 @@ namespace TShockAPI.DB
|
|||
return "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates the group list and loads permissions for each group appropriately.
|
||||
/// </summary>
|
||||
public void LoadPermisions()
|
||||
{
|
||||
try
|
||||
{
|
||||
List<Group> newGroups = new List<Group>(groups.Count);
|
||||
Dictionary<string,string> newGroupParents = new Dictionary<string, string>(groups.Count);
|
||||
Dictionary<string, string> newGroupParents = new Dictionary<string, string>(groups.Count);
|
||||
using (var reader = database.QueryReader("SELECT * FROM GroupList"))
|
||||
{
|
||||
while (reader.Read())
|
||||
|
|
@ -271,7 +366,8 @@ namespace TShockAPI.DB
|
|||
continue;
|
||||
}
|
||||
|
||||
newGroups.Add(new Group(groupName, null, reader.Get<string>("ChatColor"), reader.Get<string>("Commands")) {
|
||||
newGroups.Add(new Group(groupName, null, reader.Get<string>("ChatColor"), reader.Get<string>("Commands"))
|
||||
{
|
||||
Prefix = reader.Get<string>("Prefix"),
|
||||
Suffix = reader.Get<string>("Suffix"),
|
||||
});
|
||||
|
|
@ -360,32 +456,60 @@ namespace TShockAPI.DB
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the base GroupManager exception.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class GroupManagerException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GroupManagerException"/> with the specified message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
public GroupManagerException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GroupManagerException"/> with the specified message and inner exception.
|
||||
/// </summary>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <param name="inner">The inner exception.</param>
|
||||
public GroupManagerException(string message, Exception inner)
|
||||
: base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the GroupExists exception.
|
||||
/// This exception is thrown whenever an attempt to add an existing group into the database is made.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class GroupExistsException : GroupManagerException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GroupExistsException"/> with the specified group name.
|
||||
/// </summary>
|
||||
/// <param name="name">The group name.</param>
|
||||
public GroupExistsException(string name)
|
||||
: base("Group '" + name + "' already exists")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the GroupNotExist exception.
|
||||
/// This exception is thrown whenever we try to access a group that does not exist.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class GroupNotExistException : GroupManagerException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GroupNotExistException"/> with the specified group name.
|
||||
/// </summary>
|
||||
/// <param name="name">The group name.</param>
|
||||
public GroupNotExistException(string name)
|
||||
: base("Group '" + name + "' does not exist")
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue