Easy banning using slash commands in Hall chat of users, users & their last IP, users & the range for the last IP.

This commit is contained in:
marcins78
2014-01-09 11:39:40 +00:00
parent 6b19470f06
commit 21b6de8190
14 changed files with 230 additions and 51 deletions

View File

@@ -7,6 +7,7 @@ import com.gempukku.lotro.builder.PacksStorageBuilder;
import com.gempukku.lotro.builder.ServerBuilder;
import com.gempukku.lotro.cards.CardSets;
import com.gempukku.lotro.packs.PacksStorage;
import com.gempukku.lotro.service.LoggedUserHolder;
import com.gempukku.polling.LongPollingSystem;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;

View File

@@ -14,6 +14,7 @@ import com.gempukku.lotro.game.Player;
import com.gempukku.lotro.game.formats.LotroFormatLibrary;
import com.gempukku.lotro.hall.HallServer;
import com.gempukku.lotro.league.*;
import com.gempukku.lotro.service.AdminService;
import com.gempukku.lotro.tournament.TournamentService;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.http.HttpMethod;
@@ -33,7 +34,6 @@ 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;
@@ -43,6 +43,7 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
private CollectionsManager _collectionManager;
private CardSets _cardSets;
private PlayerDAO _playerDAO;
private AdminService _adminService;
public AdminRequestHandler(Map<Type, Object> context) {
super(context);
@@ -55,6 +56,7 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
_leagueDao = extractObject(context, LeagueDAO.class);
_playerDAO = extractObject(context, PlayerDAO.class);
_collectionManager = extractObject(context, CollectionsManager.class);
_adminService = extractObject(context, AdminService.class);
}
@Override
@@ -145,10 +147,8 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
if (login==null)
throw new HttpProcessingException(404);
final boolean success = _playerDAO.banPlayerPermanently(login);
if (!success)
if (!_adminService.banUser(login))
throw new HttpProcessingException(404);
_loggedUserHolder.forceLogoutUser(login);
responseWriter.writeHtmlResponse("OK");
}
@@ -162,10 +162,8 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
throw new HttpProcessingException(404);
for (String login : logins) {
final boolean success = _playerDAO.banPlayerPermanently(login);
if (!success)
if (!_adminService.banUser(login))
throw new HttpProcessingException(404);
_loggedUserHolder.forceLogoutUser(login);
}
responseWriter.writeHtmlResponse("OK");
@@ -178,10 +176,8 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
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)
if (!_adminService.banUserTemp(login, duration))
throw new HttpProcessingException(404);
_loggedUserHolder.forceLogoutUser(login);
responseWriter.writeHtmlResponse("OK");
}
@@ -192,8 +188,7 @@ public class AdminRequestHandler extends LotroServerRequestHandler implements Ur
HttpPostRequestDecoder postDecoder = new HttpPostRequestDecoder(request);
String login = getFormParameterSafely(postDecoder, "login");
final boolean success = _playerDAO.unBanPlayer(login);
if (!success)
if (!_adminService.unBanUser(login))
throw new HttpProcessingException(404);
responseWriter.writeHtmlResponse("OK");

View File

@@ -4,6 +4,7 @@ import com.gempukku.lotro.PrivateInformationException;
import com.gempukku.lotro.SubscriptionExpiredException;
import com.gempukku.lotro.async.HttpProcessingException;
import com.gempukku.lotro.async.ResponseWriter;
import com.gempukku.lotro.chat.ChatCommandErrorException;
import com.gempukku.lotro.chat.ChatMessage;
import com.gempukku.lotro.chat.ChatRoomMediator;
import com.gempukku.lotro.chat.ChatServer;
@@ -68,14 +69,15 @@ public class ChatRequestHandler extends LotroServerRequestHandler implements Uri
_longPollingSystem.processLongPollingResource(polledResource, pollableResource);
}
} catch (SubscriptionExpiredException exp) {
responseWriter.writeError(410);
throw new HttpProcessingException(410);
} catch (PrivateInformationException exp) {
throw new HttpProcessingException(403);
} catch (ChatCommandErrorException exp) {
throw new HttpProcessingException(400);
}
}
private class ChatUpdateLongPollingResource implements LongPollingResource {
private ChatCommunicationChannel _chatCommunicationChannel;
private ChatRoomMediator _chatRoom;
private String _room;
private String _playerId;

View File

@@ -3,16 +3,14 @@ package com.gempukku.lotro.async.handler;
import com.gempukku.lotro.DateUtils;
import com.gempukku.lotro.PlayerLock;
import com.gempukku.lotro.async.HttpProcessingException;
import com.gempukku.lotro.async.LoggedUserHolder;
import com.gempukku.lotro.collection.CollectionsManager;
import com.gempukku.lotro.collection.TransferDAO;
import com.gempukku.lotro.db.PlayerDAO;
import com.gempukku.lotro.db.vo.CollectionType;
import com.gempukku.lotro.game.Player;
import com.gempukku.lotro.service.LoggedUserHolder;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.http.CookieEncoder;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
import org.jboss.netty.handler.codec.http.*;
import org.jboss.netty.handler.codec.http.multipart.Attribute;
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import org.jboss.netty.handler.codec.http.multipart.InterfaceHttpData;
@@ -21,11 +19,9 @@ import java.io.IOException;
import java.lang.reflect.Type;
import java.net.InetSocketAddress;
import java.sql.SQLException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.COOKIE;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.SET_COOKIE;
public class LotroServerRequestHandler {
@@ -66,14 +62,31 @@ public class LotroServerRequestHandler {
}
}
private String getLoggedUser(HttpRequest request) {
CookieDecoder cookieDecoder = new CookieDecoder();
String cookieHeader = request.getHeader(COOKIE);
if (cookieHeader != null) {
Set<Cookie> cookies = cookieDecoder.decode(cookieHeader);
for (Cookie cookie : cookies) {
if (cookie.getName().equals("loggedUser")) {
String value = cookie.getValue();
if (value != null) {
_loggedUserHolder.getLoggedUser(value);
}
}
}
}
return null;
}
protected final void processDeliveryServiceNotification(HttpRequest request, Map<String, String> headersToAdd) {
String logged = _loggedUserHolder.getLoggedUser(request);
String logged = getLoggedUser(request);
if (logged != null && _transferDAO.hasUndeliveredPackages(logged))
headersToAdd.put("Delivery-Service-Package", "true");
}
protected final Player getResourceOwnerSafely(HttpRequest request, String participantId) throws HttpProcessingException {
String loggedUser = _loggedUserHolder.getLoggedUser(request);
String loggedUser = getLoggedUser(request);
if (isTest() && loggedUser == null)
loggedUser = participantId;

View File

@@ -9,6 +9,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.net.InetSocketAddress;
import java.util.Map;
public class RegisterRequestHandler extends LotroServerRequestHandler implements UriRequestHandler {
@@ -23,7 +24,7 @@ public class RegisterRequestHandler extends LotroServerRequestHandler implements
String login = getFormParameterSafely(postDecoder, "login");
String password = getFormParameterSafely(postDecoder, "password");
try {
if (_playerDao.registerUser(login, password, e.getRemoteAddress().toString())) {
if (_playerDao.registerUser(login, password, ((InetSocketAddress) e.getRemoteAddress()).getAddress().getHostAddress())) {
responseWriter.writeXmlResponse(null, logUserReturningHeaders(e, login));
} else {
throw new HttpProcessingException(409);

View File

@@ -15,6 +15,8 @@ import com.gempukku.lotro.league.LeagueService;
import com.gempukku.lotro.merchant.MerchantService;
import com.gempukku.lotro.packs.DraftPackStorage;
import com.gempukku.lotro.packs.PacksStorage;
import com.gempukku.lotro.service.AdminService;
import com.gempukku.lotro.service.LoggedUserHolder;
import com.gempukku.lotro.tournament.*;
import java.lang.reflect.Type;
@@ -49,6 +51,13 @@ public class ServerBuilder {
extract(objectMap, CollectionsManager.class),
extract(objectMap, CardSets.class)));
objectMap.put(AdminService.class,
new AdminService(
extract(objectMap, PlayerDAO.class),
extract(objectMap, IpBanDAO.class),
extract(objectMap, LoggedUserHolder.class)
));
TournamentPrizeSchemeRegistry tournamentPrizeSchemeRegistry = new TournamentPrizeSchemeRegistry();
PairingMechanismRegistry pairingMechanismRegistry = new PairingMechanismRegistry();
@@ -89,6 +98,8 @@ public class ServerBuilder {
extract(objectMap, LotroCardBlueprintLibrary.class),
extract(objectMap, LotroFormatLibrary.class),
extract(objectMap, CollectionsManager.class),
extract(objectMap, IpBanDAO.class),
extract(objectMap, AdminService.class),
tournamentPrizeSchemeRegistry,
pairingMechanismRegistry,
extract(objectMap, CardSets.class)

View File

@@ -0,0 +1,5 @@
package com.gempukku.lotro.chat;
public interface ChatCommandCallback {
public void commandReceived(String from, String parameters, boolean admin) throws ChatCommandErrorException;
}

View File

@@ -0,0 +1,7 @@
package com.gempukku.lotro.chat;
public class ChatCommandErrorException extends Exception {
public ChatCommandErrorException(String message) {
super(message);
}
}

View File

@@ -20,6 +20,8 @@ public class ChatRoomMediator {
private ReadWriteLock _lock = new ReentrantReadWriteLock();
private Map<String, ChatCommandCallback> _chatCommandCallbacks = new HashMap<String, ChatCommandCallback>();
public ChatRoomMediator(String roomName, boolean muteJoinPartMessages, int secondsTimeoutPeriod) {
this(roomName, muteJoinPartMessages, secondsTimeoutPeriod, null);
}
@@ -31,6 +33,10 @@ public class ChatRoomMediator {
_chatRoom = new ChatRoom(muteJoinPartMessages);
}
public void addChatCommandCallback(String command, ChatCommandCallback callback) {
_chatCommandCallbacks.put(command.toLowerCase(), callback);
}
public List<ChatMessage> joinUser(String playerId, boolean admin) throws PrivateInformationException {
_lock.writeLock().lock();
try {
@@ -68,7 +74,10 @@ public class ChatRoomMediator {
}
}
public void sendMessage(String playerId, String message, boolean admin) throws PrivateInformationException {
public void sendMessage(String playerId, String message, boolean admin) throws PrivateInformationException, ChatCommandErrorException {
if (processIfKnownCommand(playerId, message, admin))
return;
_lock.writeLock().lock();
try {
if (!admin && _allowedPlayers != null && !_allowedPlayers.contains(playerId))
@@ -81,6 +90,28 @@ public class ChatRoomMediator {
}
}
private boolean processIfKnownCommand(String playerId, String message, boolean admin) throws ChatCommandErrorException {
if (message.startsWith("/")) {
// Maybe it's a known command
String commandString = message.substring(1);
int spaceIndex = commandString.indexOf(" ");
String commandName;
String commandParameters="";
if (spaceIndex>-1) {
commandName = commandString.substring(0, spaceIndex);
commandParameters = commandString.substring(spaceIndex+1);
} else {
commandName = commandString;
}
final ChatCommandCallback callbackForCommand = _chatCommandCallbacks.get(commandName.toLowerCase());
if (callbackForCommand != null) {
callbackForCommand.commandReceived(playerId, commandParameters, admin);
return true;
}
}
return false;
}
public void cleanup() {
_lock.writeLock().lock();
try {

View File

@@ -16,6 +16,8 @@ public class ChatServer extends AbstractServer {
chatRoom.sendMessage("System", "Welcome to room: " + name, true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
} catch (ChatCommandErrorException e) {
// Ignore, no command
}
_chatRooms.put(name, chatRoom);
return chatRoom;
@@ -27,6 +29,8 @@ public class ChatServer extends AbstractServer {
chatRoom.sendMessage("System", "Welcome to private room: " + name, true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
} catch (ChatCommandErrorException e) {
// Ignore, no command
}
_chatRooms.put(name, chatRoom);
return chatRoom;
@@ -38,6 +42,8 @@ public class ChatServer extends AbstractServer {
chatRoomMediator.sendMessage("System", message, true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
} catch (ChatCommandErrorException e) {
// Ignore, no command
}
}

View File

@@ -2,6 +2,7 @@ package com.gempukku.lotro.game;
import com.gempukku.lotro.AbstractServer;
import com.gempukku.lotro.PrivateInformationException;
import com.gempukku.lotro.chat.ChatCommandErrorException;
import com.gempukku.lotro.chat.ChatServer;
import com.gempukku.lotro.db.DeckDAO;
import com.gempukku.lotro.logic.timing.GameResultListener;
@@ -55,6 +56,8 @@ public class LotroServer extends AbstractServer {
_chatServer.getChatRoom(getChatRoomName(gameId)).sendMessage("System", "This game is already finished and will be shortly removed, please move to the Game Hall", true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
} catch (ChatCommandErrorException e) {
// Ignore, no command
}
_gameDeathWarningsSent.add(gameId);
}

View File

@@ -2,9 +2,12 @@ package com.gempukku.lotro.hall;
import com.gempukku.lotro.*;
import com.gempukku.lotro.cards.CardSets;
import com.gempukku.lotro.chat.ChatCommandCallback;
import com.gempukku.lotro.chat.ChatCommandErrorException;
import com.gempukku.lotro.chat.ChatRoomMediator;
import com.gempukku.lotro.chat.ChatServer;
import com.gempukku.lotro.collection.CollectionsManager;
import com.gempukku.lotro.db.IpBanDAO;
import com.gempukku.lotro.db.vo.CollectionType;
import com.gempukku.lotro.db.vo.League;
import com.gempukku.lotro.draft.Draft;
@@ -17,6 +20,7 @@ import com.gempukku.lotro.league.LeagueService;
import com.gempukku.lotro.logic.GameUtils;
import com.gempukku.lotro.logic.timing.GameResultListener;
import com.gempukku.lotro.logic.vo.LotroDeck;
import com.gempukku.lotro.service.AdminService;
import com.gempukku.lotro.tournament.*;
import java.text.ParseException;
@@ -40,6 +44,8 @@ public class HallServer extends AbstractServer {
private LotroServer _lotroServer;
private PairingMechanismRegistry _pairingMechanismRegistry;
private CardSets _cardSets;
private IpBanDAO _ipBanDAO;
private AdminService _adminService;
private TournamentPrizeSchemeRegistry _tournamentPrizeSchemeRegistry;
private CollectionType _allCardsCollectionType = CollectionType.ALL_CARDS;
@@ -65,7 +71,9 @@ public class HallServer extends AbstractServer {
private final GameResultListener _notifyHallListeners = new NotifyHallListenersGameResultListener();
public HallServer(LotroServer lotroServer, ChatServer chatServer, LeagueService leagueService, TournamentService tournamentService, LotroCardBlueprintLibrary library,
LotroFormatLibrary formatLibrary, CollectionsManager collectionsManager, TournamentPrizeSchemeRegistry tournamentPrizeSchemeRegistry,
LotroFormatLibrary formatLibrary, CollectionsManager collectionsManager,
IpBanDAO ipBanDAO, AdminService adminService,
TournamentPrizeSchemeRegistry tournamentPrizeSchemeRegistry,
PairingMechanismRegistry pairingMechanismRegistry, CardSets cardSets) {
_lotroServer = lotroServer;
_chatServer = chatServer;
@@ -74,10 +82,46 @@ public class HallServer extends AbstractServer {
_library = library;
_formatLibrary = formatLibrary;
_collectionsManager = collectionsManager;
_ipBanDAO = ipBanDAO;
_adminService = adminService;
_tournamentPrizeSchemeRegistry = tournamentPrizeSchemeRegistry;
_pairingMechanismRegistry = pairingMechanismRegistry;
_cardSets = cardSets;
_hallChat = _chatServer.createChatRoom("Game Hall", true, 15);
_hallChat.addChatCommandCallback("ban",
new ChatCommandCallback() {
@Override
public void commandReceived(String from, String parameters, boolean admin) throws ChatCommandErrorException {
if (admin) {
_adminService.banUser(parameters.trim());
} else {
throw new ChatCommandErrorException("Only administrator can ban users");
}
}
});
_hallChat.addChatCommandCallback("banIp",
new ChatCommandCallback() {
@Override
public void commandReceived(String from, String parameters, boolean admin) throws ChatCommandErrorException {
if (admin) {
_adminService.banIp(parameters.trim());
} else {
throw new ChatCommandErrorException("Only administrator can ban users");
}
}
});
_hallChat.addChatCommandCallback("banIpRange",
new ChatCommandCallback() {
@Override
public void commandReceived(String from, String parameters, boolean admin) throws ChatCommandErrorException {
if (admin) {
_adminService.banIpPrefix(parameters.trim());
} else {
throw new ChatCommandErrorException("Only administrator can ban users");
}
}
});
_tournamentQueues.put("fotr_queue", new ImmediateRecurringQueue(635, "fotr_block",
CollectionType.ALL_CARDS, "fotrQueue-", "Fellowship Block", 8,
@@ -812,6 +856,8 @@ public class HallServer extends AbstractServer {
_hallChat.sendMessage("TournamentSystem", message, true);
} catch (PrivateInformationException exp) {
// Ignore, sent as admin
} catch (ChatCommandErrorException e) {
// Ignore, no command
}
}
}

View File

@@ -0,0 +1,75 @@
package com.gempukku.lotro.service;
import com.gempukku.lotro.db.IpBanDAO;
import com.gempukku.lotro.db.PlayerDAO;
import com.gempukku.lotro.game.Player;
import java.sql.SQLException;
public class AdminService {
public static final int DAY_IN_MILIS = 1000 * 60 * 60 * 24;
private PlayerDAO _playerDAO;
private LoggedUserHolder _loggedUserHolder;
private IpBanDAO _ipBanDAO;
public AdminService(PlayerDAO playerDAO, IpBanDAO ipBanDAO, LoggedUserHolder loggedUserHolder) {
_playerDAO = playerDAO;
_ipBanDAO = ipBanDAO;
_loggedUserHolder = loggedUserHolder;
}
public boolean banUser(String login) {
try {
final boolean success = _playerDAO.banPlayerPermanently(login);
if (!success)
return false;
_loggedUserHolder.forceLogoutUser(login);
return true;
} catch (SQLException exp) {
return false;
}
}
public boolean banUserTemp(String login, int days) {
try {
final boolean success = _playerDAO.banPlayerTemporarily(login, System.currentTimeMillis() + days * DAY_IN_MILIS);
if (!success)
return false;
_loggedUserHolder.forceLogoutUser(login);
return true;
} catch (SQLException exp) {
return false;
}
}
public boolean unBanUser(String login) {
try {
return _playerDAO.unBanPlayer(login);
} catch (SQLException exp) {
return false;
}
}
public boolean banIp(String login) {
final Player player = _playerDAO.getPlayer(login);
if (player == null)
return false;
final String lastIp = player.getLastIp();
_ipBanDAO.addIpBan(lastIp);
return banUser(login);
}
public boolean banIpPrefix(String login) {
final Player player = _playerDAO.getPlayer(login);
if (player == null)
return false;
final String lastIp = player.getLastIp();
String lastIpPrefix = lastIp.substring(0, lastIp.lastIndexOf(".")+1);
_ipBanDAO.addIpPrefixBan(lastIpPrefix);
return banUser(login);
}
}

View File

@@ -1,17 +1,12 @@
package com.gempukku.lotro.async;
package com.gempukku.lotro.service;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.jboss.netty.handler.codec.http.Cookie;
import org.jboss.netty.handler.codec.http.CookieDecoder;
import org.jboss.netty.handler.codec.http.HttpRequest;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.COOKIE;
public class LoggedUserHolder {
private long _loggedUserExpireLength = 1000 * 60 * 10; // 10 minutes session length
private long _expireCheckInterval = 1000 * 60; // check every minute
@@ -29,30 +24,18 @@ public class LoggedUserHolder {
thr.start();
}
public String getLoggedUser(HttpRequest request) {
public String getLoggedUser(String sessionId) {
_readWriteLock.readLock().lock();
try {
CookieDecoder cookieDecoder = new CookieDecoder();
String cookieHeader = request.getHeader(COOKIE);
if (cookieHeader != null) {
Set<Cookie> cookies = cookieDecoder.decode(cookieHeader);
for (Cookie cookie : cookies) {
if (cookie.getName().equals("loggedUser")) {
String value = cookie.getValue();
if (value != null) {
String loggedUser = _sessionIdsToUsers.get(value);
if (loggedUser != null) {
_lastAccess.put(value, System.currentTimeMillis());
return loggedUser;
}
}
}
}
String loggedUser = _sessionIdsToUsers.get(sessionId);
if (loggedUser != null) {
_lastAccess.put(sessionId, System.currentTimeMillis());
return loggedUser;
}
return null;
} finally {
_readWriteLock.readLock().unlock();
}
return null;
}
public Map<String, String> logUser(String userName) {