package games.strategy.engine.lobby.server.userDB; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.logging.Level; import java.util.logging.Logger; import games.strategy.engine.framework.startup.ui.InGameLobbyWatcher; import games.strategy.util.MD5Crypt; import games.strategy.util.Util; public class DBUserController { private static final Logger s_logger = Logger.getLogger(DBUserController.class.getName()); /** * @return if this user is valid. */ public String validate(final String userName, final String email, final String hashedPassword) { if (email == null || !Util.isMailValid(email)) { return "Invalid email address"; } if (hashedPassword == null || hashedPassword.length() < 3 || !hashedPassword.startsWith(MD5Crypt.MAGIC)) { return "Invalid password"; } return validateUserName(userName); } public static String validateUserName(final String userName) { // is this a valid user? if (userName == null || !userName.matches("[0-9a-zA-Z_-]+") || userName.length() <= 2) { return "Usernames must be at least 3 characters long and can only contain alpha numeric characters, -, and _"; } if (userName.contains(InGameLobbyWatcher.LOBBY_WATCHER_NAME)) { return InGameLobbyWatcher.LOBBY_WATCHER_NAME + " cannot be part of a name"; } if (userName.toLowerCase().contains("admin")) { return "Username can't contain the word admin"; } return null; } public static void main(final String[] args) throws SQLException { Database.getConnection().close(); } /** * @return null if the user does not exist. */ public String getPassword(final String userName) { final String sql = "select password from ta_users where username = ?"; final Connection con = Database.getConnection(); try { final PreparedStatement ps = con.prepareStatement(sql); ps.setString(1, userName); final ResultSet rs = ps.executeQuery(); String rVal = null; if (rs.next()) { rVal = rs.getString(1); } rs.close(); ps.close(); return rVal; } catch (final SQLException sqle) { s_logger.info("Error for testing user existence:" + userName + " error:" + sqle.getMessage()); throw new IllegalStateException(sqle.getMessage()); } finally { DbUtil.closeConnection(con); } } public boolean doesUserExist(final String userName) { final String sql = "select username from ta_users where upper(username) = upper(?)"; final Connection con = Database.getConnection(); try { final PreparedStatement ps = con.prepareStatement(sql); ps.setString(1, userName); final ResultSet rs = ps.executeQuery(); final boolean found = rs.next(); rs.close(); ps.close(); return found; } catch (final SQLException sqle) { s_logger.info("Error for testing user existence:" + userName + " error:" + sqle.getMessage()); throw new IllegalStateException(sqle.getMessage()); } finally { DbUtil.closeConnection(con); } } public void updateUser(final String name, final String email, final String hashedPassword, final boolean admin) { final String validationErrors = validate(name, email, hashedPassword); if (validationErrors != null) { throw new IllegalStateException(validationErrors); } final Connection con = Database.getConnection(); try { final PreparedStatement ps = con.prepareStatement("update ta_users set password = ?, email = ?, admin = ? where username = ?"); ps.setString(1, hashedPassword); ps.setString(2, email); ps.setBoolean(3, admin); ps.setString(4, name); ps.execute(); ps.close(); con.commit(); } catch (final SQLException sqle) { s_logger.log(Level.SEVERE, "Error updating name:" + name + " email: " + email + " pwd: " + hashedPassword, sqle); throw new IllegalStateException(sqle.getMessage()); } finally { DbUtil.closeConnection(con); } } /** * Create a user in the database. * If an error occured, an IllegalStateException will be thrown with a user displayable error message. */ public void createUser(final String name, final String email, final String hashedPassword, final boolean admin) { final String validationErrors = validate(name, email, hashedPassword); if (validationErrors != null) { throw new IllegalStateException(validationErrors); } if (doesUserExist(name)) { throw new IllegalStateException("That user name has already been taken"); } final Connection con = Database.getConnection(); try { final PreparedStatement ps = con.prepareStatement( "insert into ta_users (username, password, email, joined, lastLogin, admin) values (?, ?, ?, ?, ?, ?)"); ps.setString(1, name); ps.setString(2, hashedPassword); ps.setString(3, email); ps.setTimestamp(4, new Timestamp(System.currentTimeMillis())); ps.setTimestamp(5, new java.sql.Timestamp(System.currentTimeMillis())); ps.setInt(6, admin ? 1 : 0); ps.execute(); ps.close(); con.commit(); } catch (final SQLException sqle) { if (sqle.getErrorCode() == 30000) { s_logger.info("Tried to create duplicate user for name:" + name + " error:" + sqle.getMessage()); throw new IllegalStateException("That user name is already taken"); } s_logger.log(Level.SEVERE, "Error inserting name:" + name + " email: " + email + " pwd: " + hashedPassword, sqle); throw new IllegalStateException(sqle.getMessage()); } finally { DbUtil.closeConnection(con); } } /** * Validate the username password, returning true if the user is able to login. * This has the side effect of updating the users last login time. */ public boolean login(final String userName, final String hashedPassword) { final Connection con = Database.getConnection(); try { PreparedStatement ps = con.prepareStatement("select username from ta_users where username = ? and password = ?"); ps.setString(1, userName); ps.setString(2, hashedPassword); final ResultSet rs = ps.executeQuery(); if (!rs.next()) { return false; } ps.close(); rs.close(); // update last login time ps = con.prepareStatement("update ta_users set lastLogin = ? where username = ? "); ps.setTimestamp(1, new Timestamp(System.currentTimeMillis())); ps.setString(2, userName); ps.execute(); ps.close(); return true; } catch (final SQLException sqle) { s_logger.log(Level.SEVERE, "Error validating password name:" + userName + " : " + " pwd:" + hashedPassword, sqle); throw new IllegalStateException(sqle.getMessage()); } finally { DbUtil.closeConnection(con); } } /** * @return null if no such user. */ public DBUser getUser(final String userName) { final String sql = "select * from ta_users where username = ?"; final Connection con = Database.getConnection(); try { final PreparedStatement ps = con.prepareStatement(sql); ps.setString(1, userName); final ResultSet rs = ps.executeQuery(); if (!rs.next()) { return null; } final DBUser user = new DBUser(rs.getString("username"), rs.getString("email"), rs.getBoolean("admin"), rs.getTimestamp("lastLogin"), rs.getTimestamp("joined")); rs.close(); ps.close(); return user; } catch (final SQLException sqle) { s_logger.info("Error for testing user existence:" + userName + " error:" + sqle.getMessage()); throw new IllegalStateException(sqle.getMessage()); } finally { DbUtil.closeConnection(con); } } }