diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 1d966e79..99cb7bbc 100755 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -323,6 +323,8 @@ namespace TShockAPI } } + //Todo: Add separate help text for '/user add' and '/user del'. Also add '/user addip' and '/user delip' + private static void ManageUsers(CommandArgs args) { if (args.Parameters.Count < 2) @@ -331,66 +333,76 @@ namespace TShockAPI args.Player.SendMessage("Note: Passwords are stored with SHA512 hashing. To reset a user's password, remove and re-add them."); return; } - if (args.Parameters[0] == "add" && args.Parameters.Count > 2) + + string subcmd = args.Parameters[0]; + + if (subcmd == "add") + { + var namepass = args.Parameters[1].Split(':'); + var user = new User(); + + try { - int returnval = 0; - if (args.Parameters[1].Split(':').Length == 2) + if (args.Parameters.Count > 2) { - if ((returnval = TShock.Users.AddUser("", args.Parameters[1].Split(':')[0], args.Parameters[1].Split(':')[1], args.Parameters[2])) == 1) + if (namepass.Length == 2) { - args.Player.SendMessage("Account " + args.Parameters[1].Split(':')[0] + " has been added to group " + args.Parameters[2] + "!", Color.Green); - Log.ConsoleInfo(args.Player.Name + " added Account " + args.Parameters[1].Split(':')[0] + " to group " + args.Parameters[2]); + user.Name = namepass[0]; + user.Password = namepass[1]; + user.Group = args.Parameters[2]; } - else if (returnval == 2) - args.Player.SendMessage("Invalid Group", Color.Green); - else - args.Player.SendMessage("Could not add user", Color.Green); - return; - } - else if (args.Parameters[1].Split(':').Length == 1) - { - if ((returnval = TShock.Users.AddUser(args.Parameters[1], args.Parameters[1], "null", args.Parameters[2])) == 1) + else if (namepass.Length == 1) + { + user.Address = namepass[0]; + user.Group = args.Parameters[2]; + } + if (!string.IsNullOrEmpty(user.Address)) { args.Player.SendMessage("IP address admin added. If they're logged in, tell them to rejoin.", Color.Green); args.Player.SendMessage("WARNING: This is insecure! It would be better to use a user account instead.", Color.Red); - Log.ConsoleInfo(args.Player.Name + " added IP " + args.Parameters[1] + " to group " + args.Parameters[2]); + Log.ConsoleInfo(args.Player.Name + " added IP " + user.Address + " to group " + user.Group); } - else if (returnval == 2) - args.Player.SendMessage("Invalid Group", Color.Green); else - args.Player.SendMessage("Could not add user", Color.Green); - return; + { + args.Player.SendMessage("Account " + user.Name + " has been added to group " + user.Group + "!", Color.Green); + Log.ConsoleInfo(args.Player.Name + " added Account " + user.Name + " to group " + user.Group); + } } - args.Player.SendMessage("Invalid syntax. Try /user help.", Color.Red); - }else if (args.Parameters[0] == "del" && args.Parameters.Count == 2) - { - if (args.Parameters[1].Contains(".")) + else { - //If this isn't an IP, well... - if (TShock.Users.RemoveUser(args.Parameters[1], true) == 1) - { - args.Player.SendMessage("IP removed successfully.", Color.Green); - Log.ConsoleInfo(args.Player.Name + " successfully deleted ip: " + args.Parameters[1]); - } - else - { - args.Player.SendMessage("IP wasn't removed. Was it invalid?", Color.Red); - Log.ConsoleInfo(args.Player.Name + " failed deleting invalid ip: " + args.Parameters[1]); - } - } else - { - if (TShock.Users.RemoveUser(args.Parameters[1], false) == 1) - { - args.Player.SendMessage("Account removed successfully.", Color.Green); - Log.ConsoleInfo(args.Player.Name + " successfully deleted account: " + args.Parameters[1]); - } - else - { - args.Player.SendMessage("Account wasn't removed. Was it invalid?", Color.Red); - Log.ConsoleInfo(args.Player.Name + " failed deleting invalid account: " + args.Parameters[1]); - } + args.Player.SendMessage("Invalid syntax. Try /user help.", Color.Red); } } + catch (UserManagerException ex) + { + args.Player.SendMessage(ex.Message, Color.Green); + Log.ConsoleError(ex.ToString()); + } + } + else if (subcmd == "del" && args.Parameters.Count == 2) + { + var user = new User(); + if (args.Parameters[1].Contains(".")) + user.Address = args.Parameters[1]; + else + user.Name = args.Parameters[1]; + + try + { + TShock.Users.RemoveUser(user); + args.Player.SendMessage("Account removed successfully.", Color.Green); + Log.ConsoleInfo(args.Player.Name + " successfully deleted account: " + args.Parameters[1]); + } + catch (UserManagerException ex) + { + args.Player.SendMessage(ex.Message, Color.Red); + Log.ConsoleError(ex.ToString()); + } + } + else + { + args.Player.SendMessage("Invalid syntax. Try /user help.", Color.Red); + } } #endregion @@ -418,7 +430,7 @@ namespace TShockAPI { args.Player.SendMessage("Invalid player.", Color.Red); } - } + } private static void Kick(CommandArgs args) { @@ -1383,7 +1395,7 @@ namespace TShockAPI { string playerName = args.Parameters[1]; string regionName = ""; - string playerID = "0"; + User playerID; for (int i = 2; i < args.Parameters.Count; i++) { @@ -1396,7 +1408,7 @@ namespace TShockAPI regionName = regionName + " " + args.Parameters[i]; } } - if ((playerID = TShock.Users.GetUserID(Tools.FindPlayer(playerName)[0].UserName)) != "0") + if ((playerID = TShock.Users.GetUserByName(Tools.FindPlayer(playerName)[0].UserName)) != null) { if (TShock.Regions.AddNewUser(regionName, playerID)) { @@ -1405,7 +1417,7 @@ namespace TShockAPI else args.Player.SendMessage("Region " + regionName + " not found", Color.Red); } - else if ((playerID = TShock.Users.GetUserID("",Tools.FindPlayer(playerName)[0].IP)) != "0") + else if ((playerID = TShock.Users.GetUserByIP(Tools.FindPlayer(playerName)[0].IP)) != null) { if (TShock.Regions.AddNewUser(regionName, playerID)) { @@ -1534,13 +1546,21 @@ namespace TShockAPI int givenCode = Convert.ToInt32(args.Parameters[0]); if (givenCode == TShock.AuthToken && args.Player.Group.Name != "superadmin") { - TShock.Users.AddUser(args.Player.IP,"","","superadmin"); - args.Player.Group = Tools.GetGroup("superadmin"); - args.Player.SendMessage("This IP address is now superadmin. Please perform the following command:"); - args.Player.SendMessage("/user add : superadmin"); - args.Player.SendMessage("Creates: with the password as part of the superadmin group."); - args.Player.SendMessage("Please use /login to login from now on."); - args.Player.SendMessage("If you understand, please /login now, and type /auth-verify"); + try + { + TShock.Users.AddUser(new User(args.Player.IP, "", "", "superadmin")); + args.Player.Group = Tools.GetGroup("superadmin"); + args.Player.SendMessage("This IP address is now superadmin. Please perform the following command:"); + args.Player.SendMessage("/user add : superadmin"); + args.Player.SendMessage("Creates: with the password as part of the superadmin group."); + args.Player.SendMessage("Please use /login to login from now on."); + args.Player.SendMessage("If you understand, please /login now, and type /auth-verify"); + } + catch (UserManagerException ex) + { + Log.ConsoleError(ex.ToString()); + args.Player.SendMessage(ex.Message); + } return; } diff --git a/TShockAPI/ConfigFile.cs b/TShockAPI/ConfigFile.cs index 3125a4df..9c93f6b0 100644 --- a/TShockAPI/ConfigFile.cs +++ b/TShockAPI/ConfigFile.cs @@ -77,9 +77,8 @@ namespace TShockAPI /// public string StorageType = "sqlite"; - public string MySqlHost = "localhost"; + public string MySqlHost = "localhost:3306"; public string MySqlDbName = ""; - public string MySqlPort = "3306"; public string MySqlUsername = ""; public string MySqlPassword = ""; diff --git a/TShockAPI/DB/RegionManager.cs b/TShockAPI/DB/RegionManager.cs index 7810f6ff..9fc37278 100644 --- a/TShockAPI/DB/RegionManager.cs +++ b/TShockAPI/DB/RegionManager.cs @@ -109,7 +109,7 @@ namespace TShockAPI.DB { com.CommandText = "UPDATE Regions SET Protected=@bool WHERE RegionName=@name WorldID=@worldid"; com.AddParameter("@name", name); - if (state) + if (state) com.AddParameter("@bool", 1); else com.AddParameter("@bool", 0); @@ -127,7 +127,7 @@ namespace TShockAPI.DB } } - public bool InProtectedArea(int X, int Y, string ID) + public bool InProtectedArea(int X, int Y, User user) { try { @@ -154,7 +154,7 @@ namespace TShockAPI.DB Y <= Y2 && Protected == 1) { - if (!SplitIDs.Contains(ID)) + if (!SplitIDs.Contains(user.ID.ToString())) return true; } } @@ -191,7 +191,7 @@ namespace TShockAPI.DB return SplitIDs; } - public bool AddNewUser(string regionName, string ID) + public bool AddNewUser(string regionName, User user) { string MergedIDs = string.Empty; @@ -206,23 +206,17 @@ namespace TShockAPI.DB using (var reader = com.ExecuteReader()) { if (reader.Read()) - { MergedIDs = reader.Get("UserIds"); - } - reader.Close(); } if (MergedIDs == string.Empty) - MergedIDs = ID; + MergedIDs = user.ID.ToString(); else - MergedIDs = MergedIDs + "," + ID; + MergedIDs = MergedIDs + "," + user.ID; com.CommandText = "UPDATE Regions SET UserIds=@ids"; com.AddParameter("@ids", MergedIDs); - if (com.ExecuteNonQuery() > 0) - return true; - else - return false; + return (com.ExecuteNonQuery() > 0); } } catch (Exception ex) diff --git a/TShockAPI/DB/UserManager.cs b/TShockAPI/DB/UserManager.cs index a1ca1d09..14af0682 100644 --- a/TShockAPI/DB/UserManager.cs +++ b/TShockAPI/DB/UserManager.cs @@ -27,7 +27,7 @@ using Community.CsharpSqlite.SQLiteClient; namespace TShockAPI.DB { public class UserManager - { + { private IDbConnection database; public UserManager(IDbConnection db) @@ -38,94 +38,72 @@ namespace TShockAPI.DB { if (TShock.Config.StorageType.ToLower() == "sqlite") com.CommandText = - "CREATE TABLE IF NOT EXISTS 'Users' ('Username' TEXT PRIMARY KEY, 'Password' TEXT, 'UserGroup' TEXT, 'IP' TEXT);"; + "CREATE TABLE IF NOT EXISTS 'Users' ('ID' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, 'Username' VARCHAR(32) UNIQUE, 'Password' VARCHAR(64), 'Usergroup' TEXT, 'IP' VARCHAR(15));"; else if (TShock.Config.StorageType.ToLower() == "mysql") com.CommandText = - "CREATE TABLE IF NOT EXISTS Users (Username VARCHAR(255) PRIMARY, Password VARCHAR(255), UserGroup VARCHAR(255), IP VARCHAR(255));"; - + "CREATE TABLE IF NOT EXISTS Users (ID INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, Username VARCHAR(32) UNIQUE, Password VARCHAR(64), Usergroup VARCHAR(255), IP VARCHAR(15));"; + com.ExecuteNonQuery(); } } - public int AddUser(string ip = "" , string name = "", string password = "", string group = "default") //I LOVE HOW THIS IS COMPLETELY NOT THE FORMAT FOR, YOU KNOW, THE DB + + public void AddUser(User user) { try { using (var com = database.CreateCommand()) { com.CommandText = "INSERT INTO Users (Username, Password, UserGroup, IP) VALUES (@name, @password, @group, @ip);"; - com.AddParameter("@name", name.ToLower()); - com.AddParameter("@password", Tools.HashPassword(password)); + com.AddParameter("@name", user.Name); + com.AddParameter("@password", Tools.HashPassword(user.Password)); - if(TShock.Groups.GroupExists(group)) - com.AddParameter("@group", group); - else - //Return code 2 (Group not exist) - return 2; + if (!TShock.Groups.GroupExists(user.Group)) + throw new GroupNotExistsException(user.Group); - com.AddParameter("@ip", ip); + com.AddParameter("@group", user.Group); + com.AddParameter("@ip", user.Address); using (var reader = com.ExecuteReader()) { - if (reader.RecordsAffected > 0) - { - //Return code 1 (User added) - return 1; - } - else - { - //Return code 0 (Add failed) - return 0; - } - } - } - } - catch (Exception ex) - { - //Return code 0 (Add failed) - Log.ConsoleError("AddUser SQL returned an error: " + ex.ToString()); - return 0; - } - } - - public int RemoveUser(string inputUser, bool ip) - { - try - { - using (var com = database.CreateCommand()) - { - if (ip) - { - com.CommandText = "DELETE FROM Users WHERE IP=@ip"; - com.AddParameter("@ip", inputUser.ToLower()); - } else - { - com.CommandText = "DELETE FROM Users WHERE Username=@name"; - com.AddParameter("@name", inputUser.ToLower()); - } - - using (var reader = com.ExecuteReader()) - { - if (reader.RecordsAffected > 0) - { - //Return code 1 (User removed) - reader.Close(); - return 1; - } - else - { - //Return code 0 (Remove failed) - reader.Close(); - return 0; - } + if (reader.RecordsAffected < 1) + throw new UserExistsException(user.Name); } } } catch (Exception ex) { - //Return code 0 (Remove failed) - Log.ConsoleError("RemoveUser SQL returned an error: " + ex.ToString()); - return 0; + throw new UserManagerException("AddUser SQL returned an error", ex); + } + } + + public void RemoveUser(User user) + { + try + { + using (var com = database.CreateCommand()) + { + if (!string.IsNullOrEmpty(user.Address)) + { + com.CommandText = "DELETE FROM Users WHERE IP=@ip"; + com.AddParameter("@ip", user.Address); + } + else + { + com.CommandText = "DELETE FROM Users WHERE Username=@name"; + com.AddParameter("@name", user.Name); + } + + using (var reader = com.ExecuteReader()) + { + if (reader.RecordsAffected < 1) + throw new UserNotExistException(string.IsNullOrEmpty(user.Address) ? user.Name : user.Address); + } + } + } + catch (Exception ex) + { + throw new UserManagerException("RemoveUser SQL returned an error", ex); } } @@ -183,7 +161,6 @@ namespace TShockAPI.DB string group = reader.Get("UserGroup"); return Tools.GetGroup(group); } - reader.Close(); } } } @@ -193,42 +170,122 @@ namespace TShockAPI.DB } return Tools.GetGroup("default"); } + public User GetUserByName(string name) + { + try + { + return GetUser(new User { Name = name }); + } + catch (UserManagerException) + { + return null; + } + } + public User GetUserByIP(string ip) + { + try + { + return GetUser(new User { Address = ip }); + } + catch (UserManagerException) + { + return null; + } + } - public string GetUserID(string username = "", string IP = "") + public User GetUser(User user) { try { using (var com = database.CreateCommand()) { - if (username != "" && username != null) + if (string.IsNullOrEmpty(user.Address)) { com.CommandText = "SELECT * FROM Users WHERE Username=@name"; - com.AddParameter("@name", username); - } - else if (IP != "" && IP != null) - { - com.CommandText = "SELECT * FROM Users WHERE IP=@ip"; - com.AddParameter("@ip", IP); + com.AddParameter("@name", user.Name); } else - return "0"; + { + com.CommandText = "SELECT * FROM Users WHERE IP=@ip"; + com.AddParameter("@ip", user.Address); + } using (var reader = com.ExecuteReader()) { if (reader.Read()) { - string ID = reader.Get("ID"); - return ID; + user.ID = reader.Get("ID"); + user.Group = reader.Get("Usergroup"); + return user; } - reader.Close(); } } } catch (Exception ex) { - Log.ConsoleError("GetUserID SQL returned an error: " + ex.ToString()); + throw new UserManagerException("GetUserID SQL returned an error", ex); } - return "0"; + throw new UserNotExistException(string.IsNullOrEmpty(user.Address) ? user.Name : user.Address); + } + } + + public class User + { + public int ID { get; set; } + public string Name { get; set; } + public string Password { get; set; } + public string Group { get; set; } + public string Address { get; set; } + + public User(string ip, string name, string pass, string group) + { + Address = ip; + Name = name; + Password = pass; + Group = group; + } + public User() + { + Address = ""; + Name = ""; + Password = ""; + Group = ""; + } + } + + public class UserManagerException : Exception + { + public UserManagerException(string message) + : base(message) + { + + } + public UserManagerException(string message, Exception inner) + : base(message, inner) + { + + } + } + public class UserExistsException : UserManagerException + { + public UserExistsException(string name) + : base("User '" + name + "' already exists") + { + } + } + public class UserNotExistException : UserManagerException + { + public UserNotExistException(string name) + : base("User '" + name + "' does not exist") + { + } + } + + public class GroupNotExistsException : UserManagerException + { + public GroupNotExistsException(string group) + : base("Group '" + group + "' does not exist") + { } } } diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index c6f8295d..632d81e1 100755 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -278,7 +278,7 @@ namespace TShockAPI return true; } } - if (!args.Player.Group.HasPermission("editspawn") && TShock.Regions.InProtectedArea(x, y, TShock.Users.GetUserID(args.Player.UserName,args.Player.IP))) + if (!args.Player.Group.HasPermission("editspawn") && TShock.Regions.InProtectedArea(x, y, TShock.Users.GetUserByIP(args.Player.IP))) { if ((DateTime.UtcNow - args.Player.LastTileChangeNotify).TotalMilliseconds > 1000) { @@ -537,7 +537,7 @@ namespace TShockAPI args.Player.SendTileSquare(tilex, tiley); return true; } - if (!args.Player.Group.HasPermission("editspawn") && TShock.Regions.InProtectedArea(tilex, tiley, Tools.GetPlayerIP(args.Player.Name))) + if (!args.Player.Group.HasPermission("editspawn") && TShock.Regions.InProtectedArea(tilex, tiley, TShock.Users.GetUserByName(args.Player.Name))) { args.Player.SendMessage("Region protected from changes.", Color.Red); args.Player.SendTileSquare(tilex, tiley); diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 0aa05e28..b14ca2c5 100755 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -143,13 +143,15 @@ namespace TShockAPI { try { + var hostport = Config.MySqlHost.Split(':'); DB = new MySqlConnection(); - DB.ConnectionString = - "Server='" + Config.MySqlHost + - "';Port='" + Config.MySqlPort + - "';Database='" + Config.MySqlDbName + - "';Uid='" + Config.MySqlUsername + - "';Pwd='" + Config.MySqlPassword + "';"; + DB.ConnectionString = String.Format("Server='{0}'; Port='{1}'; Database='{2}'; Uid='{3}'; Pwd='{4}';", + hostport[0], + hostport.Length > 1 ? hostport[1] : "3306", + Config.MySqlDbName, + Config.MySqlUsername, + Config.MySqlPassword + ); DB.Open(); } catch (MySqlException ex)