Parents now implemented correctly as a separate column.

Negate permissions now work again.
This commit is contained in:
high 2011-08-17 17:19:56 -04:00
parent 1fa5fdcf04
commit f90b530531
2 changed files with 95 additions and 72 deletions

View file

@ -19,6 +19,7 @@ namespace TShockAPI.DB
var table = new SqlTable("GroupList", var table = new SqlTable("GroupList",
new SqlColumn("GroupName", MySqlDbType.VarChar, 32) { Primary = true }, new SqlColumn("GroupName", MySqlDbType.VarChar, 32) { Primary = true },
new SqlColumn("Parent", MySqlDbType.VarChar, 32),
new SqlColumn("Commands", MySqlDbType.Text), new SqlColumn("Commands", MySqlDbType.Text),
new SqlColumn("ChatColor", MySqlDbType.Text) new SqlColumn("ChatColor", MySqlDbType.Text)
); );
@ -26,11 +27,11 @@ namespace TShockAPI.DB
creator.EnsureExists(table); creator.EnsureExists(table);
//Add default groups //Add default groups
AddGroup("trustedadmin", "admin,maintenance,cfg,butcher,item,heal,immunetoban,ignorecheatdetection,ignoregriefdetection,usebanneditem,manageusers");
AddGroup("admin", "newadmin,ban,unban,whitelist,causeevents,spawnboss,spawnmob,managewarp,time,tp,pvpfun,kill,logs,immunetokick,tphere");
AddGroup("newadmin", "default,kick,editspawn,reservedslot");
AddGroup("default", "canwater,canlava,warp,canbuild"); AddGroup("default", "canwater,canlava,warp,canbuild");
AddGroup("vip", "default,canwater,canlava,warp,canbuild,reservedslot"); AddGroup("newadmin", "default", "kick,editspawn,reservedslot");
AddGroup("admin", "newadmin", "ban,unban,whitelist,causeevents,spawnboss,spawnmob,managewarp,time,tp,pvpfun,kill,logs,immunetokick,tphere");
AddGroup("trustedadmin", "admin", "maintenance,cfg,butcher,item,heal,immunetoban,ignorecheatdetection,ignoregriefdetection,usebanneditem,manageusers");
AddGroup("vip", "default", "canwater,canlava,warp,canbuild,reservedslot");
String file = Path.Combine(TShock.SavePath, "groups.txt"); String file = Path.Combine(TShock.SavePath, "groups.txt");
if (File.Exists(file)) if (File.Exists(file))
@ -81,37 +82,53 @@ namespace TShockAPI.DB
return true; return true;
foreach (Group g in groups) return groups.Any(g => g.Name.Equals(group));
{
if (g.Name.Equals(group))
return true;
}
return false;
} }
/// <summary> /// <summary>
/// Adds group with name and permissions if it does not exist. /// Adds group with name and permissions if it does not exist.
/// </summary> /// </summary>
/// <param name="name">name of group</param> /// <param name="name">name of group</param>
/// <param name="parentname">parent of group</param>
/// <param name="permissions">permissions</param> /// <param name="permissions">permissions</param>
public String AddGroup(String name, String permissions, String ChatColor = "255,255,255") public String AddGroup(String name, string parentname, String permissions, String chatcolor)
{ {
String message = ""; String message = "";
if (GroupExists(name)) if (GroupExists(name))
return "Error: Group already exists. Use /modGroup to change permissions."; return "Error: Group already exists. Use /modGroup to change permissions.";
var group = new Group(name, null, chatcolor);
group.permissions.Add(permissions);
if (!string.IsNullOrWhiteSpace(parentname))
{
var parent = groups.FirstOrDefault(gp => gp.Name == parentname);
if (parent == null)
{
var error = "Invalid parent {0} for group {1}".SFormat(group.Name, parentname);
Log.ConsoleError(error);
return error;
}
group.Parent = parent;
}
string query = (TShock.Config.StorageType.ToLower() == "sqlite") ? string query = (TShock.Config.StorageType.ToLower() == "sqlite") ?
"INSERT OR IGNORE INTO GroupList (GroupName, Commands, ChatColor) VALUES (@0, @1, @2);" : "INSERT OR IGNORE INTO GroupList (GroupName, Parent, Commands, ChatColor) VALUES (@0, @1, @2, @3);" :
"INSERT IGNORE INTO GroupList SET GroupName=@0, Commands=@1"; "INSERT IGNORE INTO GroupList SET GroupName=@0, Parent=@1, Commands=@1, ChatColor=@1";
if (database.Query(query, name, permissions, ChatColor) == 1) if (database.Query(query, name, parentname, permissions, chatcolor) == 1)
message = "Group " + name + " has been created successfully."; message = "Group " + name + " has been created successfully.";
Group g = new Group(name, null, ChatColor);
g.permissions.Add(permissions); groups.Add(group);
groups.Add(g);
return message; return message;
} }
public String AddGroup(String name, String permissions)
{
return AddGroup(name, "", permissions, "255,255,255");
}
public String AddGroup(String name, string parent, String permissions)
{
return AddGroup(name, parent, permissions, "255,255,255");
}
public String DeleteGroup(String name) public String DeleteGroup(String name)
{ {
@ -161,24 +178,36 @@ namespace TShockAPI.DB
public void LoadPermisions() public void LoadPermisions()
{ {
groups = new List<Group>(); //Create a temporary list so if there is an error it doesn't override the currently loaded groups with broken groups.
groups.Add(new SuperAdminGroup()); var tempgroups = new List<Group>();
tempgroups.Add(new SuperAdminGroup());
if (groups == null || groups.Count < 2)
groups = tempgroups;
try try
{ {
var groupsparents = new List<Tuple<Group, string>>();
using (var reader = database.QueryReader("SELECT * FROM GroupList")) using (var reader = database.QueryReader("SELECT * FROM GroupList"))
{ {
while (reader.Read()) while (reader.Read())
{ {
Group group = null;
string groupname = reader.Get<String>("GroupName"); string groupname = reader.Get<String>("GroupName");
group = new Group(groupname); var group = new Group(groupname);
//Inherit Given commands //Inherit Given commands
String[] commands = reader.Get<String>("Commands").Split(','); String[] commands = reader.Get<String>("Commands").Split(',');
for (int i = 0; i < commands.Length; i++) foreach (var t in commands)
{ {
group.AddPermission(commands[i].Trim()); var str = t.Trim();
if (str.StartsWith("!"))
{
group.NegatePermission(str.Substring(1));
}
else
{
group.AddPermission(str);
}
} }
String[] chatcolour = (reader.Get<String>("ChatColor") ?? "").Split(','); String[] chatcolour = (reader.Get<String>("ChatColor") ?? "").Split(',');
if (chatcolour.Length == 3) if (chatcolour.Length == 3)
@ -187,9 +216,30 @@ namespace TShockAPI.DB
byte.TryParse(chatcolour[1], out group.G); byte.TryParse(chatcolour[1], out group.G);
byte.TryParse(chatcolour[2], out group.B); byte.TryParse(chatcolour[2], out group.B);
} }
groups.Add(group);
groupsparents.Add(Tuple.Create(group, reader.Get<string>("Parent")));
} }
} }
foreach (var t in groupsparents)
{
var group = t.Item1;
var parentname = t.Item2;
if (!string.IsNullOrWhiteSpace(parentname))
{
var parent = groupsparents.FirstOrDefault(gp => gp.Item1.Name == parentname);
if (parent == null)
{
Log.ConsoleError("Invalid parent {0} for group {1}".SFormat(group.Name, parentname));
return;
}
group.Parent = parent.Item1;
}
tempgroups.Add(group);
}
groups = tempgroups;
} }
catch (Exception ex) catch (Exception ex)
{ {

View file

@ -23,44 +23,43 @@ namespace TShockAPI
public class Group public class Group
{ {
public readonly List<string> permissions = new List<string>(); public readonly List<string> permissions = new List<string>();
private readonly List<string> negatedpermissions = new List<string>(); public readonly List<string> negatedpermissions = new List<string>();
public string Name { get; protected set; } public string Name { get; set; }
public Group Parent { get; protected set; } public Group Parent { get; set; }
public int Order { get; set; } public int Order { get; set; }
public byte R = 255; public byte R = 255;
public byte G = 255; public byte G = 255;
public byte B = 255; public byte B = 255;
public Group(string groupname, Group parentgroup = null, string ChatColor = "255,255,255") public Group(string groupname, Group parentgroup = null, string chatcolor = "255,255,255")
{ {
Name = groupname; Name = groupname;
Parent = parentgroup; Parent = parentgroup;
byte.TryParse(ChatColor.Split(',')[0], out R); byte.TryParse(chatcolor.Split(',')[0], out R);
byte.TryParse(ChatColor.Split(',')[1], out G); byte.TryParse(chatcolor.Split(',')[1], out G);
byte.TryParse(ChatColor.Split(',')[2], out B); byte.TryParse(chatcolor.Split(',')[2], out B);
} }
public virtual bool HasPermission(string permission) public virtual bool HasPermission(string permission)
{ {
if (string.IsNullOrEmpty(permission)) var cur = this;
return true; var traversed = new List<Group>();
if (negatedpermissions.Contains(permission)) while (cur != null)
return false;
if (permissions.Contains(permission))
return true;
if (Parent != null)
return Parent.HasPermission(permission);
bool ret = false;
foreach( string g in permissions )
{ {
if (TShock.Groups.GroupExists(g)) if (string.IsNullOrEmpty(permission))
return true;
if (cur.negatedpermissions.Contains(permission))
return false;
if (cur.permissions.Contains(permission))
return true;
if (traversed.Contains(cur))
{ {
ret = checkGroupForPermission(g, permission); throw new Exception("Infinite group parenting ({0})".SFormat(cur.Name));
if (ret)
return true;
} }
traversed.Add(cur);
cur = cur.Parent;
} }
return false; return false;
} }
@ -74,32 +73,6 @@ namespace TShockAPI
{ {
permissions.Add(permission); permissions.Add(permission);
} }
private bool checkGroupForPermission(String g, String permission )
{
bool ret = false;
if( !TShock.Groups.GroupExists( g ) )
{
if( g.Equals(permission) )
return true;
}
else
{
Group group = Tools.GetGroup(g);
foreach (String perm in group.permissions)
{
if( perm.Equals( permission ) )
{
return true;
}
ret = checkGroupForPermission( perm, permission );
if( ret )
return ret;
}
}
return ret;
}
} }
public class SuperAdminGroup : Group public class SuperAdminGroup : Group