diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 8577fc89..f43aae1f 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -3210,10 +3210,9 @@ namespace TShockAPI { try { - TShock.Users.AddUser(new User("", "", "superadmin")); args.Player.Group = TShock.Utils.GetGroup("superadmin"); - args.Player.SendInfoMessage("This IP address is now superadmin. Please perform the following command:"); - args.Player.SendInfoMessage("/user add : superadmin"); + args.Player.SendInfoMessage("You are now superadmin, please do the following to finish your install:"); + args.Player.SendInfoMessage("/user add superadmin"); args.Player.SendInfoMessage("Creates: with the password as part of the superadmin group."); args.Player.SendInfoMessage("Please use /login to login from now on."); args.Player.SendInfoMessage("If you understand, please /login now, and type /auth-verify."); @@ -3229,9 +3228,7 @@ namespace TShockAPI if (args.Player.Group.Name == "superadmin") { args.Player.SendInfoMessage("Please disable the auth system! If you need help, consult the forums. http://tshock.co/"); - args.Player.SendInfoMessage("This IP address is now superadmin. Please perform the following command:"); - args.Player.SendInfoMessage("/user add : superadmin"); - args.Player.SendInfoMessage("Creates: with the password as part of the superadmin group."); + args.Player.SendInfoMessage("This account is superadmin, please do the following to finish your install:"); args.Player.SendInfoMessage("Please use /login to login from now on."); args.Player.SendInfoMessage("If you understand, please /login now, and type /auth-verify."); return; @@ -3250,15 +3247,6 @@ namespace TShockAPI return; } - if (!args.Player.IsLoggedIn) - { - args.Player.SendWarningMessage("You must be logged in to disable the auth system."); - args.Player.SendWarningMessage("This is a security measure designed to prevent insecure administration setups."); - args.Player.SendWarningMessage("Please re-run /auth and read the instructions!"); - args.Player.SendWarningMessage("If you're still confused, consult the forums: http://tshock.co/"); - return; - } - args.Player.SendSuccessMessage("Your new account has been verified, and the /auth system has been turned off."); args.Player.SendSuccessMessage("You can always use the /user command to manage players. Don't just delete the auth.lck."); args.Player.SendSuccessMessage("Thank you for using TShock! http://tshock.co/ & http://github.com/TShock/TShock"); diff --git a/TShockAPI/DB/GroupManager.cs b/TShockAPI/DB/GroupManager.cs index ab9fe61d..bd91f09b 100644 --- a/TShockAPI/DB/GroupManager.cs +++ b/TShockAPI/DB/GroupManager.cs @@ -53,13 +53,15 @@ namespace TShockAPI.DB LoadPermisions(); // Add default groups if they don't exist - AddDefaultGroup("guest", "", "canbuild,canregister,canlogin,canpartychat,cantalkinthird"); - AddDefaultGroup("default", "guest", "warp,canchangepassword"); + AddDefaultGroup(TShock.Config.DefaultGuestGroupName, "", "canbuild,canregister,canlogin,canpartychat,cantalkinthird"); + AddDefaultGroup("default", TShock.Config.DefaultGuestGroupName, "warp,canchangepassword"); AddDefaultGroup("newadmin", "default", "kick,editspawn,reservedslot"); AddDefaultGroup("admin", "newadmin", "ban,unban,whitelist,causeevents,spawnboss,spawnmob,managewarp,time,tp,pvpfun,kill,logs,immunetokick,tphere"); AddDefaultGroup("trustedadmin", "admin", "maintenance,cfg,butcher,item,heal,immunetoban,usebanneditem,manageusers"); AddDefaultGroup("vip", "default", "reservedslot"); + + Group.DefaultGroup = GetGroupByName(TShock.Config.DefaultGuestGroupName); } private void AddDefaultGroup(string name, string parent, string permissions) diff --git a/TShockAPI/DB/UserManager.cs b/TShockAPI/DB/UserManager.cs index 515bad6c..c8af324c 100644 --- a/TShockAPI/DB/UserManager.cs +++ b/TShockAPI/DB/UserManager.cs @@ -37,7 +37,9 @@ namespace TShockAPI.DB new SqlColumn("ID", MySqlDbType.Int32) {Primary = true, AutoIncrement = true}, new SqlColumn("Username", MySqlDbType.VarChar, 32) {Unique = true}, new SqlColumn("Password", MySqlDbType.VarChar, 128), - new SqlColumn("Usergroup", MySqlDbType.Text) + new SqlColumn("Usergroup", MySqlDbType.Text), + new SqlColumn("LastAccessed", MySqlDbType.Text), + new SqlColumn("KnownIPs", MySqlDbType.Text) ); var creator = new SqlTableCreator(db, db.GetSqlType() == SqlType.Sqlite @@ -92,7 +94,6 @@ namespace TShockAPI.DB } } - /// /// Sets the Hashed Password for a given username /// @@ -141,6 +142,19 @@ namespace TShockAPI.DB } } + public void UpdateLogin(User user) + { + try + { + if (database.Query("UPDATE Users SET LastAccessed = @0, KnownIps = @1 WHERE Username = @2;", DateTime.Now.ToString("G"), user.KnownIps, user.Name) == 0) + throw new UserNotExistException(user.Name); + } + catch (Exception ex) + { + throw new UserManagerException("UpdateLogin SQL returned an error", ex); + } + } + public int GetUserID(string username) { try @@ -254,6 +268,8 @@ namespace TShockAPI.DB user.Group = result.Get("Usergroup"); user.Password = result.Get("Password"); user.Name = result.Get("Username"); + user.LastAccessed = result.Get("LastAccessed"); + user.KnownIps = result.Get("KnownIps"); return user; } } @@ -264,12 +280,16 @@ namespace TShockAPI.DB public string Name { get; set; } public string Password { get; set; } public string Group { get; set; } + public string LastAccessed { get; set; } + public string KnownIps { get; set; } - public User(string name, string pass, string group) + public User(string name, string pass, string group, string last, string known) { Name = name; Password = pass; Group = group; + LastAccessed = last; + KnownIps = known; } public User() @@ -277,6 +297,8 @@ namespace TShockAPI.DB Name = ""; Password = ""; Group = ""; + LastAccessed = ""; + KnownIps = ""; } } diff --git a/TShockAPI/Group.cs b/TShockAPI/Group.cs index 50995b51..08a2aa9b 100644 --- a/TShockAPI/Group.cs +++ b/TShockAPI/Group.cs @@ -152,6 +152,7 @@ namespace TShockAPI public byte G = 255; public byte B = 255; + public static Group DefaultGroup = null; #if COMPAT_SIGS [Obsolete("This constructor is for signature compatibility for external code only")] public Group(string groupname, Group parentgroup, string chatcolor) diff --git a/TShockAPI/Rest/RestManager.cs b/TShockAPI/Rest/RestManager.cs index 67aca06a..1c170a88 100644 --- a/TShockAPI/Rest/RestManager.cs +++ b/TShockAPI/Rest/RestManager.cs @@ -307,7 +307,7 @@ namespace TShockAPI return RestMissingParam("password"); // NOTE: ip can be blank - User user = new User(username, password, group); + User user = new User(username, password, group, "", ""); try { TShock.Users.AddUser(user); diff --git a/TShockAPI/TSPlayer.cs b/TShockAPI/TSPlayer.cs index 824758dc..3dcfb24f 100644 --- a/TShockAPI/TSPlayer.cs +++ b/TShockAPI/TSPlayer.cs @@ -408,7 +408,7 @@ namespace TShockAPI TilesDestroyed = new Dictionary(); TilesCreated = new Dictionary(); Index = index; - Group = new Group(TShock.Config.DefaultGuestGroupName); + Group = Group.DefaultGroup; IceTiles = new List(); AwaitingResponse = new Dictionary>(); } @@ -419,7 +419,7 @@ namespace TShockAPI TilesCreated = new Dictionary(); Index = -1; FakePlayer = new Player {name = playerName, whoAmi = -1}; - Group = new Group(TShock.Config.DefaultGuestGroupName); + Group = Group.DefaultGroup; AwaitingResponse = new Dictionary>(); } diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 96643f4d..1b15f63e 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -24,12 +24,14 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; +using System.Linq; using System.Net; using System.Reflection; using Hooks; using MaxMind; using Mono.Data.Sqlite; using MySql.Data.MySqlClient; +using Newtonsoft.Json; using Rests; using Terraria; using TShockAPI.DB; @@ -248,6 +250,7 @@ namespace TShockAPI WorldHooks.SaveWorld += SaveManager.Instance.OnSaveWorld; WorldHooks.ChristmasCheck += OnXmasCheck; NetHooks.NameCollision += NetHooks_NameCollision; + TShockAPI.Hooks.PlayerHooks.PlayerPostLogin += OnPlayerLogin; GetDataHandlers.InitGetDataHandler(); Commands.InitCommands(); @@ -322,6 +325,7 @@ namespace TShockAPI WorldHooks.SaveWorld -= SaveManager.Instance.OnSaveWorld; WorldHooks.ChristmasCheck -= OnXmasCheck; NetHooks.NameCollision -= NetHooks_NameCollision; + TShockAPI.Hooks.PlayerHooks.PlayerPostLogin -= OnPlayerLogin; if (File.Exists(Path.Combine(SavePath, "tshock.pid"))) { @@ -334,7 +338,31 @@ namespace TShockAPI base.Dispose(disposing); } - void NetHooks_NameCollision(int who, string name, HandledEventArgs e) + private void OnPlayerLogin(Hooks.PlayerPostLoginEventArgs args) + { + User u = Users.GetUserByName(args.Player.UserAccountName); + List KnownIps = new List(); + if (!string.IsNullOrWhiteSpace(u.KnownIps)) + { + KnownIps = JsonConvert.DeserializeObject>(u.KnownIps); + } + + bool found = KnownIps.Any(s => s.Equals(args.Player.IP)); + if (!found) + { + if (KnownIps.Count == 100) + { + KnownIps.RemoveAt(0); + } + + KnownIps.Add(args.Player.IP); + } + + u.KnownIps = JsonConvert.SerializeObject(KnownIps, Formatting.Indented); + Users.UpdateLogin(u); + } + + private void NetHooks_NameCollision(int who, string name, HandledEventArgs e) { string ip = TShock.Utils.GetRealIP(Netplay.serverSock[who].tcpClient.Client.RemoteEndPoint.ToString()); foreach (TSPlayer ply in TShock.Players) @@ -365,7 +393,7 @@ namespace TShockAPI return; } - void OnXmasCheck(ChristmasCheckEventArgs args) + private void OnXmasCheck(ChristmasCheckEventArgs args) { if (args.Handled) return; diff --git a/TShockAPI/Utils.cs b/TShockAPI/Utils.cs index 4178130c..4d6cc106 100644 --- a/TShockAPI/Utils.cs +++ b/TShockAPI/Utils.cs @@ -741,7 +741,7 @@ namespace TShockAPI return TShock.Groups.groups[i]; } } - return new Group(TShock.Config.DefaultGuestGroupName); + return Group.DefaultGroup; } ///