diff --git a/src/main/java/fr/xephi/authme/api/NewAPI.java b/src/main/java/fr/xephi/authme/api/NewAPI.java index 6da1026cf..8a7238849 100644 --- a/src/main/java/fr/xephi/authme/api/NewAPI.java +++ b/src/main/java/fr/xephi/authme/api/NewAPI.java @@ -178,6 +178,7 @@ public class NewAPI { .name(name) .password(result) .realName(playerName) + .registrationDate(System.currentTimeMillis()) .build(); return dataSource.saveAuth(auth); } diff --git a/src/main/java/fr/xephi/authme/api/v3/AuthMeApi.java b/src/main/java/fr/xephi/authme/api/v3/AuthMeApi.java index 0e1e099e6..81f71eb07 100644 --- a/src/main/java/fr/xephi/authme/api/v3/AuthMeApi.java +++ b/src/main/java/fr/xephi/authme/api/v3/AuthMeApi.java @@ -128,7 +128,7 @@ public class AuthMeApi { * Get the last location of an online player. * * @param player The player to process - * @return Location The location of the player + * @return The location of the player */ public Location getLastLocation(Player player) { PlayerAuth auth = playerCache.getAuth(player.getName()); @@ -143,7 +143,7 @@ public class AuthMeApi { * Get the last ip address of a player. * * @param playerName The name of the player to process - * @return String The last ip address of the player + * @return The last ip address of the player */ public String getLastIp(String playerName) { PlayerAuth auth = playerCache.getAuth(playerName); @@ -151,7 +151,7 @@ public class AuthMeApi { auth = dataSource.getAuth(playerName); } if (auth != null) { - return auth.getIp(); + return auth.getLastIp(); } return null; } @@ -160,7 +160,7 @@ public class AuthMeApi { * Get user names by ip. * * @param address The ip address to process - * @return List The list of user names related to the ip address + * @return The list of user names related to the ip address */ public List getNamesByIp(String address) { return dataSource.getAllAuthsByIp(address); @@ -170,11 +170,11 @@ public class AuthMeApi { * Get the last login date of a player. * * @param playerName The name of the player to process - * @return Date The date of the last login + * @return The date of the last login, or null if the player doesn't exist or has never logged in */ public Date getLastLogin(String playerName) { PlayerAuth auth = playerCache.getAuth(playerName); - if(auth == null) { + if (auth == null) { auth = dataSource.getAuth(playerName); } if (auth != null) { @@ -223,6 +223,7 @@ public class AuthMeApi { .name(name) .password(result) .realName(playerName) + .registrationDate(System.currentTimeMillis()) .build(); return dataSource.saveAuth(auth); } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java index d5b3d9f79..f11e6d2a9 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/AccountsCommand.java @@ -54,7 +54,7 @@ public class AccountsCommand implements ExecutableCommand { return; } - List accountList = dataSource.getAllAuthsByIp(auth.getIp()); + List accountList = dataSource.getAllAuthsByIp(auth.getLastIp()); if (accountList.isEmpty()) { commonService.send(sender, MessageKey.UNKNOWN_USER); } else if (accountList.size() == 1) { diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java index 332c0c8dd..2e00c65e9 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/GetIpCommand.java @@ -1,7 +1,10 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.command.ExecutableCommand; +import fr.xephi.authme.data.auth.PlayerAuth; +import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.service.BukkitService; +import fr.xephi.authme.util.PlayerUtils; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -13,18 +16,26 @@ public class GetIpCommand implements ExecutableCommand { @Inject private BukkitService bukkitService; + @Inject + private DataSource dataSource; + @Override public void executeCommand(CommandSender sender, List arguments) { - // Get the player query String playerName = arguments.get(0); - Player player = bukkitService.getPlayerExact(playerName); - if (player == null) { - sender.sendMessage("The player is not online"); - return; + PlayerAuth auth = dataSource.getAuth(playerName); + + if (player != null) { + sender.sendMessage("Current IP of " + player.getName() + " is " + PlayerUtils.getPlayerIp(player) + + ":" + player.getAddress().getPort()); } - sender.sendMessage(player.getName() + "'s IP is: " + player.getAddress().getAddress().getHostAddress() - + ":" + player.getAddress().getPort()); + if (auth == null) { + String displayName = player == null ? playerName : player.getName(); + sender.sendMessage(displayName + " is not registered in the database"); + } else { + sender.sendMessage("Database: last IP: " + auth.getLastIp() + ", registration IP: " + + auth.getRegistrationIp()); + } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java index 48a311a08..8f3474119 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/LastLoginCommand.java @@ -45,6 +45,6 @@ public class LastLoginCommand implements ExecutableCommand { // Show the player status sender.sendMessage("[AuthMe] " + playerName + " last login: " + date.toString()); sender.sendMessage("[AuthMe] The player " + playerName + " last logged in " + lastLoginMessage + " ago."); - sender.sendMessage("[AuthMe] Last Player's IP: " + auth.getIp()); + sender.sendMessage("[AuthMe] Last Player's IP: " + auth.getLastIp()); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java index 2f1341b92..34dfa94f6 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/RegisterAdminCommand.java @@ -64,6 +64,7 @@ public class RegisterAdminCommand implements ExecutableCommand { .name(playerNameLowerCase) .realName(playerName) .password(hashedPassword) + .registrationDate(System.currentTimeMillis()) .build(); if (!dataSource.saveAuth(auth)) { diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/CountryLookup.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/CountryLookup.java index 781b8392b..b2ae40065 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/CountryLookup.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/CountryLookup.java @@ -77,8 +77,8 @@ class CountryLookup implements DebugSection { if (auth == null) { sender.sendMessage("No player with name '" + name + "'"); } else { - sender.sendMessage("Player '" + name + "' has IP address " + auth.getIp()); - outputInfoForIpAddr(sender, auth.getIp()); + sender.sendMessage("Player '" + name + "' has IP address " + auth.getLastIp()); + outputInfoForIpAddr(sender, auth.getLastIp()); } } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/debug/PlayerAuthViewer.java b/src/main/java/fr/xephi/authme/command/executable/authme/debug/PlayerAuthViewer.java index f4a26ec87..b16a2f574 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/debug/PlayerAuthViewer.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/debug/PlayerAuthViewer.java @@ -65,10 +65,12 @@ class PlayerAuthViewer implements DebugSection { */ private void displayAuthToSender(PlayerAuth auth, CommandSender sender) { sender.sendMessage(ChatColor.GOLD + "[AuthMe] Player " + auth.getNickname() + " / " + auth.getRealName()); - sender.sendMessage("Email: " + auth.getEmail() + ". IP: " + auth.getIp() + ". Group: " + auth.getGroupId()); + sender.sendMessage("Email: " + auth.getEmail() + ". IP: " + auth.getLastIp() + ". Group: " + auth.getGroupId()); sender.sendMessage("Quit location: " + formatLocation(auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ(), auth.getWorld())); - sender.sendMessage("Last login: " + formatLastLogin(auth)); + sender.sendMessage("Last login: " + formatDate(auth.getLastLogin())); + sender.sendMessage("Registration: " + formatDate(auth.getRegistrationDate()) + + " with IP " + auth.getRegistrationIp()); HashedPassword hashedPass = auth.getPassword(); sender.sendMessage("Hash / salt (partial): '" + safeSubstring(hashedPass.getHash(), 6) @@ -94,17 +96,18 @@ class PlayerAuthViewer implements DebugSection { } /** - * Formats the last login date from the given PlayerAuth. + * Formats the given timestamp to a human readable date. * - * @param auth the auth object - * @return the last login as human readable date + * @param timestamp the timestamp to format (nullable) + * @return the formatted timestamp */ - private static String formatLastLogin(PlayerAuth auth) { - long lastLogin = auth.getLastLogin(); - if (lastLogin == 0) { - return "Never (0)"; + private static String formatDate(Long timestamp) { + if (timestamp == null) { + return "Not available (null)"; + } else if (timestamp == 0) { + return "Not available (0)"; } else { - LocalDateTime date = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastLogin), ZoneId.systemDefault()); + LocalDateTime date = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()); return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(date); } } diff --git a/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java b/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java index addfdead5..bbab3cc33 100644 --- a/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java +++ b/src/main/java/fr/xephi/authme/data/auth/PlayerAuth.java @@ -3,6 +3,8 @@ package fr.xephi.authme.data.auth; import fr.xephi.authme.security.crypts.HashedPassword; import org.bukkit.Location; +import java.util.Objects; + import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkNotNull; @@ -18,9 +20,11 @@ public class PlayerAuth { private String realName; private HashedPassword password; private String email; - private String ip; + private String lastIp; private int groupId; private long lastLogin; + private String registrationIp; + private long registrationDate; // Fields storing the player's quit location private double x; private double y; @@ -29,13 +33,6 @@ public class PlayerAuth { private float yaw; private float pitch; - /** - * @param serialized String - */ - public PlayerAuth(String serialized) { - this.deserialize(serialized); - } - /** * Hidden constructor. * @@ -112,12 +109,12 @@ public class PlayerAuth { return pitch; } - public String getIp() { - return ip; + public String getLastIp() { + return lastIp; } - public void setIp(String ip) { - this.ip = ip; + public void setLastIp(String lastIp) { + this.lastIp = lastIp; } public long getLastLogin() { @@ -144,76 +141,45 @@ public class PlayerAuth { this.password = password; } + public String getRegistrationIp() { + return registrationIp; + } + + public long getRegistrationDate() { + return registrationDate; + } + + public void setRegistrationDate(long registrationDate) { + this.registrationDate = registrationDate; + } + @Override public boolean equals(Object obj) { if (!(obj instanceof PlayerAuth)) { return false; } PlayerAuth other = (PlayerAuth) obj; - return other.getIp().equals(this.ip) && other.getNickname().equals(this.nickname); + return Objects.equals(other.lastIp, this.lastIp) && Objects.equals(other.nickname, this.nickname); } @Override public int hashCode() { int hashCode = 7; hashCode = 71 * hashCode + (this.nickname != null ? this.nickname.hashCode() : 0); - hashCode = 71 * hashCode + (this.ip != null ? this.ip.hashCode() : 0); + hashCode = 71 * hashCode + (this.lastIp != null ? this.lastIp.hashCode() : 0); return hashCode; } @Override public String toString() { return "Player : " + nickname + " | " + realName - + " ! IP : " + ip + + " ! IP : " + lastIp + " ! LastLogin : " + lastLogin + " ! LastPosition : " + x + "," + y + "," + z + "," + world + " ! Email : " + email + " ! Password : {" + password.getHash() + ", " + password.getSalt() + "}"; } - /** - * Method to serialize PlayerAuth - * - * @return String - */ - public String serialize() { - StringBuilder str = new StringBuilder(); - char d = ';'; - str.append(this.nickname).append(d); - str.append(this.realName).append(d); - str.append(this.ip).append(d); - str.append(this.email).append(d); - str.append(this.password.getHash()).append(d); - str.append(this.password.getSalt()).append(d); - str.append(this.groupId).append(d); - str.append(this.lastLogin).append(d); - str.append(this.world).append(d); - str.append(this.x).append(d); - str.append(this.y).append(d); - str.append(this.z); - return str.toString(); - } - - /** - * Method to deserialize PlayerAuth - * - * @param str String - */ - public void deserialize(String str) { - String[] args = str.split(";"); - this.nickname = args[0]; - this.realName = args[1]; - this.ip = args[2]; - this.email = args[3]; - this.password = new HashedPassword(args[4], args[5]); - this.groupId = Integer.parseInt(args[6]); - this.lastLogin = Long.parseLong(args[7]); - this.world = args[8]; - this.x = Double.parseDouble(args[9]); - this.y = Double.parseDouble(args[10]); - this.z = Double.parseDouble(args[11]); - } - public static Builder builder() { return new Builder(); } @@ -222,10 +188,12 @@ public class PlayerAuth { private String name; private String realName; private HashedPassword password; - private String ip; + private String lastIp; private String email; private int groupId = -1; private long lastLogin = System.currentTimeMillis(); + private String registrationIp; + private Long registrationDate; private double x; private double y; @@ -245,9 +213,11 @@ public class PlayerAuth { auth.realName = firstNonNull(realName, "Player"); auth.password = firstNonNull(password, new HashedPassword("")); auth.email = firstNonNull(email, "your@email.com"); - auth.ip = firstNonNull(ip, "127.0.0.1"); + auth.lastIp = firstNonNull(lastIp, "127.0.0.1"); auth.groupId = groupId; auth.lastLogin = lastLogin; + auth.registrationIp = registrationIp; + auth.registrationDate = registrationDate == null ? System.currentTimeMillis() : registrationDate; auth.x = x; auth.y = y; @@ -277,8 +247,8 @@ public class PlayerAuth { return password(new HashedPassword(hash, salt)); } - public Builder ip(String ip) { - this.ip = ip; + public Builder lastIp(String lastIp) { + this.lastIp = lastIp; return this; } @@ -342,5 +312,15 @@ public class PlayerAuth { this.email = email; return this; } + + public Builder registrationIp(String ip) { + this.registrationIp = ip; + return this; + } + + public Builder registrationDate(long date) { + this.registrationDate = date; + return this; + } } } diff --git a/src/main/java/fr/xephi/authme/datasource/Columns.java b/src/main/java/fr/xephi/authme/datasource/Columns.java index 7d6f50917..92127d971 100644 --- a/src/main/java/fr/xephi/authme/datasource/Columns.java +++ b/src/main/java/fr/xephi/authme/datasource/Columns.java @@ -14,7 +14,7 @@ public final class Columns { public final String REAL_NAME; public final String PASSWORD; public final String SALT; - public final String IP; + public final String LAST_IP; public final String LAST_LOGIN; public final String GROUP; public final String LASTLOC_X; @@ -26,24 +26,28 @@ public final class Columns { public final String EMAIL; public final String ID; public final String IS_LOGGED; + public final String REGISTRATION_DATE; + public final String REGISTRATION_IP; public Columns(Settings settings) { - NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME); - REAL_NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_REALNAME); - PASSWORD = settings.getProperty(DatabaseSettings.MYSQL_COL_PASSWORD); - SALT = settings.getProperty(DatabaseSettings.MYSQL_COL_SALT); - IP = settings.getProperty(DatabaseSettings.MYSQL_COL_IP); - LAST_LOGIN = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOGIN); - GROUP = settings.getProperty(DatabaseSettings.MYSQL_COL_GROUP); - LASTLOC_X = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_X); - LASTLOC_Y = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_Y); - LASTLOC_Z = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_Z); - LASTLOC_WORLD = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_WORLD); - LASTLOC_YAW = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_YAW); - LASTLOC_PITCH = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_PITCH); - EMAIL = settings.getProperty(DatabaseSettings.MYSQL_COL_EMAIL); - ID = settings.getProperty(DatabaseSettings.MYSQL_COL_ID); - IS_LOGGED = settings.getProperty(DatabaseSettings.MYSQL_COL_ISLOGGED); + NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME); + REAL_NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_REALNAME); + PASSWORD = settings.getProperty(DatabaseSettings.MYSQL_COL_PASSWORD); + SALT = settings.getProperty(DatabaseSettings.MYSQL_COL_SALT); + LAST_IP = settings.getProperty(DatabaseSettings.MYSQL_COL_LAST_IP); + LAST_LOGIN = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOGIN); + GROUP = settings.getProperty(DatabaseSettings.MYSQL_COL_GROUP); + LASTLOC_X = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_X); + LASTLOC_Y = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_Y); + LASTLOC_Z = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_Z); + LASTLOC_WORLD = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_WORLD); + LASTLOC_YAW = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_YAW); + LASTLOC_PITCH = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_PITCH); + EMAIL = settings.getProperty(DatabaseSettings.MYSQL_COL_EMAIL); + ID = settings.getProperty(DatabaseSettings.MYSQL_COL_ID); + IS_LOGGED = settings.getProperty(DatabaseSettings.MYSQL_COL_ISLOGGED); + REGISTRATION_DATE = settings.getProperty(DatabaseSettings.MYSQL_COL_REGISTER_DATE); + REGISTRATION_IP = settings.getProperty(DatabaseSettings.MYSQL_COL_REGISTER_IP); } } diff --git a/src/main/java/fr/xephi/authme/datasource/FlatFile.java b/src/main/java/fr/xephi/authme/datasource/FlatFile.java index bb9aa3ef2..3b6bd2203 100644 --- a/src/main/java/fr/xephi/authme/datasource/FlatFile.java +++ b/src/main/java/fr/xephi/authme/datasource/FlatFile.java @@ -79,7 +79,7 @@ public class FlatFile implements DataSource { return false; } try (BufferedWriter bw = new BufferedWriter(new FileWriter(source, true))) { - bw.write(auth.getNickname() + ":" + auth.getPassword().getHash() + ":" + auth.getIp() + bw.write(auth.getNickname() + ":" + auth.getPassword().getHash() + ":" + auth.getLastIp() + ":" + auth.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY() + ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n"); } catch (IOException ex) { @@ -139,7 +139,7 @@ public class FlatFile implements DataSource { newAuth = buildAuthFromArray(args); if (newAuth != null) { newAuth.setLastLogin(auth.getLastLogin()); - newAuth.setIp(auth.getIp()); + newAuth.setLastIp(auth.getLastIp()); } break; } @@ -393,7 +393,7 @@ public class FlatFile implements DataSource { PlayerAuth.Builder builder = PlayerAuth.builder() .name(args[0]).realName(args[0]).password(args[1], null); - if (args.length >= 3) builder.ip(args[2]); + if (args.length >= 3) builder.lastIp(args[2]); if (args.length >= 4) builder.lastLogin(Long.parseLong(args[3])); if (args.length >= 7) { builder.locX(Double.parseDouble(args[4])) diff --git a/src/main/java/fr/xephi/authme/datasource/MySQL.java b/src/main/java/fr/xephi/authme/datasource/MySQL.java index 73f758403..15db98f54 100644 --- a/src/main/java/fr/xephi/authme/datasource/MySQL.java +++ b/src/main/java/fr/xephi/authme/datasource/MySQL.java @@ -189,9 +189,9 @@ public class MySQL implements DataSource { st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.SALT + " VARCHAR(255);"); } - if (isColumnMissing(md, col.IP)) { + if (isColumnMissing(md, col.LAST_IP)) { st.executeUpdate("ALTER TABLE " + tableName - + " ADD COLUMN " + col.IP + " VARCHAR(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL;"); + + " ADD COLUMN " + col.LAST_IP + " VARCHAR(40) CHARACTER SET ascii COLLATE ascii_bin NOT NULL;"); } if (isColumnMissing(md, col.LAST_LOGIN)) { @@ -201,6 +201,16 @@ public class MySQL implements DataSource { migrateLastLoginColumn(con, md); } + if (isColumnMissing(md, col.REGISTRATION_DATE)) { + st.executeUpdate("ALTER TABLE " + tableName + + " ADD COLUMN " + col.REGISTRATION_DATE + " BIGINT;"); + } + + if (isColumnMissing(md, col.REGISTRATION_IP)) { + st.executeUpdate("ALTER TABLE " + tableName + + " ADD COLUMN " + col.REGISTRATION_IP + " VARCHAR(40) CHARACTER SET ascii COLLATE ascii_bin;"); + } + if (isColumnMissing(md, col.LASTLOC_X)) { st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_X + " DOUBLE NOT NULL DEFAULT '0.0' AFTER " + col.LAST_LOGIN + " , ADD " @@ -305,20 +315,19 @@ public class MySQL implements DataSource { public boolean saveAuth(PlayerAuth auth) { try (Connection con = getConnection()) { String sql; - boolean useSalt = !col.SALT.isEmpty() || !StringUtils.isEmpty(auth.getPassword().getSalt()); sql = "INSERT INTO " + tableName + "(" - + col.NAME + "," + col.PASSWORD + "," + col.IP + "," - + col.LAST_LOGIN + "," + col.REAL_NAME + "," + col.EMAIL + + col.NAME + "," + col.PASSWORD + "," + col.REAL_NAME + + "," + col.EMAIL + "," + col.REGISTRATION_DATE + "," + col.REGISTRATION_IP + (useSalt ? "," + col.SALT : "") + ") VALUES (?,?,?,?,?,?" + (useSalt ? ",?" : "") + ");"; try (PreparedStatement pst = con.prepareStatement(sql)) { pst.setString(1, auth.getNickname()); pst.setString(2, auth.getPassword().getHash()); - pst.setString(3, auth.getIp()); - pst.setLong(4, auth.getLastLogin()); - pst.setString(5, auth.getRealName()); - pst.setString(6, auth.getEmail()); + pst.setString(3, auth.getRealName()); + pst.setString(4, auth.getEmail()); + pst.setObject(5, auth.getRegistrationDate()); + pst.setString(6, auth.getRegistrationIp()); if (useSalt) { pst.setString(7, auth.getPassword().getSalt()); } @@ -382,9 +391,9 @@ public class MySQL implements DataSource { @Override public boolean updateSession(PlayerAuth auth) { String sql = "UPDATE " + tableName + " SET " - + col.IP + "=?, " + col.LAST_LOGIN + "=?, " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;"; + + col.LAST_IP + "=?, " + col.LAST_LOGIN + "=?, " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;"; try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) { - pst.setString(1, auth.getIp()); + pst.setString(1, auth.getLastIp()); pst.setLong(2, auth.getLastLogin()); pst.setString(3, auth.getRealName()); pst.setString(4, auth.getNickname()); @@ -479,7 +488,7 @@ public class MySQL implements DataSource { @Override public List getAllAuthsByIp(String ip) { List result = new ArrayList<>(); - String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.IP + "=?;"; + String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.LAST_IP + "=?;"; try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) { pst.setString(1, ip); try (ResultSet rs = pst.executeQuery()) { @@ -665,15 +674,17 @@ public class MySQL implements DataSource { .realName(row.getString(col.REAL_NAME)) .password(row.getString(col.PASSWORD), salt) .lastLogin(row.getLong(col.LAST_LOGIN)) - .ip(row.getString(col.IP)) + .lastIp(row.getString(col.LAST_IP)) + .email(row.getString(col.EMAIL)) + .registrationDate(row.getLong(col.REGISTRATION_DATE)) + .registrationIp(row.getString(col.REGISTRATION_IP)) + .groupId(group) .locWorld(row.getString(col.LASTLOC_WORLD)) .locX(row.getDouble(col.LASTLOC_X)) .locY(row.getDouble(col.LASTLOC_Y)) .locZ(row.getDouble(col.LASTLOC_Z)) .locYaw(row.getFloat(col.LASTLOC_YAW)) .locPitch(row.getFloat(col.LASTLOC_PITCH)) - .email(row.getString(col.EMAIL)) - .groupId(group) .build(); } @@ -706,6 +717,7 @@ public class MySQL implements DataSource { * Performs conversion of lastlogin column from timestamp type to bigint. * * @param con connection to the database + * @see #477 */ private void migrateLastLoginColumnFromTimestamp(Connection con) throws SQLException { ConsoleLogger.info("Migrating lastlogin column from timestamp to bigint"); @@ -721,7 +733,7 @@ public class MySQL implements DataSource { // Create lastlogin column sql = String.format("ALTER TABLE %s ADD COLUMN %s " + "BIGINT NOT NULL DEFAULT 0 AFTER %s", - tableName, col.LAST_LOGIN, col.IP); + tableName, col.LAST_LOGIN, col.LAST_IP); con.prepareStatement(sql).execute(); // Set values of lastlogin based on lastlogin_old @@ -740,6 +752,8 @@ public class MySQL implements DataSource { * Performs conversion of lastlogin column from int to bigint. * * @param con connection to the database + * @see + * #887: Migrate lastlogin column from int32 to bigint */ private void migrateLastLoginColumnFromInt(Connection con) throws SQLException { // Change from int to bigint diff --git a/src/main/java/fr/xephi/authme/datasource/SQLite.java b/src/main/java/fr/xephi/authme/datasource/SQLite.java index 4652aad9b..d7be0c09f 100644 --- a/src/main/java/fr/xephi/authme/datasource/SQLite.java +++ b/src/main/java/fr/xephi/authme/datasource/SQLite.java @@ -94,9 +94,9 @@ public class SQLite implements DataSource { st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.SALT + " VARCHAR(255);"); } - if (isColumnMissing(md, col.IP)) { + if (isColumnMissing(md, col.LAST_IP)) { st.executeUpdate("ALTER TABLE " + tableName - + " ADD COLUMN " + col.IP + " VARCHAR(40) NOT NULL DEFAULT '';"); + + " ADD COLUMN " + col.LAST_IP + " VARCHAR(40) NOT NULL DEFAULT '';"); } if (isColumnMissing(md, col.LAST_LOGIN)) { @@ -104,6 +104,16 @@ public class SQLite implements DataSource { + " ADD COLUMN " + col.LAST_LOGIN + " TIMESTAMP;"); } + if (isColumnMissing(md, col.REGISTRATION_IP)) { + st.executeUpdate("ALTER TABLE " + tableName + + " ADD COLUMN " + col.REGISTRATION_IP + " VARCHAR(40);"); + } + + if (isColumnMissing(md, col.REGISTRATION_DATE)) { + st.executeUpdate("ALTER TABLE " + tableName + + " ADD COLUMN " + col.REGISTRATION_DATE + " TIMESTAMP NOT NULL DEFAULT '0';"); + } + if (isColumnMissing(md, col.LASTLOC_X)) { st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_X + " DOUBLE NOT NULL DEFAULT '0.0';"); @@ -209,6 +219,7 @@ public class SQLite implements DataSource { @Override public boolean saveAuth(PlayerAuth auth) { + PreparedStatement pst = null; try { HashedPassword password = auth.getPassword(); if (col.SALT.isEmpty()) { @@ -216,33 +227,36 @@ public class SQLite implements DataSource { ConsoleLogger.warning("Warning! Detected hashed password with separate salt but the salt column " + "is not set in the config!"); } - try (PreparedStatement pst = con.prepareStatement("INSERT INTO " + tableName + "(" + col.NAME + "," + col.PASSWORD + - "," + col.IP + "," + col.LAST_LOGIN + "," + col.REAL_NAME + "," + col.EMAIL + - ") VALUES (?,?,?,?,?,?);")) { - pst.setString(1, auth.getNickname()); - pst.setString(2, password.getHash()); - pst.setString(3, auth.getIp()); - pst.setLong(4, auth.getLastLogin()); - pst.setString(5, auth.getRealName()); - pst.setString(6, auth.getEmail()); - pst.executeUpdate(); - } + + pst = con.prepareStatement("INSERT INTO " + tableName + "(" + col.NAME + "," + col.PASSWORD + + "," + col.REAL_NAME + "," + col.EMAIL + + "," + col.REGISTRATION_DATE + "," + col.REGISTRATION_IP + + ") VALUES (?,?,?,?,?,?);"); + pst.setString(1, auth.getNickname()); + pst.setString(2, password.getHash()); + pst.setString(3, auth.getRealName()); + pst.setString(4, auth.getEmail()); + pst.setLong(5, auth.getRegistrationDate()); + pst.setString(6, auth.getRegistrationIp()); + pst.executeUpdate(); } else { - try (PreparedStatement pst = con.prepareStatement("INSERT INTO " + tableName + "(" + col.NAME + "," + col.PASSWORD + "," - + col.IP + "," + col.LAST_LOGIN + "," + col.REAL_NAME + "," + col.EMAIL + "," + col.SALT - + ") VALUES (?,?,?,?,?,?,?);")) { - pst.setString(1, auth.getNickname()); - pst.setString(2, password.getHash()); - pst.setString(3, auth.getIp()); - pst.setLong(4, auth.getLastLogin()); - pst.setString(5, auth.getRealName()); - pst.setString(6, auth.getEmail()); - pst.setString(7, password.getSalt()); - pst.executeUpdate(); - } + pst = con.prepareStatement("INSERT INTO " + tableName + "(" + col.NAME + "," + col.PASSWORD + + "," + col.REAL_NAME + "," + col.EMAIL + + "," + col.REGISTRATION_DATE + "," + col.REGISTRATION_IP + "," + col.SALT + + ") VALUES (?,?,?,?,?,?,?);"); + pst.setString(1, auth.getNickname()); + pst.setString(2, password.getHash()); + pst.setString(3, auth.getRealName()); + pst.setString(4, auth.getEmail()); + pst.setLong(5, auth.getRegistrationDate()); + pst.setString(6, auth.getRegistrationIp()); + pst.setString(7, password.getSalt()); + pst.executeUpdate(); } } catch (SQLException ex) { logSqlException(ex); + } finally { + close(pst); } return true; } @@ -277,9 +291,10 @@ public class SQLite implements DataSource { @Override public boolean updateSession(PlayerAuth auth) { - String sql = "UPDATE " + tableName + " SET " + col.IP + "=?, " + col.LAST_LOGIN + "=?, " + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;"; + String sql = "UPDATE " + tableName + " SET " + col.LAST_IP + "=?, " + col.LAST_LOGIN + "=?, " + + col.REAL_NAME + "=? WHERE " + col.NAME + "=?;"; try (PreparedStatement pst = con.prepareStatement(sql)){ - pst.setString(1, auth.getIp()); + pst.setString(1, auth.getLastIp()); pst.setLong(2, auth.getLastLogin()); pst.setString(3, auth.getRealName()); pst.setString(4, auth.getNickname()); @@ -388,7 +403,7 @@ public class SQLite implements DataSource { @Override public List getAllAuthsByIp(String ip) { List countIp = new ArrayList<>(); - String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.IP + "=?;"; + String sql = "SELECT " + col.NAME + " FROM " + tableName + " WHERE " + col.LAST_IP + "=?;"; try (PreparedStatement pst = con.prepareStatement(sql)) { pst.setString(1, ip); try (ResultSet rs = pst.executeQuery()) { @@ -554,27 +569,24 @@ public class SQLite implements DataSource { private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException { String salt = !col.SALT.isEmpty() ? row.getString(col.SALT) : null; - PlayerAuth.Builder authBuilder = PlayerAuth.builder() + return PlayerAuth.builder() .name(row.getString(col.NAME)) .email(row.getString(col.EMAIL)) .realName(row.getString(col.REAL_NAME)) .password(row.getString(col.PASSWORD), salt) .lastLogin(row.getLong(col.LAST_LOGIN)) + .lastIp(row.getString(col.LAST_IP)) + .registrationDate(row.getLong(col.REGISTRATION_DATE)) + .registrationIp(row.getString(col.REGISTRATION_IP)) .locX(row.getDouble(col.LASTLOC_X)) .locY(row.getDouble(col.LASTLOC_Y)) .locZ(row.getDouble(col.LASTLOC_Z)) .locWorld(row.getString(col.LASTLOC_WORLD)) .locYaw(row.getFloat(col.LASTLOC_YAW)) - .locPitch(row.getFloat(col.LASTLOC_PITCH)); - - String ip = row.getString(col.IP); - if (!ip.isEmpty()) { - authBuilder.ip(ip); - } - return authBuilder.build(); + .locPitch(row.getFloat(col.LASTLOC_PITCH)) + .build(); } - private static void close(Statement st) { if (st != null) { try { diff --git a/src/main/java/fr/xephi/authme/datasource/SqlDataSourceUtils.java b/src/main/java/fr/xephi/authme/datasource/SqlDataSourceUtils.java index 7b9c6aae4..c84505d8c 100644 --- a/src/main/java/fr/xephi/authme/datasource/SqlDataSourceUtils.java +++ b/src/main/java/fr/xephi/authme/datasource/SqlDataSourceUtils.java @@ -2,6 +2,7 @@ package fr.xephi.authme.datasource; import fr.xephi.authme.ConsoleLogger; +import java.sql.ResultSet; import java.sql.SQLException; /** @@ -20,4 +21,18 @@ final class SqlDataSourceUtils { static void logSqlException(SQLException e) { ConsoleLogger.logException("Error during SQL operation:", e); } + + /** + * Returns the long value of a column, or null when appropriate. This method is necessary because + * JDBC's {@link ResultSet#getLong} returns {@code 0} if the entry in the database is {@code null}. + * + * @param rs the result set to read from + * @param columnName the name of the column to retrieve + * @return the value (which may be null) + * @throws SQLException :) + */ + static Long getNullableLong(ResultSet rs, String columnName) throws SQLException { + long longValue = rs.getLong(columnName); + return rs.wasNull() ? null : longValue; + } } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java index 209b75adc..3ae721906 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverter.java @@ -62,6 +62,7 @@ public abstract class AbstractDataSourceConverter implemen } else { adaptPlayerAuth(auth); destination.saveAuth(auth); + destination.updateSession(auth); destination.updateQuitLoc(auth); } } diff --git a/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java index 9a6f4f354..4fd5fb34c 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/LoginSecurityConverter.java @@ -18,6 +18,7 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Optional; @@ -94,6 +95,7 @@ public class LoginSecurityConverter implements Converter { } else { PlayerAuth auth = buildAuthFromLoginSecurity(name, resultSet); dataSource.saveAuth(auth); + dataSource.updateSession(auth); ++successfulSaves; } } @@ -113,16 +115,17 @@ public class LoginSecurityConverter implements Converter { * @return the created player auth object */ private static PlayerAuth buildAuthFromLoginSecurity(String name, ResultSet resultSet) throws SQLException { - // TODO #792: Last login should be null if not present - long lastLoginMillis = Optional.ofNullable(resultSet.getTimestamp("last_login")) - .map(Timestamp::getTime).orElse(System.currentTimeMillis()); + Long lastLoginMillis = Optional.ofNullable(resultSet.getTimestamp("last_login")) + .map(Timestamp::getTime).orElse(null); + long regDate = Optional.ofNullable(resultSet.getDate("registration_date")) + .map(Date::getTime).orElse(System.currentTimeMillis()); return PlayerAuth.builder() .name(name) .realName(name) .password(resultSet.getString("password"), null) - .ip(resultSet.getString("ip_address")) + .lastIp(resultSet.getString("ip_address")) .lastLogin(lastLoginMillis) - // TODO #792: Register date + .registrationDate(regDate) .locX(resultSet.getDouble("x")) .locY(resultSet.getDouble("y")) .locZ(resultSet.getDouble("z")) diff --git a/src/main/java/fr/xephi/authme/datasource/converter/RakamakConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/RakamakConverter.java index dcb25e20a..444a86bbb 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/RakamakConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/RakamakConverter.java @@ -80,11 +80,11 @@ public class RakamakConverter implements Converter { PlayerAuth auth = PlayerAuth.builder() .name(playerName) .realName(playerName) - .ip(ip) + .lastIp(ip) .password(psw) - .lastLogin(0) .build(); database.saveAuth(auth); + database.updateSession(auth); } Utils.logAndSendMessage(sender, "Rakamak database has been imported correctly"); } catch (IOException ex) { diff --git a/src/main/java/fr/xephi/authme/datasource/converter/RoyalAuthConverter.java b/src/main/java/fr/xephi/authme/datasource/converter/RoyalAuthConverter.java index 34b0d61c1..d921ade82 100644 --- a/src/main/java/fr/xephi/authme/datasource/converter/RoyalAuthConverter.java +++ b/src/main/java/fr/xephi/authme/datasource/converter/RoyalAuthConverter.java @@ -46,6 +46,7 @@ public class RoyalAuthConverter implements Converter { .build(); dataSource.saveAuth(auth); + dataSource.updateSession(auth); } catch (Exception e) { ConsoleLogger.logException("Error while trying to import " + player.getName() + " RoyalAuth data", e); } diff --git a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java index af325cbae..e7f83a67a 100644 --- a/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java +++ b/src/main/java/fr/xephi/authme/process/join/AsynchronousJoin.java @@ -188,7 +188,7 @@ public class AsynchronousJoin implements AsynchronousProcess { long timeSinceLastLogin = System.currentTimeMillis() - auth.getLastLogin(); if(timeSinceLastLogin < 0 || timeSinceLastLogin > (service.getProperty(PluginSettings.SESSIONS_TIMEOUT) * 60 * 1000) - || !auth.getIp().equals(PlayerUtils.getPlayerIp(player))) { + || !auth.getLastIp().equals(PlayerUtils.getPlayerIp(player))) { service.send(player, MessageKey.SESSION_EXPIRED); } else { RestoreSessionEvent event = bukkitService.createAndCallEvent( diff --git a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java index 46c97dc45..50d53aeaa 100644 --- a/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java +++ b/src/main/java/fr/xephi/authme/process/login/AsynchronousLogin.java @@ -215,7 +215,7 @@ public class AsynchronousLogin implements AsynchronousProcess { final String ip = PlayerUtils.getPlayerIp(player); auth.setRealName(player.getName()); auth.setLastLogin(System.currentTimeMillis()); - auth.setIp(ip); + auth.setLastIp(ip); dataSource.updateSession(auth); // Successful login, so reset the captcha & temp ban count @@ -227,8 +227,8 @@ public class AsynchronousLogin implements AsynchronousProcess { service.send(player, MessageKey.LOGIN_SUCCESS); // Other auths - List auths = dataSource.getAllAuthsByIp(auth.getIp()); - runCommandOtherAccounts(auths, player, auth.getIp()); + List auths = dataSource.getAllAuthsByIp(auth.getLastIp()); + runCommandOtherAccounts(auths, player, auth.getLastIp()); displayOtherAccounts(auths, player); final String email = auth.getEmail(); diff --git a/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java b/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java index c22a0d64f..e376ccd03 100644 --- a/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java +++ b/src/main/java/fr/xephi/authme/process/quit/AsynchronousQuit.java @@ -72,7 +72,7 @@ public class AsynchronousQuit implements AsynchronousProcess { PlayerAuth auth = PlayerAuth.builder() .name(name) .realName(player.getName()) - .ip(ip) + .lastIp(ip) .lastLogin(System.currentTimeMillis()) .build(); database.updateSession(auth); diff --git a/src/main/java/fr/xephi/authme/process/register/executors/PlayerAuthBuilderHelper.java b/src/main/java/fr/xephi/authme/process/register/executors/PlayerAuthBuilderHelper.java index 5d9ab8657..d8c6a5fcc 100644 --- a/src/main/java/fr/xephi/authme/process/register/executors/PlayerAuthBuilderHelper.java +++ b/src/main/java/fr/xephi/authme/process/register/executors/PlayerAuthBuilderHelper.java @@ -27,8 +27,8 @@ final class PlayerAuthBuilderHelper { .realName(player.getName()) .password(hashedPassword) .email(email) - .ip(PlayerUtils.getPlayerIp(player)) - .location(player.getLocation()) + .registrationIp(PlayerUtils.getPlayerIp(player)) + .registrationDate(System.currentTimeMillis()) .build(); } } diff --git a/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java b/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java index 4b3f5d3e0..be4fcdae1 100644 --- a/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java +++ b/src/main/java/fr/xephi/authme/settings/properties/DatabaseSettings.java @@ -75,14 +75,22 @@ public final class DatabaseSettings implements SettingsHolder { public static final Property MYSQL_COL_ISLOGGED = newProperty("DataSource.mySQLColumnLogged", "isLogged"); - @Comment("Column for storing players ips") - public static final Property MYSQL_COL_IP = + @Comment("Column for storing the player's last IP") + public static final Property MYSQL_COL_LAST_IP = newProperty("DataSource.mySQLColumnIp", "ip"); @Comment("Column for storing players lastlogins") public static final Property MYSQL_COL_LASTLOGIN = newProperty("DataSource.mySQLColumnLastLogin", "lastlogin"); + @Comment("Column storing the registration date") + public static final Property MYSQL_COL_REGISTER_DATE = + newProperty("DataSource.mySQLColumnRegisterDate", "regdate"); + + @Comment("Column for storing the IP address at the time of registration") + public static final Property MYSQL_COL_REGISTER_IP = + newProperty("DataSource.mySQLColumnRegisterIp", "regip"); + @Comment("Column for storing player LastLocation - X") public static final Property MYSQL_COL_LASTLOC_X = newProperty("DataSource.mySQLlastlocX", "x"); diff --git a/src/test/java/fr/xephi/authme/AuthMeMatchers.java b/src/test/java/fr/xephi/authme/AuthMeMatchers.java index fffe8b2ed..69f2ac27e 100644 --- a/src/test/java/fr/xephi/authme/AuthMeMatchers.java +++ b/src/test/java/fr/xephi/authme/AuthMeMatchers.java @@ -44,26 +44,48 @@ public final class AuthMeMatchers { } public static Matcher hasAuthBasicData(String name, String realName, - String email, String ip) { + String email, String lastIp) { return new TypeSafeMatcher() { @Override public boolean matchesSafely(PlayerAuth item) { return Objects.equals(name, item.getNickname()) && Objects.equals(realName, item.getRealName()) && Objects.equals(email, item.getEmail()) - && Objects.equals(ip, item.getIp()); + && Objects.equals(lastIp, item.getLastIp()); } @Override public void describeTo(Description description) { - description.appendValue(String.format("PlayerAuth with name %s, realname %s, email %s, ip %s", - name, realName, email, ip)); + description.appendValue(String.format("PlayerAuth with name %s, realname %s, email %s, lastIp %s", + name, realName, email, lastIp)); } @Override public void describeMismatchSafely(PlayerAuth item, Description description) { - description.appendValue(String.format("PlayerAuth with name %s, realname %s, email %s, ip %s", - item.getNickname(), item.getRealName(), item.getEmail(), item.getIp())); + description.appendValue(String.format("PlayerAuth with name %s, realname %s, email %s, lastIp %s", + item.getNickname(), item.getRealName(), item.getEmail(), item.getLastIp())); + } + }; + } + + public static Matcher hasRegistrationInfo(String registrationIp, long registrationDate) { + return new TypeSafeMatcher() { + @Override + public boolean matchesSafely(PlayerAuth item) { + return Objects.equals(registrationIp, item.getRegistrationIp()) + && Objects.equals(registrationDate, item.getRegistrationDate()); + } + + @Override + public void describeTo(Description description) { + description.appendValue(String.format("PlayerAuth with reg. IP %s and reg date %d", + registrationIp, registrationDate)); + } + + @Override + public void describeMismatchSafely(PlayerAuth item, Description description) { + description.appendValue(String.format("PlayerAuth with reg. IP %s and reg date %d", + item.getRegistrationIp(), item.getRegistrationDate())); } }; } diff --git a/src/test/java/fr/xephi/authme/api/v3/AuthMeApiTest.java b/src/test/java/fr/xephi/authme/api/v3/AuthMeApiTest.java index d1ddaf73e..85e3bd57a 100644 --- a/src/test/java/fr/xephi/authme/api/v3/AuthMeApiTest.java +++ b/src/test/java/fr/xephi/authme/api/v3/AuthMeApiTest.java @@ -146,7 +146,7 @@ public class AuthMeApiTest { String name = "Gabriel"; Player player = mockPlayerWithName(name); PlayerAuth auth = PlayerAuth.builder().name(name) - .ip("93.23.44.55") + .lastIp("93.23.44.55") .build(); given(playerCache.getAuth(name)).willReturn(auth); diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java index c5a7301a4..03256d7ad 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/AccountsCommandTest.java @@ -171,7 +171,7 @@ public class AccountsCommandTest { private static PlayerAuth authWithIp(String ip) { return PlayerAuth.builder() .name("Test") - .ip(ip) + .lastIp(ip) .build(); } } diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/GetIpCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/GetIpCommandTest.java index 28c945e39..758bc5f34 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/GetIpCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/GetIpCommandTest.java @@ -1,6 +1,8 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.TestHelper; +import fr.xephi.authme.data.auth.PlayerAuth; +import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.service.BukkitService; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -12,11 +14,12 @@ import org.mockito.junit.MockitoJUnitRunner; import java.util.Collections; -import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.both; import static org.hamcrest.Matchers.containsString; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.only; import static org.mockito.Mockito.verify; import static org.mockito.hamcrest.MockitoHamcrest.argThat; @@ -32,19 +35,25 @@ public class GetIpCommandTest { @Mock private BukkitService bukkitService; + @Mock + private DataSource dataSource; + @Test public void shouldGetIpOfPlayer() { // given given(bukkitService.getPlayerExact(anyString())).willReturn(null); + given(dataSource.getAuth(anyString())).willReturn(null); CommandSender sender = mock(CommandSender.class); + String name = "Testt"; // when - command.executeCommand(sender, Collections.singletonList("Testt")); + command.executeCommand(sender, Collections.singletonList(name)); // then - verify(bukkitService).getPlayerExact("Testt"); - verify(sender).sendMessage(argThat(containsString("not online"))); + verify(bukkitService).getPlayerExact(name); + verify(dataSource).getAuth(name); + verify(sender, only()).sendMessage(argThat(containsString("not registered"))); } @Test @@ -54,6 +63,8 @@ public class GetIpCommandTest { String ip = "123.34.56.88"; Player player = mockPlayer(playerName, ip); given(bukkitService.getPlayerExact(playerName)).willReturn(player); + PlayerAuth auth = PlayerAuth.builder().name("t").lastIp("44.33.22.11").registrationIp("77.11.44.88").build(); + given(dataSource.getAuth(playerName)).willReturn(auth); CommandSender sender = mock(CommandSender.class); // when @@ -61,7 +72,29 @@ public class GetIpCommandTest { // then verify(bukkitService).getPlayerExact(playerName); - verify(sender).sendMessage(argThat(allOf(containsString(playerName), containsString(ip)))); + verify(dataSource).getAuth(playerName); + verify(sender).sendMessage(argThat(both(containsString(playerName)).and(containsString(ip)))); + verify(sender).sendMessage(argThat(both(containsString("44.33.22.11")).and(containsString("77.11.44.88")))); + } + + @Test + public void shouldHandleUnregisteredOnlinePlayer() { + // given + String playerName = "Test"; + String ip = "44.111.22.33"; + Player player = mockPlayer(playerName, ip); + given(bukkitService.getPlayerExact(playerName)).willReturn(player); + given(dataSource.getAuth(anyString())).willReturn(null); + CommandSender sender = mock(CommandSender.class); + + // when + command.executeCommand(sender, Collections.singletonList(playerName)); + + // then + verify(bukkitService).getPlayerExact(playerName); + verify(dataSource).getAuth(playerName); + verify(sender).sendMessage(argThat(both(containsString(playerName)).and(containsString(ip)))); + verify(sender).sendMessage(argThat(containsString("not registered"))); } private static Player mockPlayer(String name, String ip) { diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java index f0891ffe2..ef1389cce 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/LastLoginCommandTest.java @@ -65,7 +65,7 @@ public class LastLoginCommandTest { (412 * DAY_IN_MSEC + 10 * HOUR_IN_MSEC - 9000); PlayerAuth auth = mock(PlayerAuth.class); given(auth.getLastLogin()).willReturn(lastLogin); - given(auth.getIp()).willReturn("123.45.66.77"); + given(auth.getLastIp()).willReturn("123.45.66.77"); given(dataSource.getAuth(player)).willReturn(auth); CommandSender sender = mock(CommandSender.class); @@ -94,7 +94,7 @@ public class LastLoginCommandTest { - (412 * DAY_IN_MSEC + 10 * HOUR_IN_MSEC - 9000); PlayerAuth auth = mock(PlayerAuth.class); given(auth.getLastLogin()).willReturn(lastLogin); - given(auth.getIp()).willReturn("123.45.66.77"); + given(auth.getLastIp()).willReturn("123.45.66.77"); given(dataSource.getAuth(name)).willReturn(auth); // when diff --git a/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java index bd0b92a22..be9e9a68c 100644 --- a/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/datasource/AbstractDataSourceIntegrationTest.java @@ -12,6 +12,7 @@ import java.util.Set; import static fr.xephi.authme.AuthMeMatchers.equalToHash; import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData; import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation; +import static fr.xephi.authme.AuthMeMatchers.hasRegistrationInfo; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.empty; @@ -97,11 +98,13 @@ public abstract class AbstractDataSourceIntegrationTest { assertThat(bobbyAuth, hasAuthBasicData("bobby", "Bobby", "your@email.com", "123.45.67.89")); assertThat(bobbyAuth, hasAuthLocation(1.05, 2.1, 4.2, "world", -0.44f, 2.77f)); + assertThat(bobbyAuth, hasRegistrationInfo("127.0.4.22", 1436778723L)); assertThat(bobbyAuth.getLastLogin(), equalTo(1449136800L)); assertThat(bobbyAuth.getPassword(), equalToHash("$SHA$11aa0706173d7272$dbba966")); assertThat(userAuth, hasAuthBasicData("user", "user", "user@example.org", "34.56.78.90")); assertThat(userAuth, hasAuthLocation(124.1, 76.3, -127.8, "nether", 0.23f, 4.88f)); + assertThat(userAuth, hasRegistrationInfo(null, 0)); assertThat(userAuth.getLastLogin(), equalTo(1453242857L)); assertThat(userAuth.getPassword(), equalToHash("b28c32f624a4eb161d6adc9acb5bfc5b", "f750ba32")); } @@ -211,7 +214,7 @@ public abstract class AbstractDataSourceIntegrationTest { DataSource dataSource = getDataSource(); PlayerAuth bobby = PlayerAuth.builder() .name("bobby").realName("BOBBY").lastLogin(123L) - .ip("12.12.12.12").build(); + .lastIp("12.12.12.12").build(); // when boolean response = dataSource.updateSession(bobby); @@ -298,7 +301,9 @@ public abstract class AbstractDataSourceIntegrationTest { List initialList = dataSource.getAllAuthsByIp("123.45.67.89"); List emptyList = dataSource.getAllAuthsByIp("8.8.8.8"); for (int i = 0; i < 3; ++i) { - dataSource.saveAuth(PlayerAuth.builder().name("test-" + i).ip("123.45.67.89").build()); + PlayerAuth auth = PlayerAuth.builder().name("test-" + i).lastIp("123.45.67.89").build(); + dataSource.saveAuth(auth); + dataSource.updateSession(auth); // trigger storage of last IP } List updatedList = dataSource.getAllAuthsByIp("123.45.67.89"); @@ -329,8 +334,9 @@ public abstract class AbstractDataSourceIntegrationTest { public void shouldGetRecordsToPurge() { // given DataSource dataSource = getDataSource(); - PlayerAuth auth = PlayerAuth.builder().name("potato").lastLogin(0).build(); + PlayerAuth auth = PlayerAuth.builder().name("potato").lastLogin(0L).build(); dataSource.saveAuth(auth); + dataSource.updateSession(auth); // 1453242857 -> user, 1449136800 -> bobby, 0 -> potato // when diff --git a/src/test/java/fr/xephi/authme/datasource/FlatFileIntegrationTest.java b/src/test/java/fr/xephi/authme/datasource/FlatFileIntegrationTest.java index 351b6ff99..201e3dbc9 100644 --- a/src/test/java/fr/xephi/authme/datasource/FlatFileIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/datasource/FlatFileIntegrationTest.java @@ -79,7 +79,7 @@ public class FlatFileIntegrationTest { public void shouldAddAuth() { // given / when boolean response = dataSource.saveAuth( - PlayerAuth.builder().name("Test").email("user@EXAMPLE.org").ip("123.45.67.77").build()); + PlayerAuth.builder().name("Test").email("user@EXAMPLE.org").lastIp("123.45.67.77").build()); List authList = dataSource.getAllAuths(); // then diff --git a/src/test/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverterTest.java b/src/test/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverterTest.java index 14e59dff1..f4c70280c 100644 --- a/src/test/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverterTest.java +++ b/src/test/java/fr/xephi/authme/datasource/converter/AbstractDataSourceConverterTest.java @@ -98,6 +98,7 @@ public class AbstractDataSourceConverterTest { verify(destination).getType(); verify(destination, times(3)).isAuthAvailable(anyString()); verify(destination, times(2)).saveAuth(any(PlayerAuth.class)); + verify(destination, times(2)).updateSession(any(PlayerAuth.class)); verify(destination, times(2)).updateQuitLoc(any(PlayerAuth.class)); verifyNoMoreInteractions(destination); verify(sender).sendMessage(argThat(containsString(auths.get(0).getNickname()))); diff --git a/src/test/java/fr/xephi/authme/datasource/converter/LoginSecurityConverterTest.java b/src/test/java/fr/xephi/authme/datasource/converter/LoginSecurityConverterTest.java index 7e4afee39..4a7e94fe6 100644 --- a/src/test/java/fr/xephi/authme/datasource/converter/LoginSecurityConverterTest.java +++ b/src/test/java/fr/xephi/authme/datasource/converter/LoginSecurityConverterTest.java @@ -27,6 +27,8 @@ import java.sql.Statement; import static fr.xephi.authme.AuthMeMatchers.equalToHash; import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -71,16 +73,19 @@ public class LoginSecurityConverterTest { assertThat(captor.getAllValues().get(0).getNickname(), equalTo("player1")); assertThat(captor.getAllValues().get(0).getRealName(), equalTo("Player1")); assertThat(captor.getAllValues().get(0).getLastLogin(), equalTo(1494242093652L)); + assertThat(captor.getAllValues().get(0).getRegistrationDate(), equalTo(1494242093400L)); assertThat(captor.getAllValues().get(0).getPassword(), equalToHash("$2a$10$E1Ri7XKeIIBv4qVaiPplgepT7QH9xGFh3hbHfcmCjq7hiW.UBTiGK")); - assertThat(captor.getAllValues().get(0).getIp(), equalTo("127.0.0.1")); + assertThat(captor.getAllValues().get(0).getLastIp(), equalTo("127.0.0.1")); assertThat(captor.getAllValues().get(1).getNickname(), equalTo("player2")); assertThat(captor.getAllValues().get(1).getLastLogin(), equalTo(1494242174589L)); - assertThat(captor.getAllValues().get(1).getIp(), equalTo("127.4.5.6")); + assertThat(captor.getAllValues().get(1).getLastIp(), equalTo("127.4.5.6")); assertThat(captor.getAllValues().get(2).getRealName(), equalTo("Player3")); assertThat(captor.getAllValues().get(2).getPassword(), equalToHash("$2a$10$WFui8KSXMLDOVXKFpCLyPukPi4M82w1cv/rNojsAnwJjba3pp8sba")); assertThat(captor.getAllValues().get(2), hasAuthLocation(14.24, 67.99, -12.83, "hubb", -10f, 185f)); + assertThat(captor.getAllValues().get(2).getLastIp(), equalTo("127.0.0.1")); + assertIsCloseTo(captor.getAllValues().get(2).getRegistrationDate(), System.currentTimeMillis(), 500L); } @Test @@ -99,11 +104,12 @@ public class LoginSecurityConverterTest { assertThat(captor.getAllValues().get(0).getRealName(), equalTo("Player1")); assertThat(captor.getAllValues().get(0).getLastLogin(), equalTo(1494242093000L)); assertThat(captor.getAllValues().get(0).getPassword(), equalToHash("$2a$10$E1Ri7XKeIIBv4qVaiPplgepT7QH9xGFh3hbHfcmCjq7hiW.UBTiGK")); - assertThat(captor.getAllValues().get(0).getIp(), equalTo("127.0.0.1")); + assertThat(captor.getAllValues().get(0).getLastIp(), equalTo("127.0.0.1")); + assertThat(captor.getAllValues().get(0).getRegistrationDate(), equalTo(1494194400000L)); assertThat(captor.getAllValues().get(1).getNickname(), equalTo("player2")); assertThat(captor.getAllValues().get(1).getLastLogin(), equalTo(1489317753000L)); - assertThat(captor.getAllValues().get(1).getIp(), equalTo("127.4.5.6")); + assertThat(captor.getAllValues().get(1).getLastIp(), equalTo("127.4.5.6")); assertThat(captor.getAllValues().get(2).getRealName(), equalTo("Player3")); assertThat(captor.getAllValues().get(2).getPassword(), equalToHash("$2a$10$WFui8KSXMLDOVXKFpCLyPukPi4M82w1cv/rNojsAnwJjba3pp8sba")); @@ -129,4 +135,8 @@ public class LoginSecurityConverterTest { } return connection; } + + private static void assertIsCloseTo(long value1, long value2, long tolerance) { + assertThat(Math.abs(value1 - value2), not(greaterThan(tolerance))); + } } diff --git a/src/test/java/fr/xephi/authme/process/register/executors/EmailRegisterExecutorProviderTest.java b/src/test/java/fr/xephi/authme/process/register/executors/EmailRegisterExecutorProviderTest.java index d1c4021a4..891d4271e 100644 --- a/src/test/java/fr/xephi/authme/process/register/executors/EmailRegisterExecutorProviderTest.java +++ b/src/test/java/fr/xephi/authme/process/register/executors/EmailRegisterExecutorProviderTest.java @@ -12,8 +12,6 @@ import fr.xephi.authme.security.PasswordSecurity; import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.service.CommonService; import fr.xephi.authme.settings.properties.EmailSettings; -import org.bukkit.Location; -import org.bukkit.World; import org.bukkit.entity.Player; import org.junit.Test; import org.junit.runner.RunWith; @@ -22,9 +20,10 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData; -import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation; import static fr.xephi.authme.AuthMeMatchers.stringWithLength; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.BDDMockito.given; @@ -116,17 +115,15 @@ public class EmailRegisterExecutorProviderTest { Player player = mock(Player.class); TestHelper.mockPlayerIp(player, "123.45.67.89"); given(player.getName()).willReturn("Veronica"); - World world = mock(World.class); - given(world.getName()).willReturn("someWorld"); - given(player.getLocation()).willReturn(new Location(world, 48, 96, 144)); EmailRegisterParams params = EmailRegisterParams.of(player, "test@example.com"); // when PlayerAuth auth = executor.buildPlayerAuth(params); // then - assertThat(auth, hasAuthBasicData("veronica", "Veronica", "test@example.com", "123.45.67.89")); - assertThat(auth, hasAuthLocation(48, 96, 144, "someWorld", 0, 0)); + assertThat(auth, hasAuthBasicData("veronica", "Veronica", "test@example.com", "127.0.0.1")); + assertThat(auth.getRegistrationIp(), equalTo("123.45.67.89")); + assertIsCloseTo(auth.getRegistrationDate(), System.currentTimeMillis(), 1000); assertThat(auth.getPassword().getHash(), stringWithLength(12)); } @@ -167,4 +164,7 @@ public class EmailRegisterExecutorProviderTest { verifyZeroInteractions(syncProcessManager); } + private static void assertIsCloseTo(long value1, long value2, long tolerance) { + assertThat(Math.abs(value1 - value2), not(greaterThan(tolerance))); + } } diff --git a/src/test/java/fr/xephi/authme/process/register/executors/PasswordRegisterExecutorTest.java b/src/test/java/fr/xephi/authme/process/register/executors/PasswordRegisterExecutorTest.java index 9866cc5a0..cf471e477 100644 --- a/src/test/java/fr/xephi/authme/process/register/executors/PasswordRegisterExecutorTest.java +++ b/src/test/java/fr/xephi/authme/process/register/executors/PasswordRegisterExecutorTest.java @@ -13,8 +13,6 @@ import fr.xephi.authme.service.ValidationService; import fr.xephi.authme.service.ValidationService.ValidationResult; import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.RegistrationSettings; -import org.bukkit.Location; -import org.bukkit.World; import org.bukkit.entity.Player; import org.junit.Test; import org.junit.runner.RunWith; @@ -24,8 +22,9 @@ import org.mockito.junit.MockitoJUnitRunner; import static fr.xephi.authme.AuthMeMatchers.equalToHash; import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData; -import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.BDDMockito.given; @@ -98,17 +97,15 @@ public class PasswordRegisterExecutorTest { invocation -> new HashedPassword(invocation.getArgument(0))); Player player = mockPlayerWithName("S1m0N"); TestHelper.mockPlayerIp(player, "123.45.67.89"); - World world = mock(World.class); - given(world.getName()).willReturn("someWorld"); - given(player.getLocation()).willReturn(new Location(world, 48, 96, 144, 1.1f, 0.28f)); PasswordRegisterParams params = PasswordRegisterParams.of(player, "pass", "mail@example.org"); // when PlayerAuth auth = executor.buildPlayerAuth(params); // then - assertThat(auth, hasAuthBasicData("s1m0n", "S1m0N", "mail@example.org", "123.45.67.89")); - assertThat(auth, hasAuthLocation(48, 96, 144, "someWorld", 1.1f, 0.28f)); + assertThat(auth, hasAuthBasicData("s1m0n", "S1m0N", "mail@example.org", "127.0.0.1")); + assertThat(auth.getRegistrationIp(), equalTo("123.45.67.89")); + assertIsCloseTo(auth.getRegistrationDate(), System.currentTimeMillis(), 500); assertThat(auth.getPassword(), equalToHash("pass")); } @@ -149,4 +146,8 @@ public class PasswordRegisterExecutorTest { given(player.getName()).willReturn(name); return player; } + + private static void assertIsCloseTo(long value1, long value2, long tolerance) { + assertThat(Math.abs(value1 - value2), not(greaterThan(tolerance))); + } } diff --git a/src/test/java/fr/xephi/authme/process/register/executors/PlayerAuthBuilderHelperTest.java b/src/test/java/fr/xephi/authme/process/register/executors/PlayerAuthBuilderHelperTest.java index fd34a0572..0ac7c0643 100644 --- a/src/test/java/fr/xephi/authme/process/register/executors/PlayerAuthBuilderHelperTest.java +++ b/src/test/java/fr/xephi/authme/process/register/executors/PlayerAuthBuilderHelperTest.java @@ -3,13 +3,13 @@ package fr.xephi.authme.process.register.executors; import fr.xephi.authme.TestHelper; import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.security.crypts.HashedPassword; -import org.bukkit.Location; -import org.bukkit.World; import org.bukkit.entity.Player; import org.junit.Test; +import static fr.xephi.authme.AuthMeMatchers.equalToHash; import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData; -import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.lessThan; import static org.junit.Assert.assertThat; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -26,10 +26,6 @@ public class PlayerAuthBuilderHelperTest { given(player.getName()).willReturn("Noah"); String ip = "192.168.34.47"; TestHelper.mockPlayerIp(player, ip); - World world = mock(World.class); - given(world.getName()).willReturn("worldName"); - Location location = new Location(world, 123, 80, -99, 2.45f, 7.61f); - given(player.getLocation()).willReturn(location); HashedPassword hashedPassword = new HashedPassword("myHash0001"); String email = "test@example.org"; @@ -37,8 +33,10 @@ public class PlayerAuthBuilderHelperTest { PlayerAuth auth = PlayerAuthBuilderHelper.createPlayerAuth(player, hashedPassword, email); // then - assertThat(auth, hasAuthBasicData("noah", "Noah", email, ip)); - assertThat(auth, hasAuthLocation(123, 80, -99, "worldName", 2.45f, 7.61f)); + assertThat(auth, hasAuthBasicData("noah", "Noah", email, "127.0.0.1")); + assertThat(auth.getRegistrationIp(), equalTo("192.168.34.47")); + assertThat(Math.abs(auth.getRegistrationDate() - System.currentTimeMillis()), lessThan(1000L)); + assertThat(auth.getPassword(), equalToHash("myHash0001")); } @Test diff --git a/src/test/resources/fr/xephi/authme/datasource/converter/LoginSecurity.db b/src/test/resources/fr/xephi/authme/datasource/converter/LoginSecurity.db index 7dc6336b9..5f989c9b2 100644 Binary files a/src/test/resources/fr/xephi/authme/datasource/converter/LoginSecurity.db and b/src/test/resources/fr/xephi/authme/datasource/converter/LoginSecurity.db differ diff --git a/src/test/resources/fr/xephi/authme/datasource/sql-initialize.sql b/src/test/resources/fr/xephi/authme/datasource/sql-initialize.sql index 8edcfe26d..699acf6db 100644 --- a/src/test/resources/fr/xephi/authme/datasource/sql-initialize.sql +++ b/src/test/resources/fr/xephi/authme/datasource/sql-initialize.sql @@ -4,23 +4,24 @@ CREATE TABLE authme ( id INTEGER AUTO_INCREMENT, username VARCHAR(255) NOT NULL UNIQUE, password VARCHAR(255) NOT NULL, - ip VARCHAR(40) NOT NULL, + ip VARCHAR(40), lastlogin BIGINT, + regdate BIGINT NOT NULL, + regip VARCHAR(40), x DOUBLE NOT NULL DEFAULT '0.0', y DOUBLE NOT NULL DEFAULT '0.0', z DOUBLE NOT NULL DEFAULT '0.0', world VARCHAR(255) NOT NULL DEFAULT 'world', yaw FLOAT, pitch FLOAT, - email VARCHAR(255) DEFAULT 'your@email.com', - isLogged INT DEFAULT '0', realname VARCHAR(255) NOT NULL DEFAULT 'Player', + email VARCHAR(255), + isLogged INT DEFAULT '0', + realname VARCHAR(255) NOT NULL DEFAULT 'Player', salt varchar(255), - recoverycode VARCHAR(20), - recoveryexpiration BIGINT, CONSTRAINT table_const_prim PRIMARY KEY (id) ); -INSERT INTO authme (id, username, password, ip, lastlogin, x, y, z, world, yaw, pitch, email, isLogged, realname, salt) -VALUES (1,'bobby','$SHA$11aa0706173d7272$dbba966','123.45.67.89',1449136800,1.05,2.1,4.2,'world',-0.44,2.77,'your@email.com',0,'Bobby',NULL); -INSERT INTO authme (id, username, password, ip, lastlogin, x, y, z, world, yaw, pitch, email, isLogged, realname, salt) -VALUES (NULL,'user','b28c32f624a4eb161d6adc9acb5bfc5b','34.56.78.90',1453242857,124.1,76.3,-127.8,'nether',0.23,4.88,'user@example.org',0,'user','f750ba32'); +INSERT INTO authme (id, username, password, ip, lastlogin, x, y, z, world, yaw, pitch, email, isLogged, realname, salt, regdate, regip) +VALUES (1,'bobby','$SHA$11aa0706173d7272$dbba966','123.45.67.89',1449136800,1.05,2.1,4.2,'world',-0.44,2.77,'your@email.com',0,'Bobby',NULL,1436778723,'127.0.4.22'); +INSERT INTO authme (id, username, password, ip, lastlogin, x, y, z, world, yaw, pitch, email, isLogged, realname, salt, regdate) +VALUES (NULL,'user','b28c32f624a4eb161d6adc9acb5bfc5b','34.56.78.90',1453242857,124.1,76.3,-127.8,'nether',0.23,4.88,'user@example.org',0,'user','f750ba32',0);