* Introduce hasSession field in datasource That makes isLogged more consistent as it will be '1' only when the player is online. * Fixes * Fix unit testing * Update config doc * Create SessionService * Create test for SessionService, avoid DB operations if sessions are disabled * Cleanup: remove outdated warning for session timeout = 0 - Remove outdated warning - Encapsulate session enabled check in SessionService * Fix failing SessionServiceTest, add data source integration tests for session methods
This commit is contained in:
@@ -30,7 +30,6 @@ import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.MigrationService;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||
import fr.xephi.authme.task.CleanupTask;
|
||||
@@ -264,12 +263,6 @@ public class AuthMe extends JavaPlugin {
|
||||
ConsoleLogger.warning("WARNING!!! By disabling ForceSingleSession, your server protection is inadequate!");
|
||||
}
|
||||
|
||||
// Session timeout disabled
|
||||
if (settings.getProperty(PluginSettings.SESSIONS_TIMEOUT) == 0
|
||||
&& settings.getProperty(PluginSettings.SESSIONS_ENABLED)) {
|
||||
ConsoleLogger.warning("WARNING!!! You set session timeout to 0, this may cause security issues!");
|
||||
}
|
||||
|
||||
// Use TLS property only affects port 25
|
||||
if (!settings.getProperty(EmailSettings.PORT25_USE_TLS)
|
||||
&& settings.getProperty(EmailSettings.SMTP_PORT) != 25) {
|
||||
|
||||
@@ -51,38 +51,29 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
bukkitService.runTaskOptionallyAsync(new Runnable() {
|
||||
bukkitService.runTaskOptionallyAsync(() -> {
|
||||
if (dataSource.isAuthAvailable(playerNameLowerCase)) {
|
||||
commonService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
|
||||
return;
|
||||
}
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(playerNameLowerCase)
|
||||
.realName(playerName)
|
||||
.password(hashedPassword)
|
||||
.build();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (dataSource.isAuthAvailable(playerNameLowerCase)) {
|
||||
commonService.send(sender, MessageKey.NAME_ALREADY_REGISTERED);
|
||||
return;
|
||||
}
|
||||
HashedPassword hashedPassword = passwordSecurity.computeHash(playerPass, playerNameLowerCase);
|
||||
PlayerAuth auth = PlayerAuth.builder()
|
||||
.name(playerNameLowerCase)
|
||||
.realName(playerName)
|
||||
.password(hashedPassword)
|
||||
.build();
|
||||
if (!dataSource.saveAuth(auth)) {
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dataSource.saveAuth(auth)) {
|
||||
commonService.send(sender, MessageKey.ERROR);
|
||||
return;
|
||||
}
|
||||
dataSource.setUnlogged(playerNameLowerCase);
|
||||
|
||||
commonService.send(sender, MessageKey.REGISTER_SUCCESS);
|
||||
ConsoleLogger.info(sender.getName() + " registered " + playerName);
|
||||
final Player player = bukkitService.getPlayerExact(playerName);
|
||||
if (player != null) {
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
player.kickPlayer(commonService.retrieveSingleMessage(MessageKey.KICK_FOR_ADMIN_REGISTER));
|
||||
}
|
||||
});
|
||||
}
|
||||
commonService.send(sender, MessageKey.REGISTER_SUCCESS);
|
||||
ConsoleLogger.info(sender.getName() + " registered " + playerName);
|
||||
final Player player = bukkitService.getPlayerExact(playerName);
|
||||
if (player != null) {
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() ->
|
||||
player.kickPlayer(commonService.retrieveSingleMessage(MessageKey.KICK_FOR_ADMIN_REGISTER)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -208,6 +208,21 @@ public class CacheDataSource implements DataSource {
|
||||
source.setUnlogged(user.toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSession(final String user) {
|
||||
return source.hasSession(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantSession(final String user) {
|
||||
source.grantSession(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeSession(final String user) {
|
||||
source.revokeSession(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeLogged() {
|
||||
source.purgeLogged();
|
||||
|
||||
@@ -26,6 +26,7 @@ public final class Columns {
|
||||
public final String EMAIL;
|
||||
public final String ID;
|
||||
public final String IS_LOGGED;
|
||||
public final String HAS_SESSION;
|
||||
|
||||
public Columns(Settings settings) {
|
||||
NAME = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME);
|
||||
@@ -44,6 +45,7 @@ public final class Columns {
|
||||
EMAIL = settings.getProperty(DatabaseSettings.MYSQL_COL_EMAIL);
|
||||
ID = settings.getProperty(DatabaseSettings.MYSQL_COL_ID);
|
||||
IS_LOGGED = settings.getProperty(DatabaseSettings.MYSQL_COL_ISLOGGED);
|
||||
HAS_SESSION = settings.getProperty(DatabaseSettings.MYSQL_COL_HASSESSION);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -161,6 +161,29 @@ public interface DataSource extends Reloadable {
|
||||
*/
|
||||
void setUnlogged(String user);
|
||||
|
||||
/**
|
||||
* Query the datasource whether the player has an active session or not.
|
||||
* Warning: this value won't expire, you have also to check the user's last login timestamp.
|
||||
*
|
||||
* @param user The name of the player to verify
|
||||
* @return True if the user has a valid session, false otherwise
|
||||
*/
|
||||
boolean hasSession(String user);
|
||||
|
||||
/**
|
||||
* Mark the user's hasSession value to true.
|
||||
*
|
||||
* @param user The name of the player to change
|
||||
*/
|
||||
void grantSession(String user);
|
||||
|
||||
/**
|
||||
* Mark the user's hasSession value to false.
|
||||
*
|
||||
* @param user The name of the player to change
|
||||
*/
|
||||
void revokeSession(String user);
|
||||
|
||||
/**
|
||||
* Set all players who are marked as logged in as NOT logged in.
|
||||
*/
|
||||
|
||||
@@ -329,6 +329,19 @@ public class FlatFile implements DataSource {
|
||||
public void setUnlogged(String user) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSession(String user) {
|
||||
throw new UnsupportedOperationException("Flat file no longer supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantSession(String user) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeSession(String user) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeLogged() {
|
||||
}
|
||||
|
||||
@@ -237,6 +237,11 @@ public class MySQL implements DataSource {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN "
|
||||
+ col.IS_LOGGED + " SMALLINT NOT NULL DEFAULT '0' AFTER " + col.EMAIL);
|
||||
}
|
||||
|
||||
if (isColumnMissing(md, col.HAS_SESSION)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN "
|
||||
+ col.HAS_SESSION + " SMALLINT NOT NULL DEFAULT '0' AFTER " + col.IS_LOGGED);
|
||||
}
|
||||
}
|
||||
ConsoleLogger.info("MySQL setup finished");
|
||||
}
|
||||
@@ -565,6 +570,44 @@ public class MySQL implements DataSource {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSession(String user) {
|
||||
String sql = "SELECT " + col.HAS_SESSION + " FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setString(1, user);
|
||||
try (ResultSet rs = pst.executeQuery()) {
|
||||
return rs.next() && (rs.getInt(col.HAS_SESSION) == 1);
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantSession(String user) {
|
||||
String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE " + col.NAME + "=?;";
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setInt(1, 1);
|
||||
pst.setString(2, user.toLowerCase());
|
||||
pst.executeUpdate();
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeSession(String user) {
|
||||
String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE " + col.NAME + "=?;";
|
||||
try (Connection con = getConnection(); PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setInt(1, 0);
|
||||
pst.setString(2, user.toLowerCase());
|
||||
pst.executeUpdate();
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void purgeLogged() {
|
||||
String sql = "UPDATE " + tableName + " SET " + col.IS_LOGGED + "=? WHERE " + col.IS_LOGGED + "=?;";
|
||||
|
||||
@@ -134,7 +134,13 @@ public class SQLite implements DataSource {
|
||||
}
|
||||
|
||||
if (isColumnMissing(md, col.IS_LOGGED)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN " + col.IS_LOGGED + " INT DEFAULT '0';");
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.IS_LOGGED + " INT NOT NULL DEFAULT '0';");
|
||||
}
|
||||
|
||||
if (isColumnMissing(md, col.HAS_SESSION)) {
|
||||
st.executeUpdate("ALTER TABLE " + tableName
|
||||
+ " ADD COLUMN " + col.HAS_SESSION + " INT NOT NULL DEFAULT '0';");
|
||||
}
|
||||
}
|
||||
ConsoleLogger.info("SQLite Setup finished");
|
||||
@@ -426,7 +432,7 @@ public class SQLite implements DataSource {
|
||||
|
||||
@Override
|
||||
public boolean isLogged(String user) {
|
||||
String sql = "SELECT * FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=?;";
|
||||
String sql = "SELECT " + col.IS_LOGGED + " FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=?;";
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setString(1, user);
|
||||
try (ResultSet rs = pst.executeQuery()) {
|
||||
@@ -455,14 +461,52 @@ public class SQLite implements DataSource {
|
||||
@Override
|
||||
public void setUnlogged(String user) {
|
||||
String sql = "UPDATE " + tableName + " SET " + col.IS_LOGGED + "=? WHERE LOWER(" + col.NAME + ")=?;";
|
||||
if (user != null) {
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setInt(1, 0);
|
||||
pst.setString(2, user);
|
||||
pst.executeUpdate();
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setInt(1, 0);
|
||||
pst.setString(2, user);
|
||||
pst.executeUpdate();
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSession(String user) {
|
||||
String sql = "SELECT " + col.HAS_SESSION + " FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=?;";
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setString(1, user);
|
||||
try (ResultSet rs = pst.executeQuery()) {
|
||||
if (rs.next()) {
|
||||
return rs.getInt(col.HAS_SESSION) == 1;
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void grantSession(String user) {
|
||||
String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE LOWER(" + col.NAME + ")=?;";
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setInt(1, 1);
|
||||
pst.setString(2, user);
|
||||
pst.executeUpdate();
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void revokeSession(String user) {
|
||||
String sql = "UPDATE " + tableName + " SET " + col.HAS_SESSION + "=? WHERE LOWER(" + col.NAME + ")=?;";
|
||||
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||
pst.setInt(1, 0);
|
||||
pst.setString(2, user);
|
||||
pst.executeUpdate();
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,17 +618,6 @@ public class SQLite implements DataSource {
|
||||
return authBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
private static void close(Statement st) {
|
||||
if (st != null) {
|
||||
try {
|
||||
st.close();
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void close(Connection con) {
|
||||
if (con != null) {
|
||||
try {
|
||||
@@ -594,14 +627,4 @@ public class SQLite implements DataSource {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void close(ResultSet rs) {
|
||||
if (rs != null) {
|
||||
try {
|
||||
rs.close();
|
||||
} catch (SQLException ex) {
|
||||
logSqlException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package fr.xephi.authme.process.join;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.data.auth.PlayerCache;
|
||||
import fr.xephi.authme.data.limbo.LimboService;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.events.ProtectInventoryEvent;
|
||||
import fr.xephi.authme.events.RestoreSessionEvent;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.permission.PlayerStatePermission;
|
||||
import fr.xephi.authme.process.AsynchronousProcess;
|
||||
@@ -14,11 +11,11 @@ import fr.xephi.authme.process.login.AsynchronousLogin;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.PluginHookService;
|
||||
import fr.xephi.authme.service.SessionService;
|
||||
import fr.xephi.authme.service.ValidationService;
|
||||
import fr.xephi.authme.settings.WelcomeMessageConfiguration;
|
||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
@@ -48,9 +45,6 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
@Inject
|
||||
private CommonService service;
|
||||
|
||||
@Inject
|
||||
private PlayerCache playerCache;
|
||||
|
||||
@Inject
|
||||
private LimboService limboService;
|
||||
|
||||
@@ -72,6 +66,9 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
@Inject
|
||||
private WelcomeMessageConfiguration welcomeMessageConfiguration;
|
||||
|
||||
@Inject
|
||||
private SessionService sessionService;
|
||||
|
||||
AsynchronousJoin() {
|
||||
}
|
||||
|
||||
@@ -121,7 +118,7 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
}
|
||||
|
||||
// Session logic
|
||||
if (canResumeSession(player)) {
|
||||
if (sessionService.canResumeSession(player)) {
|
||||
service.send(player, MessageKey.SESSION_RECONNECTION);
|
||||
// Run commands
|
||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
||||
@@ -177,30 +174,6 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
||||
});
|
||||
}
|
||||
|
||||
private boolean canResumeSession(Player player) {
|
||||
final String name = player.getName();
|
||||
if (database.isLogged(name)) {
|
||||
database.setUnlogged(name);
|
||||
playerCache.removePlayer(name);
|
||||
if(service.getProperty(PluginSettings.SESSIONS_ENABLED)) {
|
||||
PlayerAuth auth = database.getAuth(name);
|
||||
if (auth != null) {
|
||||
long timeSinceLastLogin = System.currentTimeMillis() - auth.getLastLogin();
|
||||
if(timeSinceLastLogin < 0
|
||||
|| timeSinceLastLogin > (service.getProperty(PluginSettings.SESSIONS_TIMEOUT) * 60 * 1000)
|
||||
|| !auth.getIp().equals(PlayerUtils.getPlayerIp(player))) {
|
||||
service.send(player, MessageKey.SESSION_EXPIRED);
|
||||
} else {
|
||||
RestoreSessionEvent event = bukkitService.createAndCallEvent(
|
||||
isAsync -> new RestoreSessionEvent(player, isAsync));
|
||||
return !event.isCancelled();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the maximum number of accounts has been exceeded for the given IP address (according to
|
||||
* settings and permissions). If this is the case, the player is kicked.
|
||||
|
||||
@@ -20,6 +20,7 @@ import fr.xephi.authme.process.SyncProcessManager;
|
||||
import fr.xephi.authme.security.PasswordSecurity;
|
||||
import fr.xephi.authme.service.BukkitService;
|
||||
import fr.xephi.authme.service.CommonService;
|
||||
import fr.xephi.authme.service.SessionService;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||
@@ -69,6 +70,9 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
||||
@Inject
|
||||
private EmailService emailService;
|
||||
|
||||
@Inject
|
||||
private SessionService sessionService;
|
||||
|
||||
AsynchronousLogin() {
|
||||
}
|
||||
|
||||
@@ -238,9 +242,10 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
||||
|
||||
ConsoleLogger.fine(player.getName() + " logged in!");
|
||||
|
||||
// makes player isLoggedin via API
|
||||
// makes player loggedin
|
||||
playerCache.updatePlayer(auth);
|
||||
dataSource.setLogged(name);
|
||||
sessionService.grantSession(name);
|
||||
|
||||
// As the scheduling executes the Task most likely after the current
|
||||
// task, we schedule it in the end
|
||||
|
||||
@@ -53,6 +53,7 @@ public class AsynchronousLogout implements AsynchronousProcess {
|
||||
|
||||
playerCache.removePlayer(name);
|
||||
database.setUnlogged(name);
|
||||
database.revokeSession(name);
|
||||
syncProcessManager.processSyncPlayerLogout(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,11 @@ public class AsynchronousQuit implements AsynchronousProcess {
|
||||
playerCache.removePlayer(name);
|
||||
|
||||
//always update the database when the player quit the game (if sessions are disabled)
|
||||
if(!wasLoggedIn || !service.getProperty(PluginSettings.SESSIONS_ENABLED)) {
|
||||
if (wasLoggedIn) {
|
||||
database.setUnlogged(name);
|
||||
if (!service.getProperty(PluginSettings.SESSIONS_ENABLED)) {
|
||||
database.revokeSession(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (plugin.isEnabled()) {
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package fr.xephi.authme.service;
|
||||
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||
import fr.xephi.authme.datasource.DataSource;
|
||||
import fr.xephi.authme.events.RestoreSessionEvent;
|
||||
import fr.xephi.authme.initialization.Reloadable;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||
import fr.xephi.authme.util.PlayerUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Handles the user sessions.
|
||||
*/
|
||||
public class SessionService implements Reloadable {
|
||||
|
||||
private final CommonService service;
|
||||
private final BukkitService bukkitService;
|
||||
private final DataSource database;
|
||||
|
||||
private boolean isEnabled;
|
||||
|
||||
@Inject
|
||||
SessionService(CommonService service, BukkitService bukkitService, DataSource database) {
|
||||
this.service = service;
|
||||
this.bukkitService = bukkitService;
|
||||
this.database = database;
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the player has a session he can resume.
|
||||
*
|
||||
* @param player the player to check
|
||||
* @return true if there is a current session, false otherwise
|
||||
*/
|
||||
public boolean canResumeSession(Player player) {
|
||||
final String name = player.getName();
|
||||
if (isEnabled && database.hasSession(name)) {
|
||||
database.setUnlogged(name);
|
||||
database.revokeSession(name);
|
||||
PlayerAuth auth = database.getAuth(name);
|
||||
if (hasValidSessionData(auth, player)) {
|
||||
RestoreSessionEvent event = bukkitService.createAndCallEvent(
|
||||
isAsync -> new RestoreSessionEvent(player, isAsync));
|
||||
return !event.isCancelled();
|
||||
} else {
|
||||
service.send(player, MessageKey.SESSION_EXPIRED);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given Player has a current session by comparing its properties
|
||||
* with the given PlayerAuth's.
|
||||
*
|
||||
* @param auth the player auth
|
||||
* @param player the associated player
|
||||
* @return true if the player may resume his login session, false otherwise
|
||||
*/
|
||||
private boolean hasValidSessionData(PlayerAuth auth, Player player) {
|
||||
if (auth == null) {
|
||||
ConsoleLogger.warning("No PlayerAuth in database for '" + player.getName() + "' during session check");
|
||||
return false;
|
||||
}
|
||||
long timeSinceLastLogin = System.currentTimeMillis() - auth.getLastLogin();
|
||||
return auth.getIp().equals(PlayerUtils.getPlayerIp(player))
|
||||
&& timeSinceLastLogin > 0
|
||||
&& timeSinceLastLogin < service.getProperty(PluginSettings.SESSIONS_TIMEOUT) * 60 * 1000;
|
||||
}
|
||||
|
||||
public void grantSession(String name) {
|
||||
if (isEnabled) {
|
||||
database.grantSession(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload() {
|
||||
this.isEnabled = service.getProperty(PluginSettings.SESSIONS_ENABLED);
|
||||
}
|
||||
}
|
||||
@@ -75,6 +75,10 @@ public final class DatabaseSettings implements SettingsHolder {
|
||||
public static final Property<String> MYSQL_COL_ISLOGGED =
|
||||
newProperty("DataSource.mySQLColumnLogged", "isLogged");
|
||||
|
||||
@Comment("Column for storing if a player has a valid session or not")
|
||||
public static final Property<String> MYSQL_COL_HASSESSION =
|
||||
newProperty("DataSource.mySQLColumnHasSession", "hasSession");
|
||||
|
||||
@Comment("Column for storing players ips")
|
||||
public static final Property<String> MYSQL_COL_IP =
|
||||
newProperty("DataSource.mySQLColumnIp", "ip");
|
||||
|
||||
Reference in New Issue
Block a user