#1031 Introduce hasSession field in datasource (#1351)

* 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:
Gabriele C
2017-10-15 18:32:51 +02:00
committed by ljacqu
parent 1487fc0d9e
commit 22e95493de
19 changed files with 537 additions and 106 deletions
@@ -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);
}
}
}
}