From 4bd44ea8f1a66f1b81ab44cb9a9b92d208bbf016 Mon Sep 17 00:00:00 2001 From: marcins78 Date: Thu, 23 May 2013 14:32:21 +0000 Subject: [PATCH] User management. --- .../async/handler/AdminRequestHandler.java | 96 +++++++++ .../async/handler/LoginRequestHandler.java | 7 +- .../gemp-lotr-async/src/main/web/ban.html | 184 ++++++++++++++++++ .../gemp-lotr-async/src/main/web/index.html | 6 +- .../java/com/gempukku/lotro/game/Player.java | 28 ++- .../gempukku/lotro/db/CachedPlayerDAO.java | 30 +++ .../com/gempukku/lotro/db/DbPlayerDAO.java | 170 ++++++++++++---- .../java/com/gempukku/lotro/db/PlayerDAO.java | 9 + 8 files changed, 493 insertions(+), 37 deletions(-) create mode 100644 gemp-lotr/gemp-lotr-async/src/main/web/ban.html diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/AdminRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/AdminRequestHandler.java index ddc2e2bb2..cf1296c0f 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/AdminRequestHandler.java +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/AdminRequestHandler.java @@ -7,6 +7,7 @@ import com.gempukku.lotro.cache.CacheManager; import com.gempukku.lotro.cards.CardSets; import com.gempukku.lotro.collection.CollectionsManager; import com.gempukku.lotro.db.LeagueDAO; +import com.gempukku.lotro.db.PlayerDAO; import com.gempukku.lotro.db.vo.CollectionType; import com.gempukku.lotro.game.CardCollection; import com.gempukku.lotro.game.Player; @@ -25,12 +26,14 @@ import org.w3c.dom.Element; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.lang.reflect.Type; +import java.text.SimpleDateFormat; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Map; public class AdminRequestHandler extends LotroServerRequestHandler implements UriRequestHandler { + public static final int DAY_IN_MILIS = 1000 * 60 * 60 * 24; private LeagueService _leagueService; private TournamentService _tournamentService; private CacheManager _cacheManager; @@ -39,6 +42,7 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur private LeagueDAO _leagueDao; private CollectionsManager _collectionManager; private CardSets _cardSets; + private PlayerDAO _playerDAO; public AdminRequestHandler(Map context) { super(context); @@ -49,6 +53,7 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur _hallServer = extractObject(context, HallServer.class); _formatLibrary = extractObject(context, LotroFormatLibrary.class); _leagueDao = extractObject(context, LeagueDAO.class); + _playerDAO = extractObject(context, PlayerDAO.class); _collectionManager = extractObject(context, CollectionsManager.class); } @@ -72,10 +77,101 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur addItems(request, responseWriter); } else if (uri.equals("/addItemsToCollection") && request.getMethod() == HttpMethod.POST) { addItemsToCollection(request, responseWriter); + } else if (uri.equals("/banUser") && request.getMethod() == HttpMethod.POST) { + banUser(request, responseWriter); + } else if (uri.equals("/banUserTemp") && request.getMethod() == HttpMethod.POST) { + banUserTemp(request, responseWriter); + } else if (uri.equals("/unBanUser") && request.getMethod() == HttpMethod.POST) { + unBanUser(request, responseWriter); + } else if (uri.equals("/findMultipleAccounts") && request.getMethod() == HttpMethod.POST) { + findMultipleAccounts(request, responseWriter); } else { responseWriter.writeError(404); } + } + private void findMultipleAccounts(HttpRequest request, ResponseWriter responseWriter) throws Exception { + validateAdmin(request); + + HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(request); + String login = getFormParameterSafely(postDecoder, "login"); + + List similarPlayers = _playerDAO.findSimilarAccounts(login); + if (similarPlayers == null) + responseWriter.writeError(404); + + DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); + + Document doc = documentBuilder.newDocument(); + Element players = doc.createElement("players"); + + for (Player similarPlayer : similarPlayers) { + Element playerElem = doc.createElement("league"); + playerElem.setAttribute("id", String.valueOf(similarPlayer.getId())); + playerElem.setAttribute("name", similarPlayer.getName()); + playerElem.setAttribute("password", similarPlayer.getPassword()); + playerElem.setAttribute("status", getStatus(similarPlayer)); + playerElem.setAttribute("createIp", similarPlayer.getCreateIp()); + playerElem.setAttribute("loginIp", similarPlayer.getLastIp()); + players.appendChild(playerElem); + } + + doc.appendChild(players); + + responseWriter.writeXmlResponse(doc); + } + + private String getStatus(Player similarPlayer) { + if (similarPlayer.getBannedUntil() != null) { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + return "Banned until " + format.format(similarPlayer.getBannedUntil()); + } + if (similarPlayer.getType().contains("n")) + return "Unbanned"; + if (similarPlayer.getType().equals("")) + return "Banned permanently"; + return "OK"; + } + + private void banUser(HttpRequest request, ResponseWriter responseWriter) throws Exception { + validateAdmin(request); + + HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(request); + String login = getFormParameterSafely(postDecoder, "login"); + + final boolean success = _playerDAO.banPlayerPermanently(login); + if (!success) + throw new HttpProcessingException(404); + + responseWriter.writeHtmlResponse("OK"); + } + + private void banUserTemp(HttpRequest request, ResponseWriter responseWriter) throws Exception { + validateAdmin(request); + + HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(request); + String login = getFormParameterSafely(postDecoder, "login"); + int duration = Integer.parseInt(getFormParameterSafely(postDecoder, "duration")); + + final boolean success = _playerDAO.banPlayerTemporarily(login, System.currentTimeMillis() + duration * DAY_IN_MILIS); + if (!success) + throw new HttpProcessingException(404); + + responseWriter.writeHtmlResponse("OK"); + } + + private void unBanUser(HttpRequest request, ResponseWriter responseWriter) throws Exception { + validateAdmin(request); + + HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(request); + String login = getFormParameterSafely(postDecoder, "login"); + + final boolean success = _playerDAO.unBanPlayer(login); + if (!success) + throw new HttpProcessingException(404); + + responseWriter.writeHtmlResponse("OK"); } private void addItemsToCollection(HttpRequest request, ResponseWriter responseWriter) throws Exception { diff --git a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/LoginRequestHandler.java b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/LoginRequestHandler.java index 1cf710d7c..698c226ac 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/LoginRequestHandler.java +++ b/gemp-lotr/gemp-lotr-async/src/main/java/com/gempukku/lotro/async/handler/LoginRequestHandler.java @@ -8,6 +8,7 @@ import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder; import java.lang.reflect.Type; +import java.util.Date; import java.util.Map; public class LoginRequestHandler extends LotroServerRequestHandler implements UriRequestHandler { @@ -25,7 +26,11 @@ public class LoginRequestHandler extends LotroServerRequestHandler implements Ur Player player = _playerDao.loginUser(login, password); if (player != null) { if (player.getType().contains("u")) { - responseWriter.writeXmlResponse(null, logUserReturningHeaders(e, login)); + final Date bannedUntil = player.getBannedUntil(); + if (bannedUntil != null && bannedUntil.after(new Date())) + responseWriter.writeError(409); + else + responseWriter.writeXmlResponse(null, logUserReturningHeaders(e, login)); } else { responseWriter.writeError(403); } diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/ban.html b/gemp-lotr/gemp-lotr-async/src/main/web/ban.html new file mode 100644 index 000000000..2381b6932 --- /dev/null +++ b/gemp-lotr/gemp-lotr-async/src/main/web/ban.html @@ -0,0 +1,184 @@ + + + Gemp-LotR Ban Manager + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Ban user

+

Permanently

+
+ Name (case-sensitive):
+ +
+

Temporarily

+
+ Name (case-sensitive):
+ Duration: +
+ +
+

Unban user

+
+ Name (case-sensitive):
+ +
+

Find suspicious behaviour

+

Multiple user accounts

+
+ Name (case-sensitive):
+ +
+
+ + \ No newline at end of file diff --git a/gemp-lotr/gemp-lotr-async/src/main/web/index.html b/gemp-lotr/gemp-lotr-async/src/main/web/index.html index 475f29668..a2e9ae0a7 100644 --- a/gemp-lotr/gemp-lotr-async/src/main/web/index.html +++ b/gemp-lotr/gemp-lotr-async/src/main/web/index.html @@ -117,9 +117,13 @@ loginScreen(); }, "403": function() { - $(".error").html("You have been banned. If you think it was a mistake, please write an e-mail to TLHH forums."); $(".interaction").html(""); }, + "409": function() { + $(".error").html("You have been temporarily banned. You can try logging in at a later time. If you think it was a mistake you can try sending a private message to CoS on TLHH forums."); + $(".interaction").html(""); + } "503": function() { $(".error").html("Server is down for maintenance. Please come at a later time."); } diff --git a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/Player.java b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/Player.java index 5f1555d47..e933136ee 100644 --- a/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/Player.java +++ b/gemp-lotr/gemp-lotr-logic/src/main/java/com/gempukku/lotro/game/Player.java @@ -1,16 +1,26 @@ package com.gempukku.lotro.game; +import java.util.Date; + public class Player { private int _id; private String _name; + private String _password; private String _type; private Integer _lastLoginReward; + private Date _bannedUntil; + private String _createIp; + private String _lastIp; - public Player(int id, String name, String type, Integer lastLoginReward) { + public Player(int id, String name, String password, String type, Integer lastLoginReward, Date bannedUntil, String createIp, String lastIp) { _id = id; _name = name; + _password = password; _type = type; _lastLoginReward = lastLoginReward; + _bannedUntil = bannedUntil; + _createIp = createIp; + _lastIp = lastIp; } public int getId() { @@ -21,6 +31,10 @@ public class Player { return _name; } + public String getPassword() { + return _password; + } + public String getType() { return _type; } @@ -33,6 +47,18 @@ public class Player { _lastLoginReward = lastLoginReward; } + public Date getBannedUntil() { + return _bannedUntil; + } + + public String getCreateIp() { + return _createIp; + } + + public String getLastIp() { + return _lastIp; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java index ad5da3c39..c052257b1 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/CachedPlayerDAO.java @@ -6,6 +6,7 @@ import org.apache.commons.collections.map.LRUMap; import java.sql.SQLException; import java.util.Collections; +import java.util.List; import java.util.Map; public class CachedPlayerDAO implements PlayerDAO, Cached { @@ -28,6 +29,35 @@ public class CachedPlayerDAO implements PlayerDAO, Cached { return _playerById.size() + _playerByName.size(); } + @Override + public boolean banPlayerPermanently(String login) throws SQLException { + final boolean success = _delegate.banPlayerPermanently(login); + if (success) + clearCache(); + return success; + } + + @Override + public boolean banPlayerTemporarily(String login, long dateTo) throws SQLException { + final boolean success = _delegate.banPlayerTemporarily(login, dateTo); + if (success) + clearCache(); + return success; + } + + @Override + public boolean unBanPlayer(String login) throws SQLException { + final boolean success = _delegate.unBanPlayer(login); + if (success) + clearCache(); + return success; + } + + @Override + public List findSimilarAccounts(String login) throws SQLException { + return _delegate.findSimilarAccounts(login); + } + @Override public Player getPlayer(int id) { Player player = (Player) _playerById.get(id); diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java index 134dc13e8..bb88deeb1 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/DbPlayerDAO.java @@ -7,9 +7,13 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; public class DbPlayerDAO implements PlayerDAO { private final String validLoginChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; + private final String _selectPlayer = "select id, name, password, type, last_login_reward, banned_until, create_ip, last_ip from player"; private DbAccess _dbAccess; @@ -17,42 +21,128 @@ public class DbPlayerDAO implements PlayerDAO { _dbAccess = dbAccess; } - public synchronized Player getPlayer(int id) { + @Override + public Player getPlayer(int id) { try { - final Player player = getPlayerFromDBById(id); - return player; + return getPlayerFromDBById(id); } catch (SQLException exp) { throw new RuntimeException("Error while retrieving player", exp); } } - public synchronized Player getPlayer(String playerName) { + @Override + public Player getPlayer(String playerName) { try { - Player player = getPlayerFromDBByName(playerName); - return player; + return getPlayerFromDBByName(playerName); } catch (SQLException exp) { throw new RuntimeException("Unable to get player from DB", exp); } } - public synchronized Player loginUser(String login, String password) throws SQLException { + @Override + public List findSimilarAccounts(String login) throws SQLException { + final Player player = getPlayerFromDBByName(login); + if (player == null) + return null; + Connection conn = _dbAccess.getDataSource().getConnection(); try { - PreparedStatement statement = conn.prepareStatement("select id, name, type, last_login_reward from player where name=? and password=?"); + String sql = _selectPlayer + " where password=?"; + if (player.getCreateIp() != null) + sql += " or create_ip=? or last_ip=?"; + if (player.getLastIp() != null) + sql += " or create_ip=? or last_ip=?"; + + PreparedStatement statement = conn.prepareStatement(sql); + try { + statement.setString(1, player.getPassword()); + int nextParamIndex = 2; + if (player.getCreateIp() != null) { + statement.setString(nextParamIndex, player.getCreateIp()); + nextParamIndex++; + } + if (player.getLastIp() != null) { + statement.setString(nextParamIndex, player.getLastIp()); + nextParamIndex++; + } + ResultSet rs = statement.executeQuery(); + try { + List players = new LinkedList(); + while (rs.next()) + players.add(getPlayerFromResultSet(rs)); + return players; + } finally { + rs.close(); + } + } finally { + statement.close(); + } + } finally { + conn.close(); + } + } + + @Override + public boolean banPlayerPermanently(String login) throws SQLException { + Connection conn = _dbAccess.getDataSource().getConnection(); + try { + PreparedStatement statement = conn.prepareStatement("update player set type='' where name=?"); + try { + statement.setString(1, login); + return statement.executeUpdate() == 1; + } finally { + statement.close(); + } + } finally { + conn.close(); + } + } + + @Override + public boolean banPlayerTemporarily(String login, long dateTo) throws SQLException { + Connection conn = _dbAccess.getDataSource().getConnection(); + try { + PreparedStatement statement = conn.prepareStatement("update player set banned_until=? where name=?"); + try { + statement.setLong(1, dateTo); + statement.setString(2, login); + return statement.executeUpdate() == 1; + } finally { + statement.close(); + } + } finally { + conn.close(); + } + } + + @Override + public boolean unBanPlayer(String login) throws SQLException { + Connection conn = _dbAccess.getDataSource().getConnection(); + try { + PreparedStatement statement = conn.prepareStatement("update player set type='un', banned_until=null where name=?"); + try { + statement.setString(1, login); + return statement.executeUpdate() == 1; + } finally { + statement.close(); + } + } finally { + conn.close(); + } + } + + @Override + public Player loginUser(String login, String password) throws SQLException { + Connection conn = _dbAccess.getDataSource().getConnection(); + try { + PreparedStatement statement = conn.prepareStatement(_selectPlayer + " where name=? and password=?"); try { statement.setString(1, login); statement.setString(2, encodePassword(password)); ResultSet rs = statement.executeQuery(); try { if (rs.next()) { - int id = rs.getInt(1); - String name = rs.getString(2); - String type = rs.getString(3); - Integer lastLoginReward = rs.getInt(4); - if (rs.wasNull()) - lastLoginReward = null; - - return new Player(id, name, type, lastLoginReward); + return getPlayerFromResultSet(rs); } else return null; } finally { @@ -66,7 +156,29 @@ public class DbPlayerDAO implements PlayerDAO { } } - public synchronized void setLastReward(Player player, int currentReward) throws SQLException { + private Player getPlayerFromResultSet(ResultSet rs) throws SQLException { + int id = rs.getInt(1); + String name = rs.getString(2); + String password = rs.getString(3); + String type = rs.getString(4); + Integer lastLoginReward = rs.getInt(5); + if (rs.wasNull()) + lastLoginReward = null; + Long bannedUntilLong = rs.getLong(6); + if (rs.wasNull()) + bannedUntilLong = null; + + Date bannedUntil = null; + if (bannedUntilLong != null) + bannedUntil = new Date(bannedUntilLong); + String createIp = rs.getString(7); + String lastIp = rs.getString(8); + + return new Player(id, name, password, type, lastLoginReward, bannedUntil, createIp, lastIp); + } + + @Override + public void setLastReward(Player player, int currentReward) throws SQLException { Connection conn = _dbAccess.getDataSource().getConnection(); try { PreparedStatement statement = conn.prepareStatement("update player set last_login_reward =? where id=?"); @@ -83,6 +195,7 @@ public class DbPlayerDAO implements PlayerDAO { } } + @Override public synchronized boolean updateLastReward(Player player, int previousReward, int currentReward) throws SQLException { Connection conn = _dbAccess.getDataSource().getConnection(); try { @@ -104,6 +217,7 @@ public class DbPlayerDAO implements PlayerDAO { } } + @Override public synchronized boolean registerUser(String login, String password, String remoteAddr) throws SQLException, LoginInvalidException { boolean result = validateLogin(login); if (!result) @@ -186,19 +300,13 @@ public class DbPlayerDAO implements PlayerDAO { private Player getPlayerFromDBById(int id) throws SQLException { Connection conn = _dbAccess.getDataSource().getConnection(); try { - PreparedStatement statement = conn.prepareStatement("select id, name, type, last_login_reward from player where id=?"); + PreparedStatement statement = conn.prepareStatement(_selectPlayer + " where id=?"); try { statement.setInt(1, id); ResultSet rs = statement.executeQuery(); try { if (rs.next()) { - String name = rs.getString(2); - String type = rs.getString(3); - Integer lastLoginReward = rs.getInt(4); - if (rs.wasNull()) - lastLoginReward = null; - - return new Player(id, name, type, lastLoginReward); + return getPlayerFromResultSet(rs); } else { return null; } @@ -216,20 +324,13 @@ public class DbPlayerDAO implements PlayerDAO { private Player getPlayerFromDBByName(String playerName) throws SQLException { Connection conn = _dbAccess.getDataSource().getConnection(); try { - PreparedStatement statement = conn.prepareStatement("select id, name, type, last_login_reward from player where name=?"); + PreparedStatement statement = conn.prepareStatement(_selectPlayer + " where name=?"); try { statement.setString(1, playerName); ResultSet rs = statement.executeQuery(); try { if (rs.next()) { - int id = rs.getInt(1); - String name = rs.getString(2); - String type = rs.getString(3); - Integer lastLoginReward = rs.getInt(4); - if (rs.wasNull()) - lastLoginReward = null; - - return new Player(id, name, type, lastLoginReward); + return getPlayerFromResultSet(rs); } else { return null; } @@ -244,6 +345,7 @@ public class DbPlayerDAO implements PlayerDAO { } } + @Override public void updateLastLoginIp(String login, String remoteAddr) throws SQLException { Connection conn = _dbAccess.getDataSource().getConnection(); try { diff --git a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java index b11f059ca..53e41e586 100644 --- a/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java +++ b/gemp-lotr/gemp-lotr-server/src/main/java/com/gempukku/lotro/db/PlayerDAO.java @@ -3,12 +3,21 @@ package com.gempukku.lotro.db; import com.gempukku.lotro.game.Player; import java.sql.SQLException; +import java.util.List; public interface PlayerDAO { public Player getPlayer(int id); public Player getPlayer(String playerName); + public boolean banPlayerPermanently(String login) throws SQLException; + + public boolean banPlayerTemporarily(String login, long dateTo) throws SQLException; + + public boolean unBanPlayer(String login) throws SQLException; + + public List findSimilarAccounts(String login) throws SQLException; + public Player loginUser(String login, String password) throws SQLException; public void setLastReward(Player player, int currentReward) throws SQLException;