Merge pull request #530 from Olink/general-devel

Added LastAccessed time field and KnownIPs field to the user database. Note: extent of testing was starting TShock again, so may have broken something important (e.g. stat tracking)
This commit is contained in:
Lucas Nicodemus 2013-09-21 18:04:39 -07:00
commit 222042cc4d
8 changed files with 67 additions and 26 deletions

View file

@ -3210,10 +3210,9 @@ namespace TShockAPI
{ {
try try
{ {
TShock.Users.AddUser(new User("", "", "superadmin"));
args.Player.Group = TShock.Utils.GetGroup("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("You are now superadmin, please do the following to finish your install:");
args.Player.SendInfoMessage("/user add <username>:<password> superadmin"); args.Player.SendInfoMessage("/user add <username> <password> superadmin");
args.Player.SendInfoMessage("Creates: <username> with the password <password> as part of the superadmin group."); args.Player.SendInfoMessage("Creates: <username> with the password <password> as part of the superadmin group.");
args.Player.SendInfoMessage("Please use /login <username> <password> to login from now on."); args.Player.SendInfoMessage("Please use /login <username> <password> to login from now on.");
args.Player.SendInfoMessage("If you understand, please /login <username> <password> now, and type /auth-verify."); args.Player.SendInfoMessage("If you understand, please /login <username> <password> now, and type /auth-verify.");
@ -3229,9 +3228,7 @@ namespace TShockAPI
if (args.Player.Group.Name == "superadmin") 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("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("This account is superadmin, please do the following to finish your install:");
args.Player.SendInfoMessage("/user add <username>:<password> superadmin");
args.Player.SendInfoMessage("Creates: <username> with the password <password> as part of the superadmin group.");
args.Player.SendInfoMessage("Please use /login <username> <password> to login from now on."); args.Player.SendInfoMessage("Please use /login <username> <password> to login from now on.");
args.Player.SendInfoMessage("If you understand, please /login <username> <password> now, and type /auth-verify."); args.Player.SendInfoMessage("If you understand, please /login <username> <password> now, and type /auth-verify.");
return; return;
@ -3250,15 +3247,6 @@ namespace TShockAPI
return; 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("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("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"); args.Player.SendSuccessMessage("Thank you for using TShock! http://tshock.co/ & http://github.com/TShock/TShock");

View file

@ -53,13 +53,15 @@ namespace TShockAPI.DB
LoadPermisions(); LoadPermisions();
// Add default groups if they don't exist // Add default groups if they don't exist
AddDefaultGroup("guest", "", "canbuild,canregister,canlogin,canpartychat,cantalkinthird"); AddDefaultGroup(TShock.Config.DefaultGuestGroupName, "", "canbuild,canregister,canlogin,canpartychat,cantalkinthird");
AddDefaultGroup("default", "guest", "warp,canchangepassword"); AddDefaultGroup("default", TShock.Config.DefaultGuestGroupName, "warp,canchangepassword");
AddDefaultGroup("newadmin", "default", "kick,editspawn,reservedslot"); AddDefaultGroup("newadmin", "default", "kick,editspawn,reservedslot");
AddDefaultGroup("admin", "newadmin", AddDefaultGroup("admin", "newadmin",
"ban,unban,whitelist,causeevents,spawnboss,spawnmob,managewarp,time,tp,pvpfun,kill,logs,immunetokick,tphere"); "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("trustedadmin", "admin", "maintenance,cfg,butcher,item,heal,immunetoban,usebanneditem,manageusers");
AddDefaultGroup("vip", "default", "reservedslot"); AddDefaultGroup("vip", "default", "reservedslot");
Group.DefaultGroup = GetGroupByName(TShock.Config.DefaultGuestGroupName);
} }
private void AddDefaultGroup(string name, string parent, string permissions) private void AddDefaultGroup(string name, string parent, string permissions)

View file

@ -37,7 +37,9 @@ namespace TShockAPI.DB
new SqlColumn("ID", MySqlDbType.Int32) {Primary = true, AutoIncrement = true}, new SqlColumn("ID", MySqlDbType.Int32) {Primary = true, AutoIncrement = true},
new SqlColumn("Username", MySqlDbType.VarChar, 32) {Unique = true}, new SqlColumn("Username", MySqlDbType.VarChar, 32) {Unique = true},
new SqlColumn("Password", MySqlDbType.VarChar, 128), 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, var creator = new SqlTableCreator(db,
db.GetSqlType() == SqlType.Sqlite db.GetSqlType() == SqlType.Sqlite
@ -92,7 +94,6 @@ namespace TShockAPI.DB
} }
} }
/// <summary> /// <summary>
/// Sets the Hashed Password for a given username /// Sets the Hashed Password for a given username
/// </summary> /// </summary>
@ -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) public int GetUserID(string username)
{ {
try try
@ -254,6 +268,8 @@ namespace TShockAPI.DB
user.Group = result.Get<string>("Usergroup"); user.Group = result.Get<string>("Usergroup");
user.Password = result.Get<string>("Password"); user.Password = result.Get<string>("Password");
user.Name = result.Get<string>("Username"); user.Name = result.Get<string>("Username");
user.LastAccessed = result.Get<string>("LastAccessed");
user.KnownIps = result.Get<string>("KnownIps");
return user; return user;
} }
} }
@ -264,12 +280,16 @@ namespace TShockAPI.DB
public string Name { get; set; } public string Name { get; set; }
public string Password { get; set; } public string Password { get; set; }
public string Group { 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; Name = name;
Password = pass; Password = pass;
Group = group; Group = group;
LastAccessed = last;
KnownIps = known;
} }
public User() public User()
@ -277,6 +297,8 @@ namespace TShockAPI.DB
Name = ""; Name = "";
Password = ""; Password = "";
Group = ""; Group = "";
LastAccessed = "";
KnownIps = "";
} }
} }

View file

@ -152,6 +152,7 @@ namespace TShockAPI
public byte G = 255; public byte G = 255;
public byte B = 255; public byte B = 255;
public static Group DefaultGroup = null;
#if COMPAT_SIGS #if COMPAT_SIGS
[Obsolete("This constructor is for signature compatibility for external code only")] [Obsolete("This constructor is for signature compatibility for external code only")]
public Group(string groupname, Group parentgroup, string chatcolor) public Group(string groupname, Group parentgroup, string chatcolor)

View file

@ -307,7 +307,7 @@ namespace TShockAPI
return RestMissingParam("password"); return RestMissingParam("password");
// NOTE: ip can be blank // NOTE: ip can be blank
User user = new User(username, password, group); User user = new User(username, password, group, "", "");
try try
{ {
TShock.Users.AddUser(user); TShock.Users.AddUser(user);

View file

@ -408,7 +408,7 @@ namespace TShockAPI
TilesDestroyed = new Dictionary<Vector2, TileData>(); TilesDestroyed = new Dictionary<Vector2, TileData>();
TilesCreated = new Dictionary<Vector2, TileData>(); TilesCreated = new Dictionary<Vector2, TileData>();
Index = index; Index = index;
Group = new Group(TShock.Config.DefaultGuestGroupName); Group = Group.DefaultGroup;
IceTiles = new List<Point>(); IceTiles = new List<Point>();
AwaitingResponse = new Dictionary<string, Action<object>>(); AwaitingResponse = new Dictionary<string, Action<object>>();
} }
@ -419,7 +419,7 @@ namespace TShockAPI
TilesCreated = new Dictionary<Vector2, TileData>(); TilesCreated = new Dictionary<Vector2, TileData>();
Index = -1; Index = -1;
FakePlayer = new Player {name = playerName, whoAmi = -1}; FakePlayer = new Player {name = playerName, whoAmi = -1};
Group = new Group(TShock.Config.DefaultGuestGroupName); Group = Group.DefaultGroup;
AwaitingResponse = new Dictionary<string, Action<object>>(); AwaitingResponse = new Dictionary<string, Action<object>>();
} }

View file

@ -24,12 +24,14 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq;
using System.Net; using System.Net;
using System.Reflection; using System.Reflection;
using Hooks; using Hooks;
using MaxMind; using MaxMind;
using Mono.Data.Sqlite; using Mono.Data.Sqlite;
using MySql.Data.MySqlClient; using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using Rests; using Rests;
using Terraria; using Terraria;
using TShockAPI.DB; using TShockAPI.DB;
@ -248,6 +250,7 @@ namespace TShockAPI
WorldHooks.SaveWorld += SaveManager.Instance.OnSaveWorld; WorldHooks.SaveWorld += SaveManager.Instance.OnSaveWorld;
WorldHooks.ChristmasCheck += OnXmasCheck; WorldHooks.ChristmasCheck += OnXmasCheck;
NetHooks.NameCollision += NetHooks_NameCollision; NetHooks.NameCollision += NetHooks_NameCollision;
TShockAPI.Hooks.PlayerHooks.PlayerPostLogin += OnPlayerLogin;
GetDataHandlers.InitGetDataHandler(); GetDataHandlers.InitGetDataHandler();
Commands.InitCommands(); Commands.InitCommands();
@ -322,6 +325,7 @@ namespace TShockAPI
WorldHooks.SaveWorld -= SaveManager.Instance.OnSaveWorld; WorldHooks.SaveWorld -= SaveManager.Instance.OnSaveWorld;
WorldHooks.ChristmasCheck -= OnXmasCheck; WorldHooks.ChristmasCheck -= OnXmasCheck;
NetHooks.NameCollision -= NetHooks_NameCollision; NetHooks.NameCollision -= NetHooks_NameCollision;
TShockAPI.Hooks.PlayerHooks.PlayerPostLogin -= OnPlayerLogin;
if (File.Exists(Path.Combine(SavePath, "tshock.pid"))) if (File.Exists(Path.Combine(SavePath, "tshock.pid")))
{ {
@ -334,7 +338,31 @@ namespace TShockAPI
base.Dispose(disposing); 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<String> KnownIps = new List<string>();
if (!string.IsNullOrWhiteSpace(u.KnownIps))
{
KnownIps = JsonConvert.DeserializeObject<List<String>>(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()); string ip = TShock.Utils.GetRealIP(Netplay.serverSock[who].tcpClient.Client.RemoteEndPoint.ToString());
foreach (TSPlayer ply in TShock.Players) foreach (TSPlayer ply in TShock.Players)
@ -365,7 +393,7 @@ namespace TShockAPI
return; return;
} }
void OnXmasCheck(ChristmasCheckEventArgs args) private void OnXmasCheck(ChristmasCheckEventArgs args)
{ {
if (args.Handled) if (args.Handled)
return; return;

View file

@ -741,7 +741,7 @@ namespace TShockAPI
return TShock.Groups.groups[i]; return TShock.Groups.groups[i];
} }
} }
return new Group(TShock.Config.DefaultGuestGroupName); return Group.DefaultGroup;
} }
/// <summary> /// <summary>