#792 Add columns for registration IP and registration date

- Add columns for reg date and IP
- Rename "ip" to "last IP"
This commit is contained in:
ljacqu 2017-10-14 17:37:34 +02:00
parent 1487fc0d9e
commit 52d6476058
37 changed files with 362 additions and 235 deletions

View File

@ -178,6 +178,7 @@ public class NewAPI {
.name(name) .name(name)
.password(result) .password(result)
.realName(playerName) .realName(playerName)
.registrationDate(System.currentTimeMillis())
.build(); .build();
return dataSource.saveAuth(auth); return dataSource.saveAuth(auth);
} }

View File

@ -128,7 +128,7 @@ public class AuthMeApi {
* Get the last location of an online player. * Get the last location of an online player.
* *
* @param player The player to process * @param player The player to process
* @return Location The location of the player * @return The location of the player
*/ */
public Location getLastLocation(Player player) { public Location getLastLocation(Player player) {
PlayerAuth auth = playerCache.getAuth(player.getName()); PlayerAuth auth = playerCache.getAuth(player.getName());
@ -143,7 +143,7 @@ public class AuthMeApi {
* Get the last ip address of a player. * Get the last ip address of a player.
* *
* @param playerName The name of the player to process * @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) { public String getLastIp(String playerName) {
PlayerAuth auth = playerCache.getAuth(playerName); PlayerAuth auth = playerCache.getAuth(playerName);
@ -151,7 +151,7 @@ public class AuthMeApi {
auth = dataSource.getAuth(playerName); auth = dataSource.getAuth(playerName);
} }
if (auth != null) { if (auth != null) {
return auth.getIp(); return auth.getLastIp();
} }
return null; return null;
} }
@ -160,7 +160,7 @@ public class AuthMeApi {
* Get user names by ip. * Get user names by ip.
* *
* @param address The ip address to process * @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<String> getNamesByIp(String address) { public List<String> getNamesByIp(String address) {
return dataSource.getAllAuthsByIp(address); return dataSource.getAllAuthsByIp(address);
@ -170,11 +170,11 @@ public class AuthMeApi {
* Get the last login date of a player. * Get the last login date of a player.
* *
* @param playerName The name of the player to process * @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) { public Date getLastLogin(String playerName) {
PlayerAuth auth = playerCache.getAuth(playerName); PlayerAuth auth = playerCache.getAuth(playerName);
if(auth == null) { if (auth == null) {
auth = dataSource.getAuth(playerName); auth = dataSource.getAuth(playerName);
} }
if (auth != null) { if (auth != null) {
@ -223,6 +223,7 @@ public class AuthMeApi {
.name(name) .name(name)
.password(result) .password(result)
.realName(playerName) .realName(playerName)
.registrationDate(System.currentTimeMillis())
.build(); .build();
return dataSource.saveAuth(auth); return dataSource.saveAuth(auth);
} }

View File

@ -54,7 +54,7 @@ public class AccountsCommand implements ExecutableCommand {
return; return;
} }
List<String> accountList = dataSource.getAllAuthsByIp(auth.getIp()); List<String> accountList = dataSource.getAllAuthsByIp(auth.getLastIp());
if (accountList.isEmpty()) { if (accountList.isEmpty()) {
commonService.send(sender, MessageKey.UNKNOWN_USER); commonService.send(sender, MessageKey.UNKNOWN_USER);
} else if (accountList.size() == 1) { } else if (accountList.size() == 1) {

View File

@ -1,7 +1,10 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.command.ExecutableCommand; 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.service.BukkitService;
import fr.xephi.authme.util.PlayerUtils;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -13,18 +16,26 @@ public class GetIpCommand implements ExecutableCommand {
@Inject @Inject
private BukkitService bukkitService; private BukkitService bukkitService;
@Inject
private DataSource dataSource;
@Override @Override
public void executeCommand(CommandSender sender, List<String> arguments) { public void executeCommand(CommandSender sender, List<String> arguments) {
// Get the player query
String playerName = arguments.get(0); String playerName = arguments.get(0);
Player player = bukkitService.getPlayerExact(playerName); Player player = bukkitService.getPlayerExact(playerName);
if (player == null) { PlayerAuth auth = dataSource.getAuth(playerName);
sender.sendMessage("The player is not online");
return; 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() if (auth == null) {
+ ":" + player.getAddress().getPort()); 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());
}
} }
} }

View File

@ -45,6 +45,6 @@ public class LastLoginCommand implements ExecutableCommand {
// Show the player status // Show the player status
sender.sendMessage("[AuthMe] " + playerName + " last login: " + date.toString()); sender.sendMessage("[AuthMe] " + playerName + " last login: " + date.toString());
sender.sendMessage("[AuthMe] The player " + playerName + " last logged in " + lastLoginMessage + " ago."); 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());
} }
} }

View File

@ -64,6 +64,7 @@ public class RegisterAdminCommand implements ExecutableCommand {
.name(playerNameLowerCase) .name(playerNameLowerCase)
.realName(playerName) .realName(playerName)
.password(hashedPassword) .password(hashedPassword)
.registrationDate(System.currentTimeMillis())
.build(); .build();
if (!dataSource.saveAuth(auth)) { if (!dataSource.saveAuth(auth)) {

View File

@ -77,8 +77,8 @@ class CountryLookup implements DebugSection {
if (auth == null) { if (auth == null) {
sender.sendMessage("No player with name '" + name + "'"); sender.sendMessage("No player with name '" + name + "'");
} else { } else {
sender.sendMessage("Player '" + name + "' has IP address " + auth.getIp()); sender.sendMessage("Player '" + name + "' has IP address " + auth.getLastIp());
outputInfoForIpAddr(sender, auth.getIp()); outputInfoForIpAddr(sender, auth.getLastIp());
} }
} }
} }

View File

@ -65,10 +65,12 @@ class PlayerAuthViewer implements DebugSection {
*/ */
private void displayAuthToSender(PlayerAuth auth, CommandSender sender) { private void displayAuthToSender(PlayerAuth auth, CommandSender sender) {
sender.sendMessage(ChatColor.GOLD + "[AuthMe] Player " + auth.getNickname() + " / " + auth.getRealName()); 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: " sender.sendMessage("Quit location: "
+ formatLocation(auth.getQuitLocX(), auth.getQuitLocY(), auth.getQuitLocZ(), auth.getWorld())); + 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(); HashedPassword hashedPass = auth.getPassword();
sender.sendMessage("Hash / salt (partial): '" + safeSubstring(hashedPass.getHash(), 6) 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 * @param timestamp the timestamp to format (nullable)
* @return the last login as human readable date * @return the formatted timestamp
*/ */
private static String formatLastLogin(PlayerAuth auth) { private static String formatDate(Long timestamp) {
long lastLogin = auth.getLastLogin(); if (timestamp == null) {
if (lastLogin == 0) { return "Not available (null)";
return "Never (0)"; } else if (timestamp == 0) {
return "Not available (0)";
} else { } 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); return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(date);
} }
} }

View File

@ -3,6 +3,8 @@ package fr.xephi.authme.data.auth;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;
import org.bukkit.Location; import org.bukkit.Location;
import java.util.Objects;
import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -18,9 +20,11 @@ public class PlayerAuth {
private String realName; private String realName;
private HashedPassword password; private HashedPassword password;
private String email; private String email;
private String ip; private String lastIp;
private int groupId; private int groupId;
private long lastLogin; private long lastLogin;
private String registrationIp;
private long registrationDate;
// Fields storing the player's quit location // Fields storing the player's quit location
private double x; private double x;
private double y; private double y;
@ -29,13 +33,6 @@ public class PlayerAuth {
private float yaw; private float yaw;
private float pitch; private float pitch;
/**
* @param serialized String
*/
public PlayerAuth(String serialized) {
this.deserialize(serialized);
}
/** /**
* Hidden constructor. * Hidden constructor.
* *
@ -112,12 +109,12 @@ public class PlayerAuth {
return pitch; return pitch;
} }
public String getIp() { public String getLastIp() {
return ip; return lastIp;
} }
public void setIp(String ip) { public void setLastIp(String lastIp) {
this.ip = ip; this.lastIp = lastIp;
} }
public long getLastLogin() { public long getLastLogin() {
@ -144,76 +141,45 @@ public class PlayerAuth {
this.password = password; this.password = password;
} }
public String getRegistrationIp() {
return registrationIp;
}
public long getRegistrationDate() {
return registrationDate;
}
public void setRegistrationDate(long registrationDate) {
this.registrationDate = registrationDate;
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof PlayerAuth)) { if (!(obj instanceof PlayerAuth)) {
return false; return false;
} }
PlayerAuth other = (PlayerAuth) obj; 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 @Override
public int hashCode() { public int hashCode() {
int hashCode = 7; int hashCode = 7;
hashCode = 71 * hashCode + (this.nickname != null ? this.nickname.hashCode() : 0); 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; return hashCode;
} }
@Override @Override
public String toString() { public String toString() {
return "Player : " + nickname + " | " + realName return "Player : " + nickname + " | " + realName
+ " ! IP : " + ip + " ! IP : " + lastIp
+ " ! LastLogin : " + lastLogin + " ! LastLogin : " + lastLogin
+ " ! LastPosition : " + x + "," + y + "," + z + "," + world + " ! LastPosition : " + x + "," + y + "," + z + "," + world
+ " ! Email : " + email + " ! Email : " + email
+ " ! Password : {" + password.getHash() + ", " + password.getSalt() + "}"; + " ! 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() { public static Builder builder() {
return new Builder(); return new Builder();
} }
@ -222,10 +188,12 @@ public class PlayerAuth {
private String name; private String name;
private String realName; private String realName;
private HashedPassword password; private HashedPassword password;
private String ip; private String lastIp;
private String email; private String email;
private int groupId = -1; private int groupId = -1;
private long lastLogin = System.currentTimeMillis(); private long lastLogin = System.currentTimeMillis();
private String registrationIp;
private Long registrationDate;
private double x; private double x;
private double y; private double y;
@ -245,9 +213,11 @@ public class PlayerAuth {
auth.realName = firstNonNull(realName, "Player"); auth.realName = firstNonNull(realName, "Player");
auth.password = firstNonNull(password, new HashedPassword("")); auth.password = firstNonNull(password, new HashedPassword(""));
auth.email = firstNonNull(email, "your@email.com"); 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.groupId = groupId;
auth.lastLogin = lastLogin; auth.lastLogin = lastLogin;
auth.registrationIp = registrationIp;
auth.registrationDate = registrationDate == null ? System.currentTimeMillis() : registrationDate;
auth.x = x; auth.x = x;
auth.y = y; auth.y = y;
@ -277,8 +247,8 @@ public class PlayerAuth {
return password(new HashedPassword(hash, salt)); return password(new HashedPassword(hash, salt));
} }
public Builder ip(String ip) { public Builder lastIp(String lastIp) {
this.ip = ip; this.lastIp = lastIp;
return this; return this;
} }
@ -342,5 +312,15 @@ public class PlayerAuth {
this.email = email; this.email = email;
return this; return this;
} }
public Builder registrationIp(String ip) {
this.registrationIp = ip;
return this;
}
public Builder registrationDate(long date) {
this.registrationDate = date;
return this;
}
} }
} }

View File

@ -14,7 +14,7 @@ public final class Columns {
public final String REAL_NAME; public final String REAL_NAME;
public final String PASSWORD; public final String PASSWORD;
public final String SALT; public final String SALT;
public final String IP; public final String LAST_IP;
public final String LAST_LOGIN; public final String LAST_LOGIN;
public final String GROUP; public final String GROUP;
public final String LASTLOC_X; public final String LASTLOC_X;
@ -26,24 +26,28 @@ public final class Columns {
public final String EMAIL; public final String EMAIL;
public final String ID; public final String ID;
public final String IS_LOGGED; public final String IS_LOGGED;
public final String REGISTRATION_DATE;
public final String REGISTRATION_IP;
public Columns(Settings settings) { public Columns(Settings settings) {
NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME); NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME);
REAL_NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_REALNAME); REAL_NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_REALNAME);
PASSWORD = settings.getProperty(DatabaseSettings.MYSQL_COL_PASSWORD); PASSWORD = settings.getProperty(DatabaseSettings.MYSQL_COL_PASSWORD);
SALT = settings.getProperty(DatabaseSettings.MYSQL_COL_SALT); SALT = settings.getProperty(DatabaseSettings.MYSQL_COL_SALT);
IP = settings.getProperty(DatabaseSettings.MYSQL_COL_IP); LAST_IP = settings.getProperty(DatabaseSettings.MYSQL_COL_LAST_IP);
LAST_LOGIN = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOGIN); LAST_LOGIN = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOGIN);
GROUP = settings.getProperty(DatabaseSettings.MYSQL_COL_GROUP); GROUP = settings.getProperty(DatabaseSettings.MYSQL_COL_GROUP);
LASTLOC_X = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_X); LASTLOC_X = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_X);
LASTLOC_Y = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_Y); LASTLOC_Y = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_Y);
LASTLOC_Z = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_Z); LASTLOC_Z = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_Z);
LASTLOC_WORLD = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_WORLD); LASTLOC_WORLD = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_WORLD);
LASTLOC_YAW = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_YAW); LASTLOC_YAW = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_YAW);
LASTLOC_PITCH = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_PITCH); LASTLOC_PITCH = settings.getProperty(DatabaseSettings.MYSQL_COL_LASTLOC_PITCH);
EMAIL = settings.getProperty(DatabaseSettings.MYSQL_COL_EMAIL); EMAIL = settings.getProperty(DatabaseSettings.MYSQL_COL_EMAIL);
ID = settings.getProperty(DatabaseSettings.MYSQL_COL_ID); ID = settings.getProperty(DatabaseSettings.MYSQL_COL_ID);
IS_LOGGED = settings.getProperty(DatabaseSettings.MYSQL_COL_ISLOGGED); 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);
} }
} }

View File

@ -79,7 +79,7 @@ public class FlatFile implements DataSource {
return false; return false;
} }
try (BufferedWriter bw = new BufferedWriter(new FileWriter(source, true))) { 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.getLastLogin() + ":" + auth.getQuitLocX() + ":" + auth.getQuitLocY()
+ ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n"); + ":" + auth.getQuitLocZ() + ":" + auth.getWorld() + ":" + auth.getEmail() + "\n");
} catch (IOException ex) { } catch (IOException ex) {
@ -139,7 +139,7 @@ public class FlatFile implements DataSource {
newAuth = buildAuthFromArray(args); newAuth = buildAuthFromArray(args);
if (newAuth != null) { if (newAuth != null) {
newAuth.setLastLogin(auth.getLastLogin()); newAuth.setLastLogin(auth.getLastLogin());
newAuth.setIp(auth.getIp()); newAuth.setLastIp(auth.getLastIp());
} }
break; break;
} }
@ -393,7 +393,7 @@ public class FlatFile implements DataSource {
PlayerAuth.Builder builder = PlayerAuth.builder() PlayerAuth.Builder builder = PlayerAuth.builder()
.name(args[0]).realName(args[0]).password(args[1], null); .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 >= 4) builder.lastLogin(Long.parseLong(args[3]));
if (args.length >= 7) { if (args.length >= 7) {
builder.locX(Double.parseDouble(args[4])) builder.locX(Double.parseDouble(args[4]))

View File

@ -189,9 +189,9 @@ public class MySQL implements DataSource {
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.SALT + " VARCHAR(255);"); 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 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)) { if (isColumnMissing(md, col.LAST_LOGIN)) {
@ -201,6 +201,16 @@ public class MySQL implements DataSource {
migrateLastLoginColumn(con, md); 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)) { if (isColumnMissing(md, col.LASTLOC_X)) {
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN "
+ col.LASTLOC_X + " DOUBLE NOT NULL DEFAULT '0.0' AFTER " + col.LAST_LOGIN + " , ADD " + 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) { public boolean saveAuth(PlayerAuth auth) {
try (Connection con = getConnection()) { try (Connection con = getConnection()) {
String sql; String sql;
boolean useSalt = !col.SALT.isEmpty() || !StringUtils.isEmpty(auth.getPassword().getSalt()); boolean useSalt = !col.SALT.isEmpty() || !StringUtils.isEmpty(auth.getPassword().getSalt());
sql = "INSERT INTO " + tableName + "(" sql = "INSERT INTO " + tableName + "("
+ col.NAME + "," + col.PASSWORD + "," + col.IP + "," + col.NAME + "," + col.PASSWORD + "," + col.REAL_NAME
+ col.LAST_LOGIN + "," + col.REAL_NAME + "," + col.EMAIL + "," + col.EMAIL + "," + col.REGISTRATION_DATE + "," + col.REGISTRATION_IP
+ (useSalt ? "," + col.SALT : "") + (useSalt ? "," + col.SALT : "")
+ ") VALUES (?,?,?,?,?,?" + (useSalt ? ",?" : "") + ");"; + ") VALUES (?,?,?,?,?,?" + (useSalt ? ",?" : "") + ");";
try (PreparedStatement pst = con.prepareStatement(sql)) { try (PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, auth.getNickname()); pst.setString(1, auth.getNickname());
pst.setString(2, auth.getPassword().getHash()); pst.setString(2, auth.getPassword().getHash());
pst.setString(3, auth.getIp()); pst.setString(3, auth.getRealName());
pst.setLong(4, auth.getLastLogin()); pst.setString(4, auth.getEmail());
pst.setString(5, auth.getRealName()); pst.setObject(5, auth.getRegistrationDate());
pst.setString(6, auth.getEmail()); pst.setString(6, auth.getRegistrationIp());
if (useSalt) { if (useSalt) {
pst.setString(7, auth.getPassword().getSalt()); pst.setString(7, auth.getPassword().getSalt());
} }
@ -382,9 +391,9 @@ public class MySQL implements DataSource {
@Override @Override
public boolean updateSession(PlayerAuth auth) { public boolean updateSession(PlayerAuth auth) {
String sql = "UPDATE " + tableName + " SET " 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)) { 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.setLong(2, auth.getLastLogin());
pst.setString(3, auth.getRealName()); pst.setString(3, auth.getRealName());
pst.setString(4, auth.getNickname()); pst.setString(4, auth.getNickname());
@ -479,7 +488,7 @@ public class MySQL implements DataSource {
@Override @Override
public List<String> getAllAuthsByIp(String ip) { public List<String> getAllAuthsByIp(String ip) {
List<String> result = new ArrayList<>(); List<String> 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)) { try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, ip); pst.setString(1, ip);
try (ResultSet rs = pst.executeQuery()) { try (ResultSet rs = pst.executeQuery()) {
@ -665,15 +674,17 @@ public class MySQL implements DataSource {
.realName(row.getString(col.REAL_NAME)) .realName(row.getString(col.REAL_NAME))
.password(row.getString(col.PASSWORD), salt) .password(row.getString(col.PASSWORD), salt)
.lastLogin(row.getLong(col.LAST_LOGIN)) .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)) .locWorld(row.getString(col.LASTLOC_WORLD))
.locX(row.getDouble(col.LASTLOC_X)) .locX(row.getDouble(col.LASTLOC_X))
.locY(row.getDouble(col.LASTLOC_Y)) .locY(row.getDouble(col.LASTLOC_Y))
.locZ(row.getDouble(col.LASTLOC_Z)) .locZ(row.getDouble(col.LASTLOC_Z))
.locYaw(row.getFloat(col.LASTLOC_YAW)) .locYaw(row.getFloat(col.LASTLOC_YAW))
.locPitch(row.getFloat(col.LASTLOC_PITCH)) .locPitch(row.getFloat(col.LASTLOC_PITCH))
.email(row.getString(col.EMAIL))
.groupId(group)
.build(); .build();
} }
@ -706,6 +717,7 @@ public class MySQL implements DataSource {
* Performs conversion of lastlogin column from timestamp type to bigint. * Performs conversion of lastlogin column from timestamp type to bigint.
* *
* @param con connection to the database * @param con connection to the database
* @see <a href="https://github.com/AuthMe/AuthMeReloaded/issues/477">#477</a>
*/ */
private void migrateLastLoginColumnFromTimestamp(Connection con) throws SQLException { private void migrateLastLoginColumnFromTimestamp(Connection con) throws SQLException {
ConsoleLogger.info("Migrating lastlogin column from timestamp to bigint"); ConsoleLogger.info("Migrating lastlogin column from timestamp to bigint");
@ -721,7 +733,7 @@ public class MySQL implements DataSource {
// Create lastlogin column // Create lastlogin column
sql = String.format("ALTER TABLE %s ADD COLUMN %s " sql = String.format("ALTER TABLE %s ADD COLUMN %s "
+ "BIGINT NOT NULL DEFAULT 0 AFTER %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(); con.prepareStatement(sql).execute();
// Set values of lastlogin based on lastlogin_old // 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. * Performs conversion of lastlogin column from int to bigint.
* *
* @param con connection to the database * @param con connection to the database
* @see <a href="https://github.com/AuthMe/AuthMeReloaded/issues/887">
* #887: Migrate lastlogin column from int32 to bigint</a>
*/ */
private void migrateLastLoginColumnFromInt(Connection con) throws SQLException { private void migrateLastLoginColumnFromInt(Connection con) throws SQLException {
// Change from int to bigint // Change from int to bigint

View File

@ -94,9 +94,9 @@ public class SQLite implements DataSource {
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.SALT + " VARCHAR(255);"); 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 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)) { if (isColumnMissing(md, col.LAST_LOGIN)) {
@ -104,6 +104,16 @@ public class SQLite implements DataSource {
+ " ADD COLUMN " + col.LAST_LOGIN + " TIMESTAMP;"); + " 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)) { if (isColumnMissing(md, col.LASTLOC_X)) {
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_X st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.LASTLOC_X
+ " DOUBLE NOT NULL DEFAULT '0.0';"); + " DOUBLE NOT NULL DEFAULT '0.0';");
@ -209,6 +219,7 @@ public class SQLite implements DataSource {
@Override @Override
public boolean saveAuth(PlayerAuth auth) { public boolean saveAuth(PlayerAuth auth) {
PreparedStatement pst = null;
try { try {
HashedPassword password = auth.getPassword(); HashedPassword password = auth.getPassword();
if (col.SALT.isEmpty()) { 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 " ConsoleLogger.warning("Warning! Detected hashed password with separate salt but the salt column "
+ "is not set in the config!"); + "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 + pst = con.prepareStatement("INSERT INTO " + tableName + "(" + col.NAME + "," + col.PASSWORD
") VALUES (?,?,?,?,?,?);")) { + "," + col.REAL_NAME + "," + col.EMAIL
pst.setString(1, auth.getNickname()); + "," + col.REGISTRATION_DATE + "," + col.REGISTRATION_IP
pst.setString(2, password.getHash()); + ") VALUES (?,?,?,?,?,?);");
pst.setString(3, auth.getIp()); pst.setString(1, auth.getNickname());
pst.setLong(4, auth.getLastLogin()); pst.setString(2, password.getHash());
pst.setString(5, auth.getRealName()); pst.setString(3, auth.getRealName());
pst.setString(6, auth.getEmail()); pst.setString(4, auth.getEmail());
pst.executeUpdate(); pst.setLong(5, auth.getRegistrationDate());
} pst.setString(6, auth.getRegistrationIp());
pst.executeUpdate();
} else { } else {
try (PreparedStatement pst = con.prepareStatement("INSERT INTO " + tableName + "(" + col.NAME + "," + col.PASSWORD + "," pst = con.prepareStatement("INSERT INTO " + tableName + "(" + col.NAME + "," + col.PASSWORD
+ col.IP + "," + col.LAST_LOGIN + "," + col.REAL_NAME + "," + col.EMAIL + "," + col.SALT + "," + col.REAL_NAME + "," + col.EMAIL
+ ") VALUES (?,?,?,?,?,?,?);")) { + "," + col.REGISTRATION_DATE + "," + col.REGISTRATION_IP + "," + col.SALT
pst.setString(1, auth.getNickname()); + ") VALUES (?,?,?,?,?,?,?);");
pst.setString(2, password.getHash()); pst.setString(1, auth.getNickname());
pst.setString(3, auth.getIp()); pst.setString(2, password.getHash());
pst.setLong(4, auth.getLastLogin()); pst.setString(3, auth.getRealName());
pst.setString(5, auth.getRealName()); pst.setString(4, auth.getEmail());
pst.setString(6, auth.getEmail()); pst.setLong(5, auth.getRegistrationDate());
pst.setString(7, password.getSalt()); pst.setString(6, auth.getRegistrationIp());
pst.executeUpdate(); pst.setString(7, password.getSalt());
} pst.executeUpdate();
} }
} catch (SQLException ex) { } catch (SQLException ex) {
logSqlException(ex); logSqlException(ex);
} finally {
close(pst);
} }
return true; return true;
} }
@ -277,9 +291,10 @@ public class SQLite implements DataSource {
@Override @Override
public boolean updateSession(PlayerAuth auth) { 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)){ try (PreparedStatement pst = con.prepareStatement(sql)){
pst.setString(1, auth.getIp()); pst.setString(1, auth.getLastIp());
pst.setLong(2, auth.getLastLogin()); pst.setLong(2, auth.getLastLogin());
pst.setString(3, auth.getRealName()); pst.setString(3, auth.getRealName());
pst.setString(4, auth.getNickname()); pst.setString(4, auth.getNickname());
@ -388,7 +403,7 @@ public class SQLite implements DataSource {
@Override @Override
public List<String> getAllAuthsByIp(String ip) { public List<String> getAllAuthsByIp(String ip) {
List<String> countIp = new ArrayList<>(); List<String> 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)) { try (PreparedStatement pst = con.prepareStatement(sql)) {
pst.setString(1, ip); pst.setString(1, ip);
try (ResultSet rs = pst.executeQuery()) { try (ResultSet rs = pst.executeQuery()) {
@ -554,27 +569,24 @@ public class SQLite implements DataSource {
private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException { private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException {
String salt = !col.SALT.isEmpty() ? row.getString(col.SALT) : null; String salt = !col.SALT.isEmpty() ? row.getString(col.SALT) : null;
PlayerAuth.Builder authBuilder = PlayerAuth.builder() return PlayerAuth.builder()
.name(row.getString(col.NAME)) .name(row.getString(col.NAME))
.email(row.getString(col.EMAIL)) .email(row.getString(col.EMAIL))
.realName(row.getString(col.REAL_NAME)) .realName(row.getString(col.REAL_NAME))
.password(row.getString(col.PASSWORD), salt) .password(row.getString(col.PASSWORD), salt)
.lastLogin(row.getLong(col.LAST_LOGIN)) .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)) .locX(row.getDouble(col.LASTLOC_X))
.locY(row.getDouble(col.LASTLOC_Y)) .locY(row.getDouble(col.LASTLOC_Y))
.locZ(row.getDouble(col.LASTLOC_Z)) .locZ(row.getDouble(col.LASTLOC_Z))
.locWorld(row.getString(col.LASTLOC_WORLD)) .locWorld(row.getString(col.LASTLOC_WORLD))
.locYaw(row.getFloat(col.LASTLOC_YAW)) .locYaw(row.getFloat(col.LASTLOC_YAW))
.locPitch(row.getFloat(col.LASTLOC_PITCH)); .locPitch(row.getFloat(col.LASTLOC_PITCH))
.build();
String ip = row.getString(col.IP);
if (!ip.isEmpty()) {
authBuilder.ip(ip);
}
return authBuilder.build();
} }
private static void close(Statement st) { private static void close(Statement st) {
if (st != null) { if (st != null) {
try { try {

View File

@ -2,6 +2,7 @@ package fr.xephi.authme.datasource;
import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ConsoleLogger;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
/** /**
@ -20,4 +21,18 @@ final class SqlDataSourceUtils {
static void logSqlException(SQLException e) { static void logSqlException(SQLException e) {
ConsoleLogger.logException("Error during SQL operation:", 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;
}
} }

View File

@ -62,6 +62,7 @@ public abstract class AbstractDataSourceConverter<S extends DataSource> implemen
} else { } else {
adaptPlayerAuth(auth); adaptPlayerAuth(auth);
destination.saveAuth(auth); destination.saveAuth(auth);
destination.updateSession(auth);
destination.updateQuitLoc(auth); destination.updateQuitLoc(auth);
} }
} }

View File

@ -18,6 +18,7 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -94,6 +95,7 @@ public class LoginSecurityConverter implements Converter {
} else { } else {
PlayerAuth auth = buildAuthFromLoginSecurity(name, resultSet); PlayerAuth auth = buildAuthFromLoginSecurity(name, resultSet);
dataSource.saveAuth(auth); dataSource.saveAuth(auth);
dataSource.updateSession(auth);
++successfulSaves; ++successfulSaves;
} }
} }
@ -113,16 +115,17 @@ public class LoginSecurityConverter implements Converter {
* @return the created player auth object * @return the created player auth object
*/ */
private static PlayerAuth buildAuthFromLoginSecurity(String name, ResultSet resultSet) throws SQLException { 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"))
long lastLoginMillis = Optional.ofNullable(resultSet.getTimestamp("last_login")) .map(Timestamp::getTime).orElse(null);
.map(Timestamp::getTime).orElse(System.currentTimeMillis()); long regDate = Optional.ofNullable(resultSet.getDate("registration_date"))
.map(Date::getTime).orElse(System.currentTimeMillis());
return PlayerAuth.builder() return PlayerAuth.builder()
.name(name) .name(name)
.realName(name) .realName(name)
.password(resultSet.getString("password"), null) .password(resultSet.getString("password"), null)
.ip(resultSet.getString("ip_address")) .lastIp(resultSet.getString("ip_address"))
.lastLogin(lastLoginMillis) .lastLogin(lastLoginMillis)
// TODO #792: Register date .registrationDate(regDate)
.locX(resultSet.getDouble("x")) .locX(resultSet.getDouble("x"))
.locY(resultSet.getDouble("y")) .locY(resultSet.getDouble("y"))
.locZ(resultSet.getDouble("z")) .locZ(resultSet.getDouble("z"))

View File

@ -80,11 +80,11 @@ public class RakamakConverter implements Converter {
PlayerAuth auth = PlayerAuth.builder() PlayerAuth auth = PlayerAuth.builder()
.name(playerName) .name(playerName)
.realName(playerName) .realName(playerName)
.ip(ip) .lastIp(ip)
.password(psw) .password(psw)
.lastLogin(0)
.build(); .build();
database.saveAuth(auth); database.saveAuth(auth);
database.updateSession(auth);
} }
Utils.logAndSendMessage(sender, "Rakamak database has been imported correctly"); Utils.logAndSendMessage(sender, "Rakamak database has been imported correctly");
} catch (IOException ex) { } catch (IOException ex) {

View File

@ -46,6 +46,7 @@ public class RoyalAuthConverter implements Converter {
.build(); .build();
dataSource.saveAuth(auth); dataSource.saveAuth(auth);
dataSource.updateSession(auth);
} catch (Exception e) { } catch (Exception e) {
ConsoleLogger.logException("Error while trying to import " + player.getName() + " RoyalAuth data", e); ConsoleLogger.logException("Error while trying to import " + player.getName() + " RoyalAuth data", e);
} }

View File

@ -188,7 +188,7 @@ public class AsynchronousJoin implements AsynchronousProcess {
long timeSinceLastLogin = System.currentTimeMillis() - auth.getLastLogin(); long timeSinceLastLogin = System.currentTimeMillis() - auth.getLastLogin();
if(timeSinceLastLogin < 0 if(timeSinceLastLogin < 0
|| timeSinceLastLogin > (service.getProperty(PluginSettings.SESSIONS_TIMEOUT) * 60 * 1000) || 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); service.send(player, MessageKey.SESSION_EXPIRED);
} else { } else {
RestoreSessionEvent event = bukkitService.createAndCallEvent( RestoreSessionEvent event = bukkitService.createAndCallEvent(

View File

@ -215,7 +215,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
final String ip = PlayerUtils.getPlayerIp(player); final String ip = PlayerUtils.getPlayerIp(player);
auth.setRealName(player.getName()); auth.setRealName(player.getName());
auth.setLastLogin(System.currentTimeMillis()); auth.setLastLogin(System.currentTimeMillis());
auth.setIp(ip); auth.setLastIp(ip);
dataSource.updateSession(auth); dataSource.updateSession(auth);
// Successful login, so reset the captcha & temp ban count // Successful login, so reset the captcha & temp ban count
@ -227,8 +227,8 @@ public class AsynchronousLogin implements AsynchronousProcess {
service.send(player, MessageKey.LOGIN_SUCCESS); service.send(player, MessageKey.LOGIN_SUCCESS);
// Other auths // Other auths
List<String> auths = dataSource.getAllAuthsByIp(auth.getIp()); List<String> auths = dataSource.getAllAuthsByIp(auth.getLastIp());
runCommandOtherAccounts(auths, player, auth.getIp()); runCommandOtherAccounts(auths, player, auth.getLastIp());
displayOtherAccounts(auths, player); displayOtherAccounts(auths, player);
final String email = auth.getEmail(); final String email = auth.getEmail();

View File

@ -72,7 +72,7 @@ public class AsynchronousQuit implements AsynchronousProcess {
PlayerAuth auth = PlayerAuth.builder() PlayerAuth auth = PlayerAuth.builder()
.name(name) .name(name)
.realName(player.getName()) .realName(player.getName())
.ip(ip) .lastIp(ip)
.lastLogin(System.currentTimeMillis()) .lastLogin(System.currentTimeMillis())
.build(); .build();
database.updateSession(auth); database.updateSession(auth);

View File

@ -27,8 +27,8 @@ final class PlayerAuthBuilderHelper {
.realName(player.getName()) .realName(player.getName())
.password(hashedPassword) .password(hashedPassword)
.email(email) .email(email)
.ip(PlayerUtils.getPlayerIp(player)) .registrationIp(PlayerUtils.getPlayerIp(player))
.location(player.getLocation()) .registrationDate(System.currentTimeMillis())
.build(); .build();
} }
} }

View File

@ -75,14 +75,22 @@ public final class DatabaseSettings implements SettingsHolder {
public static final Property<String> MYSQL_COL_ISLOGGED = public static final Property<String> MYSQL_COL_ISLOGGED =
newProperty("DataSource.mySQLColumnLogged", "isLogged"); newProperty("DataSource.mySQLColumnLogged", "isLogged");
@Comment("Column for storing players ips") @Comment("Column for storing the player's last IP")
public static final Property<String> MYSQL_COL_IP = public static final Property<String> MYSQL_COL_LAST_IP =
newProperty("DataSource.mySQLColumnIp", "ip"); newProperty("DataSource.mySQLColumnIp", "ip");
@Comment("Column for storing players lastlogins") @Comment("Column for storing players lastlogins")
public static final Property<String> MYSQL_COL_LASTLOGIN = public static final Property<String> MYSQL_COL_LASTLOGIN =
newProperty("DataSource.mySQLColumnLastLogin", "lastlogin"); newProperty("DataSource.mySQLColumnLastLogin", "lastlogin");
@Comment("Column storing the registration date")
public static final Property<String> MYSQL_COL_REGISTER_DATE =
newProperty("DataSource.mySQLColumnRegisterDate", "regdate");
@Comment("Column for storing the IP address at the time of registration")
public static final Property<String> MYSQL_COL_REGISTER_IP =
newProperty("DataSource.mySQLColumnRegisterIp", "regip");
@Comment("Column for storing player LastLocation - X") @Comment("Column for storing player LastLocation - X")
public static final Property<String> MYSQL_COL_LASTLOC_X = public static final Property<String> MYSQL_COL_LASTLOC_X =
newProperty("DataSource.mySQLlastlocX", "x"); newProperty("DataSource.mySQLlastlocX", "x");

View File

@ -44,26 +44,48 @@ public final class AuthMeMatchers {
} }
public static Matcher<? super PlayerAuth> hasAuthBasicData(String name, String realName, public static Matcher<? super PlayerAuth> hasAuthBasicData(String name, String realName,
String email, String ip) { String email, String lastIp) {
return new TypeSafeMatcher<PlayerAuth>() { return new TypeSafeMatcher<PlayerAuth>() {
@Override @Override
public boolean matchesSafely(PlayerAuth item) { public boolean matchesSafely(PlayerAuth item) {
return Objects.equals(name, item.getNickname()) return Objects.equals(name, item.getNickname())
&& Objects.equals(realName, item.getRealName()) && Objects.equals(realName, item.getRealName())
&& Objects.equals(email, item.getEmail()) && Objects.equals(email, item.getEmail())
&& Objects.equals(ip, item.getIp()); && Objects.equals(lastIp, item.getLastIp());
} }
@Override @Override
public void describeTo(Description description) { public void describeTo(Description description) {
description.appendValue(String.format("PlayerAuth with name %s, realname %s, email %s, ip %s", description.appendValue(String.format("PlayerAuth with name %s, realname %s, email %s, lastIp %s",
name, realName, email, ip)); name, realName, email, lastIp));
} }
@Override @Override
public void describeMismatchSafely(PlayerAuth item, Description description) { public void describeMismatchSafely(PlayerAuth item, Description description) {
description.appendValue(String.format("PlayerAuth with name %s, realname %s, email %s, ip %s", description.appendValue(String.format("PlayerAuth with name %s, realname %s, email %s, lastIp %s",
item.getNickname(), item.getRealName(), item.getEmail(), item.getIp())); item.getNickname(), item.getRealName(), item.getEmail(), item.getLastIp()));
}
};
}
public static Matcher<? super PlayerAuth> hasRegistrationInfo(String registrationIp, long registrationDate) {
return new TypeSafeMatcher<PlayerAuth>() {
@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()));
} }
}; };
} }

View File

@ -146,7 +146,7 @@ public class AuthMeApiTest {
String name = "Gabriel"; String name = "Gabriel";
Player player = mockPlayerWithName(name); Player player = mockPlayerWithName(name);
PlayerAuth auth = PlayerAuth.builder().name(name) PlayerAuth auth = PlayerAuth.builder().name(name)
.ip("93.23.44.55") .lastIp("93.23.44.55")
.build(); .build();
given(playerCache.getAuth(name)).willReturn(auth); given(playerCache.getAuth(name)).willReturn(auth);

View File

@ -171,7 +171,7 @@ public class AccountsCommandTest {
private static PlayerAuth authWithIp(String ip) { private static PlayerAuth authWithIp(String ip) {
return PlayerAuth.builder() return PlayerAuth.builder()
.name("Test") .name("Test")
.ip(ip) .lastIp(ip)
.build(); .build();
} }
} }

View File

@ -1,6 +1,8 @@
package fr.xephi.authme.command.executable.authme; package fr.xephi.authme.command.executable.authme;
import fr.xephi.authme.TestHelper; 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 fr.xephi.authme.service.BukkitService;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -12,11 +14,12 @@ import org.mockito.junit.MockitoJUnitRunner;
import java.util.Collections; 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.hamcrest.Matchers.containsString;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.hamcrest.MockitoHamcrest.argThat; import static org.mockito.hamcrest.MockitoHamcrest.argThat;
@ -32,19 +35,25 @@ public class GetIpCommandTest {
@Mock @Mock
private BukkitService bukkitService; private BukkitService bukkitService;
@Mock
private DataSource dataSource;
@Test @Test
public void shouldGetIpOfPlayer() { public void shouldGetIpOfPlayer() {
// given // given
given(bukkitService.getPlayerExact(anyString())).willReturn(null); given(bukkitService.getPlayerExact(anyString())).willReturn(null);
given(dataSource.getAuth(anyString())).willReturn(null);
CommandSender sender = mock(CommandSender.class); CommandSender sender = mock(CommandSender.class);
String name = "Testt";
// when // when
command.executeCommand(sender, Collections.singletonList("Testt")); command.executeCommand(sender, Collections.singletonList(name));
// then // then
verify(bukkitService).getPlayerExact("Testt"); verify(bukkitService).getPlayerExact(name);
verify(sender).sendMessage(argThat(containsString("not online"))); verify(dataSource).getAuth(name);
verify(sender, only()).sendMessage(argThat(containsString("not registered")));
} }
@Test @Test
@ -54,6 +63,8 @@ public class GetIpCommandTest {
String ip = "123.34.56.88"; String ip = "123.34.56.88";
Player player = mockPlayer(playerName, ip); Player player = mockPlayer(playerName, ip);
given(bukkitService.getPlayerExact(playerName)).willReturn(player); 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); CommandSender sender = mock(CommandSender.class);
// when // when
@ -61,7 +72,29 @@ public class GetIpCommandTest {
// then // then
verify(bukkitService).getPlayerExact(playerName); 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) { private static Player mockPlayer(String name, String ip) {

View File

@ -65,7 +65,7 @@ public class LastLoginCommandTest {
(412 * DAY_IN_MSEC + 10 * HOUR_IN_MSEC - 9000); (412 * DAY_IN_MSEC + 10 * HOUR_IN_MSEC - 9000);
PlayerAuth auth = mock(PlayerAuth.class); PlayerAuth auth = mock(PlayerAuth.class);
given(auth.getLastLogin()).willReturn(lastLogin); 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); given(dataSource.getAuth(player)).willReturn(auth);
CommandSender sender = mock(CommandSender.class); CommandSender sender = mock(CommandSender.class);
@ -94,7 +94,7 @@ public class LastLoginCommandTest {
- (412 * DAY_IN_MSEC + 10 * HOUR_IN_MSEC - 9000); - (412 * DAY_IN_MSEC + 10 * HOUR_IN_MSEC - 9000);
PlayerAuth auth = mock(PlayerAuth.class); PlayerAuth auth = mock(PlayerAuth.class);
given(auth.getLastLogin()).willReturn(lastLogin); 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); given(dataSource.getAuth(name)).willReturn(auth);
// when // when

View File

@ -12,6 +12,7 @@ import java.util.Set;
import static fr.xephi.authme.AuthMeMatchers.equalToHash; import static fr.xephi.authme.AuthMeMatchers.equalToHash;
import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData; import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData;
import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation; 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.contains;
import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.empty; 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, 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, 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.getLastLogin(), equalTo(1449136800L));
assertThat(bobbyAuth.getPassword(), equalToHash("$SHA$11aa0706173d7272$dbba966")); assertThat(bobbyAuth.getPassword(), equalToHash("$SHA$11aa0706173d7272$dbba966"));
assertThat(userAuth, hasAuthBasicData("user", "user", "user@example.org", "34.56.78.90")); 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, hasAuthLocation(124.1, 76.3, -127.8, "nether", 0.23f, 4.88f));
assertThat(userAuth, hasRegistrationInfo(null, 0));
assertThat(userAuth.getLastLogin(), equalTo(1453242857L)); assertThat(userAuth.getLastLogin(), equalTo(1453242857L));
assertThat(userAuth.getPassword(), equalToHash("b28c32f624a4eb161d6adc9acb5bfc5b", "f750ba32")); assertThat(userAuth.getPassword(), equalToHash("b28c32f624a4eb161d6adc9acb5bfc5b", "f750ba32"));
} }
@ -211,7 +214,7 @@ public abstract class AbstractDataSourceIntegrationTest {
DataSource dataSource = getDataSource(); DataSource dataSource = getDataSource();
PlayerAuth bobby = PlayerAuth.builder() PlayerAuth bobby = PlayerAuth.builder()
.name("bobby").realName("BOBBY").lastLogin(123L) .name("bobby").realName("BOBBY").lastLogin(123L)
.ip("12.12.12.12").build(); .lastIp("12.12.12.12").build();
// when // when
boolean response = dataSource.updateSession(bobby); boolean response = dataSource.updateSession(bobby);
@ -298,7 +301,9 @@ public abstract class AbstractDataSourceIntegrationTest {
List<String> initialList = dataSource.getAllAuthsByIp("123.45.67.89"); List<String> initialList = dataSource.getAllAuthsByIp("123.45.67.89");
List<String> emptyList = dataSource.getAllAuthsByIp("8.8.8.8"); List<String> emptyList = dataSource.getAllAuthsByIp("8.8.8.8");
for (int i = 0; i < 3; ++i) { 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<String> updatedList = dataSource.getAllAuthsByIp("123.45.67.89"); List<String> updatedList = dataSource.getAllAuthsByIp("123.45.67.89");
@ -329,8 +334,9 @@ public abstract class AbstractDataSourceIntegrationTest {
public void shouldGetRecordsToPurge() { public void shouldGetRecordsToPurge() {
// given // given
DataSource dataSource = getDataSource(); 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.saveAuth(auth);
dataSource.updateSession(auth);
// 1453242857 -> user, 1449136800 -> bobby, 0 -> potato // 1453242857 -> user, 1449136800 -> bobby, 0 -> potato
// when // when

View File

@ -79,7 +79,7 @@ public class FlatFileIntegrationTest {
public void shouldAddAuth() { public void shouldAddAuth() {
// given / when // given / when
boolean response = dataSource.saveAuth( 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<PlayerAuth> authList = dataSource.getAllAuths(); List<PlayerAuth> authList = dataSource.getAllAuths();
// then // then

View File

@ -98,6 +98,7 @@ public class AbstractDataSourceConverterTest {
verify(destination).getType(); verify(destination).getType();
verify(destination, times(3)).isAuthAvailable(anyString()); verify(destination, times(3)).isAuthAvailable(anyString());
verify(destination, times(2)).saveAuth(any(PlayerAuth.class)); verify(destination, times(2)).saveAuth(any(PlayerAuth.class));
verify(destination, times(2)).updateSession(any(PlayerAuth.class));
verify(destination, times(2)).updateQuitLoc(any(PlayerAuth.class)); verify(destination, times(2)).updateQuitLoc(any(PlayerAuth.class));
verifyNoMoreInteractions(destination); verifyNoMoreInteractions(destination);
verify(sender).sendMessage(argThat(containsString(auths.get(0).getNickname()))); verify(sender).sendMessage(argThat(containsString(auths.get(0).getNickname())));

View File

@ -27,6 +27,8 @@ import java.sql.Statement;
import static fr.xephi.authme.AuthMeMatchers.equalToHash; import static fr.xephi.authme.AuthMeMatchers.equalToHash;
import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation; import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation;
import static org.hamcrest.Matchers.equalTo; 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.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; 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).getNickname(), equalTo("player1"));
assertThat(captor.getAllValues().get(0).getRealName(), equalTo("Player1")); assertThat(captor.getAllValues().get(0).getRealName(), equalTo("Player1"));
assertThat(captor.getAllValues().get(0).getLastLogin(), equalTo(1494242093652L)); 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).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).getNickname(), equalTo("player2"));
assertThat(captor.getAllValues().get(1).getLastLogin(), equalTo(1494242174589L)); 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).getRealName(), equalTo("Player3"));
assertThat(captor.getAllValues().get(2).getPassword(), equalToHash("$2a$10$WFui8KSXMLDOVXKFpCLyPukPi4M82w1cv/rNojsAnwJjba3pp8sba")); 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), 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 @Test
@ -99,11 +104,12 @@ public class LoginSecurityConverterTest {
assertThat(captor.getAllValues().get(0).getRealName(), equalTo("Player1")); assertThat(captor.getAllValues().get(0).getRealName(), equalTo("Player1"));
assertThat(captor.getAllValues().get(0).getLastLogin(), equalTo(1494242093000L)); assertThat(captor.getAllValues().get(0).getLastLogin(), equalTo(1494242093000L));
assertThat(captor.getAllValues().get(0).getPassword(), equalToHash("$2a$10$E1Ri7XKeIIBv4qVaiPplgepT7QH9xGFh3hbHfcmCjq7hiW.UBTiGK")); 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).getNickname(), equalTo("player2"));
assertThat(captor.getAllValues().get(1).getLastLogin(), equalTo(1489317753000L)); 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).getRealName(), equalTo("Player3"));
assertThat(captor.getAllValues().get(2).getPassword(), equalToHash("$2a$10$WFui8KSXMLDOVXKFpCLyPukPi4M82w1cv/rNojsAnwJjba3pp8sba")); assertThat(captor.getAllValues().get(2).getPassword(), equalToHash("$2a$10$WFui8KSXMLDOVXKFpCLyPukPi4M82w1cv/rNojsAnwJjba3pp8sba"));
@ -129,4 +135,8 @@ public class LoginSecurityConverterTest {
} }
return connection; return connection;
} }
private static void assertIsCloseTo(long value1, long value2, long tolerance) {
assertThat(Math.abs(value1 - value2), not(greaterThan(tolerance)));
}
} }

View File

@ -12,8 +12,6 @@ import fr.xephi.authme.security.PasswordSecurity;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.service.CommonService; import fr.xephi.authme.service.CommonService;
import fr.xephi.authme.settings.properties.EmailSettings; import fr.xephi.authme.settings.properties.EmailSettings;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@ -22,9 +20,10 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData; import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData;
import static fr.xephi.authme.AuthMeMatchers.hasAuthLocation;
import static fr.xephi.authme.AuthMeMatchers.stringWithLength; import static fr.xephi.authme.AuthMeMatchers.stringWithLength;
import static org.hamcrest.Matchers.equalTo; 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.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
@ -116,17 +115,15 @@ public class EmailRegisterExecutorProviderTest {
Player player = mock(Player.class); Player player = mock(Player.class);
TestHelper.mockPlayerIp(player, "123.45.67.89"); TestHelper.mockPlayerIp(player, "123.45.67.89");
given(player.getName()).willReturn("Veronica"); 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"); EmailRegisterParams params = EmailRegisterParams.of(player, "test@example.com");
// when // when
PlayerAuth auth = executor.buildPlayerAuth(params); PlayerAuth auth = executor.buildPlayerAuth(params);
// then // then
assertThat(auth, hasAuthBasicData("veronica", "Veronica", "test@example.com", "123.45.67.89")); assertThat(auth, hasAuthBasicData("veronica", "Veronica", "test@example.com", "127.0.0.1"));
assertThat(auth, hasAuthLocation(48, 96, 144, "someWorld", 0, 0)); assertThat(auth.getRegistrationIp(), equalTo("123.45.67.89"));
assertIsCloseTo(auth.getRegistrationDate(), System.currentTimeMillis(), 1000);
assertThat(auth.getPassword().getHash(), stringWithLength(12)); assertThat(auth.getPassword().getHash(), stringWithLength(12));
} }
@ -167,4 +164,7 @@ public class EmailRegisterExecutorProviderTest {
verifyZeroInteractions(syncProcessManager); verifyZeroInteractions(syncProcessManager);
} }
private static void assertIsCloseTo(long value1, long value2, long tolerance) {
assertThat(Math.abs(value1 - value2), not(greaterThan(tolerance)));
}
} }

View File

@ -13,8 +13,6 @@ import fr.xephi.authme.service.ValidationService;
import fr.xephi.authme.service.ValidationService.ValidationResult; import fr.xephi.authme.service.ValidationService.ValidationResult;
import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.settings.properties.PluginSettings;
import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.settings.properties.RegistrationSettings;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; 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.equalToHash;
import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData; 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.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
@ -98,17 +97,15 @@ public class PasswordRegisterExecutorTest {
invocation -> new HashedPassword(invocation.getArgument(0))); invocation -> new HashedPassword(invocation.getArgument(0)));
Player player = mockPlayerWithName("S1m0N"); Player player = mockPlayerWithName("S1m0N");
TestHelper.mockPlayerIp(player, "123.45.67.89"); 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"); PasswordRegisterParams params = PasswordRegisterParams.of(player, "pass", "mail@example.org");
// when // when
PlayerAuth auth = executor.buildPlayerAuth(params); PlayerAuth auth = executor.buildPlayerAuth(params);
// then // then
assertThat(auth, hasAuthBasicData("s1m0n", "S1m0N", "mail@example.org", "123.45.67.89")); assertThat(auth, hasAuthBasicData("s1m0n", "S1m0N", "mail@example.org", "127.0.0.1"));
assertThat(auth, hasAuthLocation(48, 96, 144, "someWorld", 1.1f, 0.28f)); assertThat(auth.getRegistrationIp(), equalTo("123.45.67.89"));
assertIsCloseTo(auth.getRegistrationDate(), System.currentTimeMillis(), 500);
assertThat(auth.getPassword(), equalToHash("pass")); assertThat(auth.getPassword(), equalToHash("pass"));
} }
@ -149,4 +146,8 @@ public class PasswordRegisterExecutorTest {
given(player.getName()).willReturn(name); given(player.getName()).willReturn(name);
return player; return player;
} }
private static void assertIsCloseTo(long value1, long value2, long tolerance) {
assertThat(Math.abs(value1 - value2), not(greaterThan(tolerance)));
}
} }

View File

@ -3,13 +3,13 @@ package fr.xephi.authme.process.register.executors;
import fr.xephi.authme.TestHelper; import fr.xephi.authme.TestHelper;
import fr.xephi.authme.data.auth.PlayerAuth; import fr.xephi.authme.data.auth.PlayerAuth;
import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.HashedPassword;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.junit.Test; import org.junit.Test;
import static fr.xephi.authme.AuthMeMatchers.equalToHash;
import static fr.xephi.authme.AuthMeMatchers.hasAuthBasicData; 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.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -26,10 +26,6 @@ public class PlayerAuthBuilderHelperTest {
given(player.getName()).willReturn("Noah"); given(player.getName()).willReturn("Noah");
String ip = "192.168.34.47"; String ip = "192.168.34.47";
TestHelper.mockPlayerIp(player, ip); 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"); HashedPassword hashedPassword = new HashedPassword("myHash0001");
String email = "test@example.org"; String email = "test@example.org";
@ -37,8 +33,10 @@ public class PlayerAuthBuilderHelperTest {
PlayerAuth auth = PlayerAuthBuilderHelper.createPlayerAuth(player, hashedPassword, email); PlayerAuth auth = PlayerAuthBuilderHelper.createPlayerAuth(player, hashedPassword, email);
// then // then
assertThat(auth, hasAuthBasicData("noah", "Noah", email, ip)); assertThat(auth, hasAuthBasicData("noah", "Noah", email, "127.0.0.1"));
assertThat(auth, hasAuthLocation(123, 80, -99, "worldName", 2.45f, 7.61f)); assertThat(auth.getRegistrationIp(), equalTo("192.168.34.47"));
assertThat(Math.abs(auth.getRegistrationDate() - System.currentTimeMillis()), lessThan(1000L));
assertThat(auth.getPassword(), equalToHash("myHash0001"));
} }
@Test @Test

View File

@ -4,23 +4,24 @@ CREATE TABLE authme (
id INTEGER AUTO_INCREMENT, id INTEGER AUTO_INCREMENT,
username VARCHAR(255) NOT NULL UNIQUE, username VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL,
ip VARCHAR(40) NOT NULL, ip VARCHAR(40),
lastlogin BIGINT, lastlogin BIGINT,
regdate BIGINT NOT NULL,
regip VARCHAR(40),
x DOUBLE NOT NULL DEFAULT '0.0', x DOUBLE NOT NULL DEFAULT '0.0',
y DOUBLE NOT NULL DEFAULT '0.0', y DOUBLE NOT NULL DEFAULT '0.0',
z DOUBLE NOT NULL DEFAULT '0.0', z DOUBLE NOT NULL DEFAULT '0.0',
world VARCHAR(255) NOT NULL DEFAULT 'world', world VARCHAR(255) NOT NULL DEFAULT 'world',
yaw FLOAT, yaw FLOAT,
pitch FLOAT, pitch FLOAT,
email VARCHAR(255) DEFAULT 'your@email.com', email VARCHAR(255),
isLogged INT DEFAULT '0', realname VARCHAR(255) NOT NULL DEFAULT 'Player', isLogged INT DEFAULT '0',
realname VARCHAR(255) NOT NULL DEFAULT 'Player',
salt varchar(255), salt varchar(255),
recoverycode VARCHAR(20),
recoveryexpiration BIGINT,
CONSTRAINT table_const_prim PRIMARY KEY (id) 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) 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); 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) 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'); 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);