- reorder stuff in admin.jsp
- add my global ip address to admin whitelist - add kick functionality to admin.jsp - admin.jsp redirects to itself after processing actions to avoid refreshing re-processing the action - ConnectedUsers invalidates the user when removing it
This commit is contained in:
parent
987c01cc5a
commit
83a807f4b8
|
@ -2,19 +2,33 @@
|
||||||
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
<%@ page language="java" contentType="text/html; charset=UTF-8"
|
||||||
pageEncoding="UTF-8" %>
|
pageEncoding="UTF-8" %>
|
||||||
<%@ page import="com.google.inject.Injector" %>
|
<%@ page import="com.google.inject.Injector" %>
|
||||||
|
<%@ page import="net.socialgamer.cah.Constants.DisconnectReason" %>
|
||||||
|
<%@ page import="net.socialgamer.cah.Constants.LongPollEvent" %>
|
||||||
|
<%@ page import="net.socialgamer.cah.Constants.LongPollResponse" %>
|
||||||
|
<%@ page import="net.socialgamer.cah.Constants.ReturnableData" %>
|
||||||
<%@ page import="net.socialgamer.cah.StartupUtils" %>
|
<%@ page import="net.socialgamer.cah.StartupUtils" %>
|
||||||
<%@ page import="net.socialgamer.cah.data.ConnectedUsers" %>
|
<%@ page import="net.socialgamer.cah.data.ConnectedUsers" %>
|
||||||
|
<%@ page import="net.socialgamer.cah.data.QueuedMessage" %>
|
||||||
|
<%@ page import="net.socialgamer.cah.data.QueuedMessage.MessageType" %>
|
||||||
<%@ page import="net.socialgamer.cah.data.User" %>
|
<%@ page import="net.socialgamer.cah.data.User" %>
|
||||||
<%@ page import="java.util.Collection" %>
|
<%@ page import="java.util.Collection" %>
|
||||||
<%@ page import="java.util.Date" %>
|
<%@ page import="java.util.Date" %>
|
||||||
|
<%@ page import="java.util.HashMap" %>
|
||||||
|
<%@ page import="java.util.Map" %>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
String remoteAddr = request.getRemoteAddr();
|
String remoteAddr = request.getRemoteAddr();
|
||||||
if (!(remoteAddr.equals("0:0:0:0:0:0:0:1") || remoteAddr.equals("127.0.0.1"))) {
|
// TODO better access control than hard-coding IP addresses.
|
||||||
|
if (!(remoteAddr.equals("0:0:0:0:0:0:0:1") || remoteAddr.equals("127.0.0.1") ||
|
||||||
|
remoteAddr.equals("98.248.33.90"))) {
|
||||||
response.sendError(403, "Access is restricted to known hosts");
|
response.sendError(403, "Access is restricted to known hosts");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServletContext servletContext = pageContext.getServletContext();
|
ServletContext servletContext = pageContext.getServletContext();
|
||||||
|
Injector injector = (Injector) servletContext.getAttribute(StartupUtils.INJECTOR);
|
||||||
|
|
||||||
|
ConnectedUsers connectedUsers = injector.getInstance(ConnectedUsers.class);
|
||||||
|
|
||||||
// process verbose toggle
|
// process verbose toggle
|
||||||
String verboseParam = request.getParameter("verbose");
|
String verboseParam = request.getParameter("verbose");
|
||||||
|
@ -24,11 +38,29 @@ if (verboseParam != null) {
|
||||||
} else {
|
} else {
|
||||||
servletContext.setAttribute(StartupUtils.VERBOSE_DEBUG, Boolean.FALSE);
|
servletContext.setAttribute(StartupUtils.VERBOSE_DEBUG, Boolean.FALSE);
|
||||||
}
|
}
|
||||||
|
response.sendRedirect("admin.jsp");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process kick
|
||||||
|
String kickParam = request.getParameter("kick");
|
||||||
|
if (kickParam != null) {
|
||||||
|
User user = connectedUsers.getUser(kickParam);
|
||||||
|
if (user != null) {
|
||||||
|
Map<ReturnableData, Object> data = new HashMap<ReturnableData, Object>();
|
||||||
|
data.put(LongPollResponse.EVENT, LongPollEvent.KICKED.toString());
|
||||||
|
QueuedMessage qm = new QueuedMessage(MessageType.KICKED, data);
|
||||||
|
user.enqueueMessage(qm);
|
||||||
|
|
||||||
|
connectedUsers.removeUser(user, DisconnectReason.KICKED);
|
||||||
|
}
|
||||||
|
response.sendRedirect("admin.jsp");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
%>
|
%>
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
|
@ -45,20 +77,16 @@ th, td {
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<%
|
|
||||||
Injector injector = (Injector) servletContext.getAttribute(StartupUtils.INJECTOR);
|
|
||||||
%>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Server up since
|
Server up since
|
||||||
<%
|
<%
|
||||||
Date startedDate = (Date) servletContext.getAttribute(StartupUtils.DATE_NAME);
|
Date startedDate = (Date) servletContext.getAttribute(StartupUtils.DATE_NAME);
|
||||||
long uptime = System.currentTimeMillis() - startedDate.getTime();
|
long uptime = System.currentTimeMillis() - startedDate.getTime();
|
||||||
uptime /= 1000l;
|
uptime /= 1000L;
|
||||||
long seconds = uptime % 60l;
|
long seconds = uptime % 60L;
|
||||||
long minutes = (uptime / 60l) % 60l;
|
long minutes = (uptime / 60L) % 60L;
|
||||||
long hours = (uptime / 60l / 60l) % 24l;
|
long hours = (uptime / 60L / 60L) % 24L;
|
||||||
long days = (uptime / 60l / 60l / 24l);
|
long days = (uptime / 60L / 60L / 24L);
|
||||||
out.print(String.format("%s (%d hours, %02d:%02d:%02d)",
|
out.print(String.format("%s (%d hours, %02d:%02d:%02d)",
|
||||||
startedDate.toString(), days, hours, minutes, seconds));
|
startedDate.toString(), days, hours, minutes, seconds));
|
||||||
%>
|
%>
|
||||||
|
@ -72,38 +100,37 @@ Injector injector = (Injector) servletContext.getAttribute(StartupUtils.INJECTOR
|
||||||
<tr>
|
<tr>
|
||||||
<td>In Use</td>
|
<td>In Use</td>
|
||||||
<td><% out.print((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())
|
<td><% out.print((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())
|
||||||
/ 1024 / 1024); %></td>
|
/ 1024L / 1024L); %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Free</td>
|
<td>Free</td>
|
||||||
<td><% out.print(Runtime.getRuntime().freeMemory() / 1024 / 1024); %></td>
|
<td><% out.print(Runtime.getRuntime().freeMemory() / 1024L / 1024L); %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>JVM Allocated</td>
|
<td>JVM Allocated</td>
|
||||||
<td><% out.print(Runtime.getRuntime().totalMemory() / 1024 / 1024); %></td>
|
<td><% out.print(Runtime.getRuntime().totalMemory() / 1024L / 1024L); %></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>JVM Max</td>
|
<td>JVM Max</td>
|
||||||
<td><% out.print(Runtime.getRuntime().maxMemory() / 1024 / 1024); %></td>
|
<td><% out.print(Runtime.getRuntime().maxMemory() / 1024L / 1024L); %></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<%
|
|
||||||
ConnectedUsers connectedUsers = injector.getInstance(ConnectedUsers.class);
|
|
||||||
Collection<User> users = connectedUsers.getUsers();
|
|
||||||
%>
|
|
||||||
<br/>
|
<br/>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Username</th>
|
<th>Username</th>
|
||||||
<th>Host</th>
|
<th>Host</th>
|
||||||
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
<%
|
<%
|
||||||
|
Collection<User> users = connectedUsers.getUsers();
|
||||||
for (User u : users) {
|
for (User u : users) {
|
||||||
|
// TODO have a ban system. would need to store them somewhere.
|
||||||
%>
|
%>
|
||||||
<tr>
|
<tr>
|
||||||
<td><% out.print(u.getNickname()); %></td>
|
<td><% out.print(u.getNickname()); %></td>
|
||||||
<td><% out.print(u.getHostName()); %></td>
|
<td><% out.print(u.getHostName()); %></td>
|
||||||
|
<td><a href="?kick=<% out.print(u.getNickname()); %>">Kick</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<%
|
<%
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,13 +193,14 @@ cah.$.LongPollEvent = function() {
|
||||||
// Dummy constructor to make Eclipse auto-complete.
|
// Dummy constructor to make Eclipse auto-complete.
|
||||||
};
|
};
|
||||||
cah.$.LongPollEvent.prototype.dummyForAutocomplete = undefined;
|
cah.$.LongPollEvent.prototype.dummyForAutocomplete = undefined;
|
||||||
|
cah.$.LongPollEvent.KICKED = "kicked";
|
||||||
cah.$.LongPollEvent.GAME_PLAYER_LEAVE = "game_player_leave";
|
cah.$.LongPollEvent.GAME_PLAYER_LEAVE = "game_player_leave";
|
||||||
cah.$.LongPollEvent.NEW_PLAYER = "new_player";
|
cah.$.LongPollEvent.NEW_PLAYER = "new_player";
|
||||||
cah.$.LongPollEvent.GAME_PLAYER_JOIN = "game_player_join";
|
cah.$.LongPollEvent.GAME_PLAYER_JOIN = "game_player_join";
|
||||||
cah.$.LongPollEvent.GAME_LIST_REFRESH = "game_list_refresh";
|
cah.$.LongPollEvent.GAME_LIST_REFRESH = "game_list_refresh";
|
||||||
cah.$.LongPollEvent.GAME_ROUND_COMPLETE = "game_round_complete";
|
cah.$.LongPollEvent.GAME_ROUND_COMPLETE = "game_round_complete";
|
||||||
cah.$.LongPollEvent.GAME_PLAYER_INFO_CHANGE = "game_player_info_change";
|
|
||||||
cah.$.LongPollEvent.NOOP = "noop";
|
cah.$.LongPollEvent.NOOP = "noop";
|
||||||
|
cah.$.LongPollEvent.GAME_PLAYER_INFO_CHANGE = "game_player_info_change";
|
||||||
cah.$.LongPollEvent.GAME_BLACK_RESHUFFLE = "game_black_reshuffle";
|
cah.$.LongPollEvent.GAME_BLACK_RESHUFFLE = "game_black_reshuffle";
|
||||||
cah.$.LongPollEvent.GAME_WHITE_RESHUFFLE = "game_white_reshuffle";
|
cah.$.LongPollEvent.GAME_WHITE_RESHUFFLE = "game_white_reshuffle";
|
||||||
cah.$.LongPollEvent.GAME_STATE_CHANGE = "game_state_change";
|
cah.$.LongPollEvent.GAME_STATE_CHANGE = "game_state_change";
|
||||||
|
|
|
@ -38,6 +38,15 @@ cah.longpoll.EventHandlers[cah.$.LongPollEvent.NOOP] = function(data) {
|
||||||
// pass
|
// pass
|
||||||
};
|
};
|
||||||
|
|
||||||
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.KICKED] = function() {
|
||||||
|
cah.log.status("You have been kicked by the server administrator.");
|
||||||
|
cah.longpoll.Resume = false;
|
||||||
|
$("input").attr("disabled", "disabled");
|
||||||
|
$("#menubar_left").empty();
|
||||||
|
$("#main").empty();
|
||||||
|
$("#info_area").empty();
|
||||||
|
};
|
||||||
|
|
||||||
cah.longpoll.EventHandlers[cah.$.LongPollEvent.CHAT] = function(data) {
|
cah.longpoll.EventHandlers[cah.$.LongPollEvent.CHAT] = function(data) {
|
||||||
// TODO deal with multiple channels eventually
|
// TODO deal with multiple channels eventually
|
||||||
// don't display our own chat
|
// don't display our own chat
|
||||||
|
|
|
@ -210,6 +210,7 @@ public class Constants {
|
||||||
GAME_STATE_CHANGE("game_state_change"),
|
GAME_STATE_CHANGE("game_state_change"),
|
||||||
GAME_WHITE_RESHUFFLE("game_white_reshuffle"),
|
GAME_WHITE_RESHUFFLE("game_white_reshuffle"),
|
||||||
HAND_DEAL("hand_deal"),
|
HAND_DEAL("hand_deal"),
|
||||||
|
KICKED("kicked"),
|
||||||
NEW_PLAYER("new_player"),
|
NEW_PLAYER("new_player"),
|
||||||
NOOP("noop"),
|
NOOP("noop"),
|
||||||
PLAYER_LEAVE("player_leave");
|
PLAYER_LEAVE("player_leave");
|
||||||
|
|
|
@ -12,6 +12,7 @@ import net.socialgamer.cah.Constants.ReturnableData;
|
||||||
import net.socialgamer.cah.data.QueuedMessage.MessageType;
|
import net.socialgamer.cah.data.QueuedMessage.MessageType;
|
||||||
|
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
|
import com.sun.istack.internal.Nullable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,11 +48,25 @@ public class ConnectedUsers {
|
||||||
|
|
||||||
public void removeUser(final User user, final DisconnectReason reason) {
|
public void removeUser(final User user, final DisconnectReason reason) {
|
||||||
synchronized (users) {
|
synchronized (users) {
|
||||||
users.remove(user.getNickname());
|
if (users.containsValue(user)) {
|
||||||
notifyRemoveUser(user, reason);
|
user.noLongerVaild();
|
||||||
|
users.remove(user.getNickname());
|
||||||
|
notifyRemoveUser(user, reason);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the User for the specified nickname, or null if no such user exists.
|
||||||
|
*
|
||||||
|
* @param nickname
|
||||||
|
* @return User, or null.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public User getUser(final String nickname) {
|
||||||
|
return users.get(nickname);
|
||||||
|
}
|
||||||
|
|
||||||
private void notifyRemoveUser(final User user, final DisconnectReason reason) {
|
private void notifyRemoveUser(final User user, final DisconnectReason reason) {
|
||||||
// We might also have to tell games about this directly, probably with a listener system.
|
// We might also have to tell games about this directly, probably with a listener system.
|
||||||
final HashMap<ReturnableData, Object> data = new HashMap<ReturnableData, Object>();
|
final HashMap<ReturnableData, Object> data = new HashMap<ReturnableData, Object>();
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class QueuedMessage implements Comparable<QueuedMessage> {
|
||||||
* @author ajanata
|
* @author ajanata
|
||||||
*/
|
*/
|
||||||
public enum MessageType {
|
public enum MessageType {
|
||||||
PLAYER_EVENT(3), GAME_EVENT(3), GAME_PLAYER_EVENT(4), CHAT(5);
|
KICKED(1), PLAYER_EVENT(3), GAME_EVENT(3), GAME_PLAYER_EVENT(4), CHAT(5);
|
||||||
|
|
||||||
private final int weight;
|
private final int weight;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue