forked from External/mage
Added chat mute and user (de)activation actions to the Mage server console.
This commit is contained in:
parent
7c4b40073c
commit
c46f75ac28
18 changed files with 511 additions and 213 deletions
|
|
@ -1,20 +1,22 @@
|
|||
package mage.server;
|
||||
|
||||
import com.j256.ormlite.field.DataType;
|
||||
import com.j256.ormlite.field.DatabaseField;
|
||||
import com.j256.ormlite.table.DatabaseTable;
|
||||
import java.util.Date;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.SimpleAuthenticationInfo;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
|
||||
import org.apache.shiro.util.ByteSource;
|
||||
import org.apache.shiro.codec.Base64;
|
||||
import org.apache.shiro.crypto.hash.Hash;
|
||||
import org.apache.shiro.util.ByteSource;
|
||||
|
||||
@DatabaseTable(tableName = "authorized_user")
|
||||
public class AuthorizedUser {
|
||||
|
||||
@DatabaseField(indexName = "name_index", unique = true)
|
||||
@DatabaseField(id = true, indexName = "name_index", unique = true)
|
||||
protected String name;
|
||||
|
||||
@DatabaseField
|
||||
|
|
@ -32,6 +34,18 @@ public class AuthorizedUser {
|
|||
@DatabaseField(indexName = "email_index", unique = true)
|
||||
protected String email;
|
||||
|
||||
@DatabaseField
|
||||
protected boolean active; // the user can't sign in
|
||||
|
||||
@DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss")
|
||||
protected Date lockedUntil; // the user can't sign in until timestamp
|
||||
|
||||
@DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss")
|
||||
protected Date chatLockedUntil; // the user can't use the chat until timestamp
|
||||
|
||||
@DatabaseField(dataType = DataType.DATE_STRING, format = "yyyy-MM-dd HH:mm:ss")
|
||||
protected Date lastConnection; // time of the last user connect
|
||||
|
||||
public AuthorizedUser() {
|
||||
}
|
||||
|
||||
|
|
@ -42,6 +56,9 @@ public class AuthorizedUser {
|
|||
this.hashAlgorithm = hash.getAlgorithmName();
|
||||
this.hashIterations = hash.getIterations();
|
||||
this.email = email;
|
||||
this.chatLockedUntil = null;
|
||||
this.active = true;
|
||||
this.lockedUntil = null;
|
||||
}
|
||||
|
||||
public boolean doCredentialsMatch(String name, String password) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.j256.ormlite.table.TableUtils;
|
|||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.cards.repository.RepositoryUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.shiro.crypto.RandomNumberGenerator;
|
||||
|
|
@ -27,7 +28,7 @@ public enum AuthorizedUserRepository {
|
|||
private static final String JDBC_URL = "jdbc:h2:file:./db/authorized_user.h2;AUTO_SERVER=TRUE";
|
||||
private static final String VERSION_ENTITY_NAME = "authorized_user";
|
||||
// raise this if db structure was changed
|
||||
private static final long DB_VERSION = 1;
|
||||
private static final long DB_VERSION = 2;
|
||||
private static final RandomNumberGenerator rng = new SecureRandomNumberGenerator();
|
||||
|
||||
private Dao<AuthorizedUser, Object> dao;
|
||||
|
|
@ -39,16 +40,10 @@ public enum AuthorizedUserRepository {
|
|||
}
|
||||
try {
|
||||
ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL);
|
||||
boolean obsolete = RepositoryUtil.isDatabaseObsolete(connectionSource, VERSION_ENTITY_NAME, DB_VERSION);
|
||||
|
||||
if (obsolete) {
|
||||
TableUtils.dropTable(connectionSource, AuthorizedUser.class, true);
|
||||
}
|
||||
|
||||
TableUtils.createTableIfNotExists(connectionSource, AuthorizedUser.class);
|
||||
dao = DaoManager.createDao(connectionSource, AuthorizedUser.class);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error creating authorized_user repository - ", ex);
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error creating / assigning authorized_user repository - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,6 +82,14 @@ public enum AuthorizedUserRepository {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void update(AuthorizedUser authorizedUser) {
|
||||
try {
|
||||
dao.update(authorizedUser);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error updating authorized_user", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public AuthorizedUser getByEmail(String userName) {
|
||||
try {
|
||||
QueryBuilder<AuthorizedUser, Object> qb = dao.queryBuilder();
|
||||
|
|
@ -112,4 +115,38 @@ public enum AuthorizedUserRepository {
|
|||
Logger.getLogger(AuthorizedUserRepository.class).error("Error closing authorized_user repository - ", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public long getDBVersionFromDB() {
|
||||
try {
|
||||
ConnectionSource connectionSource = new JdbcConnectionSource(JDBC_URL);
|
||||
return RepositoryUtil.getDatabaseVersion(connectionSource, VERSION_ENTITY_NAME);
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(CardRepository.class).error("Error getting DB version from DB - ", ex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean checkAlterAndMigrateAuthorizedUser() {
|
||||
long currentDBVersion = getDBVersionFromDB();
|
||||
if (currentDBVersion == 1 && DB_VERSION == 2) {
|
||||
return migrateFrom1To2();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean migrateFrom1To2() {
|
||||
try {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).info("Starting " + VERSION_ENTITY_NAME + " DB migration from version 1 to version 2");
|
||||
dao.executeRaw("ALTER TABLE authorized_user ADD COLUMN active BOOLEAN DEFAULT true;");
|
||||
dao.executeRaw("ALTER TABLE authorized_user ADD COLUMN lockedUntil DATETIME;");
|
||||
dao.executeRaw("ALTER TABLE authorized_user ADD COLUMN chatLockedUntil DATETIME;");
|
||||
dao.executeRaw("ALTER TABLE authorized_user ADD COLUMN lastConnection DATETIME;");
|
||||
RepositoryUtil.updateVersion(dao.getConnectionSource(), VERSION_ENTITY_NAME, DB_VERSION);
|
||||
Logger.getLogger(AuthorizedUserRepository.class).info("Migration finished.");
|
||||
return true;
|
||||
} catch (SQLException ex) {
|
||||
Logger.getLogger(AuthorizedUserRepository.class).error("Error while migrating from version 1 to version 2 - ", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,11 @@
|
|||
package mage.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import mage.server.util.SystemUtil;
|
||||
import mage.view.ChatMessage.MessageColor;
|
||||
import mage.view.ChatMessage.MessageType;
|
||||
import mage.view.ChatMessage.SoundToPlay;
|
||||
|
|
@ -94,10 +96,6 @@ public class ChatManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void broadcast(UUID chatId, String userName, String message, MessageColor color) {
|
||||
this.broadcast(chatId, userName, message, color, true);
|
||||
}
|
||||
|
||||
public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime) {
|
||||
this.broadcast(chatId, userName, message, color, withTime, MessageType.TALK);
|
||||
}
|
||||
|
|
@ -121,8 +119,25 @@ public class ChatManager {
|
|||
}
|
||||
}
|
||||
|
||||
if (!messageType.equals(MessageType.GAME) && message.equals(lastMessage)) {
|
||||
return;
|
||||
if (!messageType.equals(MessageType.GAME)) {
|
||||
if (message.equals(lastMessage)) {
|
||||
// prevent identical messages
|
||||
return;
|
||||
}
|
||||
if (messageType.equals(MessageType.TALK)) {
|
||||
User user = UserManager.getInstance().getUserByName(userName);
|
||||
if (user != null) {
|
||||
if (user.getChatLockedUntil() != null) {
|
||||
if (user.getChatLockedUntil().compareTo(Calendar.getInstance().getTime()) > 0) {
|
||||
chatSessions.get(chatId).broadcastInfoToUser(user, "Your chat is muted until " + SystemUtil.dateFormat.format(user.getChatLockedUntil()));
|
||||
return;
|
||||
} else {
|
||||
user.setChatLockedUntil(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
lastMessage = message;
|
||||
chatSession.broadcast(userName, message, color, withTime, messageType, soundToPlay);
|
||||
|
|
@ -195,7 +210,7 @@ public class ChatManager {
|
|||
if (user != null) {
|
||||
for (ChatSession chat : chatSessions.values()) {
|
||||
if (chat.hasUser(userId)) {
|
||||
chat.broadcast(user.getName(), message, color);
|
||||
chat.broadcast(user.getName(), message, color, true, MessageType.TALK, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -206,7 +221,7 @@ public class ChatManager {
|
|||
if (user != null) {
|
||||
for (ChatSession chat : chatSessions.values()) {
|
||||
if (chat.hasUser(userId)) {
|
||||
chat.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS);
|
||||
chat.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public class ChatSession {
|
|||
if (user != null && !clients.containsKey(userId)) {
|
||||
String userName = user.getName();
|
||||
clients.put(userId, userName);
|
||||
broadcast(null, userName + " has joined", MessageColor.BLUE, true, MessageType.STATUS);
|
||||
broadcast(null, userName + " has joined", MessageColor.BLUE, true, MessageType.STATUS, null);
|
||||
logger.trace(userName + " joined chat " + chatId);
|
||||
}
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ public class ChatSession {
|
|||
message = " left (" + reason.toString() + ")";
|
||||
}
|
||||
if (message != null) {
|
||||
broadcast(null, userName + message, MessageColor.BLUE, true, MessageType.STATUS);
|
||||
broadcast(null, userName + message, MessageColor.BLUE, true, MessageType.STATUS, null);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
|
|
@ -136,18 +136,6 @@ public class ChatSession {
|
|||
return false;
|
||||
}
|
||||
|
||||
public void broadcast(String userName, String message, MessageColor color) {
|
||||
this.broadcast(userName, message, color, true);
|
||||
}
|
||||
|
||||
public void broadcast(String userName, String message, MessageColor color, boolean withTime) {
|
||||
this.broadcast(userName, message, color, withTime, MessageType.TALK);
|
||||
}
|
||||
|
||||
public void broadcast(String userName, String message, MessageColor color, boolean withTime, MessageType messageType) {
|
||||
this.broadcast(userName, message, color, withTime, messageType, null);
|
||||
}
|
||||
|
||||
public void broadcast(String userName, String message, MessageColor color, boolean withTime, MessageType messageType, SoundToPlay soundToPlay) {
|
||||
if (!message.isEmpty()) {
|
||||
boolean remove = false;
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@
|
|||
package mage.server;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
|
@ -77,6 +75,7 @@ import mage.server.tournament.TournamentFactory;
|
|||
import mage.server.tournament.TournamentManager;
|
||||
import mage.server.util.ConfigSettings;
|
||||
import mage.server.util.ServerMessagesUtil;
|
||||
import mage.server.util.SystemUtil;
|
||||
import mage.server.util.ThreadExecutor;
|
||||
import mage.utils.ActionWithBooleanResult;
|
||||
import mage.utils.ActionWithNullNegativeResult;
|
||||
|
|
@ -105,8 +104,6 @@ public class MageServerImpl implements MageServer {
|
|||
private static final ExecutorService callExecutor = ThreadExecutor.getInstance().getCallExecutor();
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-M-dd hh:mm:ss");
|
||||
|
||||
private final String adminPassword;
|
||||
private final boolean testMode;
|
||||
private final LinkedHashMap<String, String> activeAuthTokens = new LinkedHashMap<String, String>() {
|
||||
|
|
@ -540,7 +537,7 @@ public class MageServerImpl implements MageServer {
|
|||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ChatManager.getInstance().broadcast(chatId, userName, StringEscapeUtils.escapeHtml4(message), MessageColor.BLUE);
|
||||
ChatManager.getInstance().broadcast(chatId, userName, StringEscapeUtils.escapeHtml4(message), MessageColor.BLUE, true, ChatMessage.MessageType.TALK, null);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
@ -1075,7 +1072,9 @@ public class MageServerImpl implements MageServer {
|
|||
user.getSessionId(),
|
||||
user.getConnectionTime(),
|
||||
user.getGameInfo(),
|
||||
user.getUserState().toString()));
|
||||
user.getUserState().toString(),
|
||||
user.getChatLockedUntil()
|
||||
));
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
|
@ -1100,8 +1099,38 @@ public class MageServerImpl implements MageServer {
|
|||
User user = UserManager.getInstance().getUserByName(userName);
|
||||
if (user != null) {
|
||||
Date muteUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE));
|
||||
user.showUserMessage("Admin info", "You were muted for chat messages until " + dateFormat.format(muteUntil) + ".");
|
||||
// user.setChatMuteUntil(new Date() + duationMinutes);
|
||||
user.showUserMessage("Admin info", "You were muted for chat messages until " + SystemUtil.dateFormat.format(muteUntil) + ".");
|
||||
user.setChatLockedUntil(muteUntil);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lockUser(String sessionId, final String userName, final long durationMinutes) throws MageException {
|
||||
execute("muteUser", sessionId, new Action() {
|
||||
@Override
|
||||
public void execute() {
|
||||
User user = UserManager.getInstance().getUserByName(userName);
|
||||
if (user != null) {
|
||||
Date lockUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE));
|
||||
user.showUserMessage("Admin info", "Your user profile was locked until " + SystemUtil.dateFormat.format(lockUntil) + ".");
|
||||
user.setLockedUntil(lockUntil);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggleActivation(String sessionId, final String userName) throws MageException {
|
||||
execute("muteUser", sessionId, new Action() {
|
||||
@Override
|
||||
public void execute() {
|
||||
User user = UserManager.getInstance().getUserByName(userName);
|
||||
if (user != null) {
|
||||
user.setActive(!user.isActive());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.management.MBeanServer;
|
||||
|
||||
import mage.cards.ExpansionSet;
|
||||
import mage.cards.Sets;
|
||||
import mage.cards.repository.CardScanner;
|
||||
|
|
@ -118,25 +117,42 @@ public class Main {
|
|||
}
|
||||
}
|
||||
|
||||
if (ConfigSettings.getInstance().isAuthenticationActivated()) {
|
||||
logger.info("Check authorized user DB version ...");
|
||||
if (!AuthorizedUserRepository.instance.checkAlterAndMigrateAuthorizedUser()) {
|
||||
logger.fatal("Failed to start server.");
|
||||
return;
|
||||
}
|
||||
logger.info("Done.");
|
||||
}
|
||||
|
||||
logger.info("Loading extension packages...");
|
||||
List<ExtensionPackage> extensions = new ArrayList<>();
|
||||
if(!extensionFolder.exists()) if(!extensionFolder.mkdirs())
|
||||
logger.error("Could not create extensions directory.");
|
||||
File[] extensionDirectories = extensionFolder.listFiles();
|
||||
if(extensionDirectories != null) for(File f : extensionDirectories) if(f.isDirectory())
|
||||
try {
|
||||
logger.info(" - Loading extension from "+f);
|
||||
extensions.add(ExtensionPackageLoader.loadExtension(f));
|
||||
} catch (IOException e) {
|
||||
logger.error("Could not load extension in "+f+"!", e);
|
||||
if (!extensionFolder.exists()) {
|
||||
if (!extensionFolder.mkdirs()) {
|
||||
logger.error("Could not create extensions directory.");
|
||||
}
|
||||
}
|
||||
File[] extensionDirectories = extensionFolder.listFiles();
|
||||
if (extensionDirectories != null) {
|
||||
for (File f : extensionDirectories) {
|
||||
if (f.isDirectory()) {
|
||||
try {
|
||||
logger.info(" - Loading extension from " + f);
|
||||
extensions.add(ExtensionPackageLoader.loadExtension(f));
|
||||
} catch (IOException e) {
|
||||
logger.error("Could not load extension in " + f + "!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.info("Done.");
|
||||
|
||||
if(!extensions.isEmpty()) {
|
||||
if (!extensions.isEmpty()) {
|
||||
logger.info("Registering custom sets...");
|
||||
for(ExtensionPackage pkg : extensions) {
|
||||
for(ExpansionSet set : pkg.getSets()) {
|
||||
logger.info("- Loading "+set.getName()+" ("+set.getCode()+")");
|
||||
for (ExtensionPackage pkg : extensions) {
|
||||
for (ExpansionSet set : pkg.getSets()) {
|
||||
logger.info("- Loading " + set.getName() + " (" + set.getCode() + ")");
|
||||
Sets.getInstance().addSet(set);
|
||||
}
|
||||
PluginClassloaderRegistery.registerPluginClassloader(pkg.getClassLoader());
|
||||
|
|
@ -155,7 +171,6 @@ public class Main {
|
|||
logger.info("Updating user stats DB...");
|
||||
UserStatsRepository.instance.updateUserStats();
|
||||
logger.info("Done.");
|
||||
|
||||
deleteSavedGames();
|
||||
ConfigSettings config = ConfigSettings.getInstance();
|
||||
for (GamePlugin plugin : config.getGameTypes()) {
|
||||
|
|
@ -177,12 +192,12 @@ public class Main {
|
|||
for (ExtensionPackage pkg : extensions) {
|
||||
Map<String, Class> draftCubes = pkg.getDraftCubes();
|
||||
for (String name : draftCubes.keySet()) {
|
||||
logger.info("Loading extension: ["+name+"] "+draftCubes.get(name).toString());
|
||||
logger.info("Loading extension: [" + name + "] " + draftCubes.get(name).toString());
|
||||
CubeFactory.getInstance().addDraftCube(name, draftCubes.get(name));
|
||||
}
|
||||
Map<String, Class> deckTypes = pkg.getDeckTypes();
|
||||
for (String name : deckTypes.keySet()) {
|
||||
logger.info("Loading extension: ["+name+"] "+deckTypes.get(name));
|
||||
logger.info("Loading extension: [" + name + "] " + deckTypes.get(name));
|
||||
DeckValidatorFactory.getInstance().addDeckType(name, deckTypes.get(name));
|
||||
}
|
||||
}
|
||||
|
|
@ -408,11 +423,11 @@ public class Main {
|
|||
}
|
||||
File[] files = directory.listFiles(
|
||||
new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(".game");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(".game");
|
||||
}
|
||||
}
|
||||
);
|
||||
for (File file : files) {
|
||||
file.delete();
|
||||
|
|
|
|||
|
|
@ -180,14 +180,15 @@ public class Session {
|
|||
|
||||
public String connectUserHandling(String userName, String password) throws MageException {
|
||||
this.isAdmin = false;
|
||||
AuthorizedUser authorizedUser = null;
|
||||
if (ConfigSettings.getInstance().isAuthenticationActivated()) {
|
||||
AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByName(userName);
|
||||
authorizedUser = AuthorizedUserRepository.instance.getByName(userName);
|
||||
if (authorizedUser == null || !authorizedUser.doCredentialsMatch(userName, password)) {
|
||||
return "Wrong username or password. In case you haven't, please register your account first.";
|
||||
}
|
||||
}
|
||||
|
||||
User user = UserManager.getInstance().createUser(userName, host);
|
||||
User user = UserManager.getInstance().createUser(userName, host, authorizedUser);
|
||||
boolean reconnect = false;
|
||||
if (user == null) { // user already exists
|
||||
user = UserManager.getInstance().getUserByName(userName);
|
||||
|
|
@ -223,7 +224,7 @@ public class Session {
|
|||
|
||||
public void connectAdmin() {
|
||||
this.isAdmin = true;
|
||||
User user = UserManager.getInstance().createUser("Admin", host);
|
||||
User user = UserManager.getInstance().createUser("Admin", host, null);
|
||||
if (user == null) {
|
||||
user = UserManager.getInstance().getUserByName("Admin");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,15 +91,30 @@ public class User {
|
|||
private UserState userState;
|
||||
private UserData userData;
|
||||
private UserStats userStats;
|
||||
private Date chatLockedUntil;
|
||||
private boolean active;
|
||||
private Date lockedUntil;
|
||||
private final AuthorizedUser authorizedUser;
|
||||
|
||||
public User(String userName, String host) {
|
||||
public User(String userName, String host, AuthorizedUser authorizedUser) {
|
||||
this.userId = UUID.randomUUID();
|
||||
this.userName = userName;
|
||||
this.host = host;
|
||||
this.userState = UserState.Created;
|
||||
|
||||
this.connectionTime = new Date();
|
||||
this.lastActivity = new Date();
|
||||
if (authorizedUser != null) {
|
||||
this.active = authorizedUser.active;
|
||||
this.chatLockedUntil = authorizedUser.chatLockedUntil;
|
||||
this.lockedUntil = authorizedUser.lockedUntil;
|
||||
this.authorizedUser = authorizedUser;
|
||||
updateAuthorizedUser();
|
||||
} else {
|
||||
this.active = true;
|
||||
this.chatLockedUntil = null;
|
||||
this.lockedUntil = null;
|
||||
this.authorizedUser = null;
|
||||
}
|
||||
|
||||
this.tables = new ConcurrentHashMap<>();
|
||||
this.gameSessions = new ConcurrentHashMap<>();
|
||||
|
|
@ -128,6 +143,18 @@ public class User {
|
|||
return sessionId;
|
||||
}
|
||||
|
||||
public Date getChatLockedUntil() {
|
||||
return chatLockedUntil;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public Date getLockedUntil() {
|
||||
return lockedUntil;
|
||||
}
|
||||
|
||||
public void setSessionId(String sessionId) {
|
||||
this.sessionId = sessionId;
|
||||
if (sessionId.isEmpty()) {
|
||||
|
|
@ -145,6 +172,21 @@ public class User {
|
|||
}
|
||||
}
|
||||
|
||||
public void setChatLockedUntil(Date chatLockedUntil) {
|
||||
this.chatLockedUntil = chatLockedUntil;
|
||||
updateAuthorizedUser();
|
||||
}
|
||||
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
updateAuthorizedUser();
|
||||
}
|
||||
|
||||
public void setLockedUntil(Date lockedUntil) {
|
||||
this.lockedUntil = lockedUntil;
|
||||
updateAuthorizedUser();
|
||||
}
|
||||
|
||||
public void lostConnection() {
|
||||
// Because watched games don't get restored after reconnection call stop watching
|
||||
for (Iterator<UUID> iterator = watchedGames.iterator(); iterator.hasNext();) {
|
||||
|
|
@ -731,4 +773,12 @@ public class User {
|
|||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
private void updateAuthorizedUser() {
|
||||
if (authorizedUser != null) {
|
||||
authorizedUser.lastConnection = this.connectionTime;
|
||||
authorizedUser.chatLockedUntil = this.chatLockedUntil;
|
||||
AuthorizedUserRepository.instance.update(authorizedUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,11 +76,11 @@ public class UserManager {
|
|||
}, 60, 60, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public User createUser(String userName, String host) {
|
||||
public User createUser(String userName, String host, AuthorizedUser authorizedUser) {
|
||||
if (getUserByName(userName) != null) {
|
||||
return null; //user already exists
|
||||
}
|
||||
User user = new User(userName, host);
|
||||
User user = new User(userName, host, authorizedUser);
|
||||
users.put(user.getId(), user);
|
||||
usersByName.put(userName, user);
|
||||
return user;
|
||||
|
|
|
|||
|
|
@ -166,11 +166,11 @@ public class GameController implements GameCallback {
|
|||
updateGame();
|
||||
break;
|
||||
case INFO:
|
||||
ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, ChatMessage.MessageType.GAME);
|
||||
ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, ChatMessage.MessageType.GAME, null);
|
||||
logger.trace(game.getId() + " " + event.getMessage());
|
||||
break;
|
||||
case STATUS:
|
||||
ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), ChatMessage.MessageType.GAME);
|
||||
ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.ORANGE, event.getWithTime(), ChatMessage.MessageType.GAME, null);
|
||||
logger.trace(game.getId() + " " + event.getMessage());
|
||||
break;
|
||||
case ERROR:
|
||||
|
|
@ -346,7 +346,7 @@ public class GameController implements GameCallback {
|
|||
}
|
||||
user.addGame(playerId, gameSession);
|
||||
logger.debug("Player " + player.getName() + " " + playerId + " has " + joinType + " gameId: " + game.getId());
|
||||
ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(playerId).getLogName() + " has " + joinType + " the game", MessageColor.ORANGE, true, MessageType.GAME);
|
||||
ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(playerId).getLogName() + " has " + joinType + " the game", MessageColor.ORANGE, true, MessageType.GAME, null);
|
||||
checkStart();
|
||||
}
|
||||
|
||||
|
|
@ -372,7 +372,7 @@ public class GameController implements GameCallback {
|
|||
GameManager.getInstance().joinGame(game.getId(), user.getId());
|
||||
logger.debug("Player " + player.getName() + " (disconnected) has joined gameId: " + game.getId());
|
||||
}
|
||||
ChatManager.getInstance().broadcast(chatId, player.getName(), user.getPingInfo() + " is pending to join the game", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS);
|
||||
ChatManager.getInstance().broadcast(chatId, player.getName(), user.getPingInfo() + " is pending to join the game", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS, null);
|
||||
if (user.getSecondsDisconnected() > 240) {
|
||||
// Cancel player join possibility lately after 4 minutes
|
||||
logger.debug("Player " + player.getName() + " - canceled game (after 240 seconds) gameId: " + game.getId());
|
||||
|
|
@ -443,7 +443,7 @@ public class GameController implements GameCallback {
|
|||
watchers.put(userId, gameWatcher);
|
||||
gameWatcher.init();
|
||||
user.addGameWatchInfo(game.getId());
|
||||
ChatManager.getInstance().broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS);
|
||||
ChatManager.getInstance().broadcast(chatId, user.getName(), " has started watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -451,7 +451,7 @@ public class GameController implements GameCallback {
|
|||
watchers.remove(userId);
|
||||
User user = UserManager.getInstance().getUser(userId);
|
||||
if (user != null) {
|
||||
ChatManager.getInstance().broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS);
|
||||
ChatManager.getInstance().broadcast(chatId, user.getName(), " has stopped watching", MessageColor.BLUE, true, ChatMessage.MessageType.STATUS, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -678,7 +678,7 @@ public class GameController implements GameCallback {
|
|||
String sb = player.getLogName()
|
||||
+ " has timed out (player had priority and was not active for "
|
||||
+ ConfigSettings.getInstance().getMaxSecondsIdle() + " seconds ) - Auto concede.";
|
||||
ChatManager.getInstance().broadcast(chatId, "", sb, MessageColor.BLACK, true, MessageType.STATUS);
|
||||
ChatManager.getInstance().broadcast(chatId, "", sb, MessageColor.BLACK, true, MessageType.STATUS, null);
|
||||
game.idleTimeout(playerId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,73 +89,73 @@ public class TournamentController {
|
|||
private void init() {
|
||||
tournament.addTableEventListener(
|
||||
new Listener<TableEvent>() {
|
||||
@Override
|
||||
public void event(TableEvent event) {
|
||||
switch (event.getEventType()) {
|
||||
case CHECK_STATE_PLAYERS:
|
||||
checkPlayersState();
|
||||
break;
|
||||
case INFO:
|
||||
ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, MessageType.STATUS);
|
||||
logger.debug(tournament.getId() + " " + event.getMessage());
|
||||
break;
|
||||
case START_DRAFT:
|
||||
startDraft(event.getDraft());
|
||||
break;
|
||||
case CONSTRUCT:
|
||||
if (!isAbort()) {
|
||||
construct();
|
||||
} else {
|
||||
endTournament();
|
||||
}
|
||||
break;
|
||||
case START_MATCH:
|
||||
if (!isAbort()) {
|
||||
initTournament(); // set state
|
||||
startMatch(event.getPair(), event.getMatchOptions());
|
||||
}
|
||||
break;
|
||||
case START_MULTIPLAYER_MATCH:
|
||||
if (!isAbort()) {
|
||||
initTournament(); // set state
|
||||
MatchOptions matchOptions = event.getMatchOptions();
|
||||
if (matchOptions != null && event.getMultiplayerRound() != null) {
|
||||
for (TournamentPlayer player : event.getMultiplayerRound().getAllPlayers()) {
|
||||
matchOptions.getPlayerTypes().add(player.getPlayerType());
|
||||
}
|
||||
}
|
||||
|
||||
startMultiplayerMatch(event.getMultiplayerRound(), event.getMatchOptions());
|
||||
}
|
||||
break;
|
||||
case END:
|
||||
endTournament();
|
||||
break;
|
||||
@Override
|
||||
public void event(TableEvent event) {
|
||||
switch (event.getEventType()) {
|
||||
case CHECK_STATE_PLAYERS:
|
||||
checkPlayersState();
|
||||
break;
|
||||
case INFO:
|
||||
ChatManager.getInstance().broadcast(chatId, "", event.getMessage(), MessageColor.BLACK, true, MessageType.STATUS, null);
|
||||
logger.debug(tournament.getId() + " " + event.getMessage());
|
||||
break;
|
||||
case START_DRAFT:
|
||||
startDraft(event.getDraft());
|
||||
break;
|
||||
case CONSTRUCT:
|
||||
if (!isAbort()) {
|
||||
construct();
|
||||
} else {
|
||||
endTournament();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case START_MATCH:
|
||||
if (!isAbort()) {
|
||||
initTournament(); // set state
|
||||
startMatch(event.getPair(), event.getMatchOptions());
|
||||
}
|
||||
break;
|
||||
case START_MULTIPLAYER_MATCH:
|
||||
if (!isAbort()) {
|
||||
initTournament(); // set state
|
||||
MatchOptions matchOptions = event.getMatchOptions();
|
||||
if (matchOptions != null && event.getMultiplayerRound() != null) {
|
||||
for (TournamentPlayer player : event.getMultiplayerRound().getAllPlayers()) {
|
||||
matchOptions.getPlayerTypes().add(player.getPlayerType());
|
||||
}
|
||||
}
|
||||
|
||||
startMultiplayerMatch(event.getMultiplayerRound(), event.getMatchOptions());
|
||||
}
|
||||
break;
|
||||
case END:
|
||||
endTournament();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
tournament.addPlayerQueryEventListener(
|
||||
new Listener<PlayerQueryEvent>() {
|
||||
@Override
|
||||
public void event(PlayerQueryEvent event) {
|
||||
try {
|
||||
switch (event.getQueryType()) {
|
||||
case CONSTRUCT:
|
||||
construct(event.getPlayerId(), event.getMax());
|
||||
break;
|
||||
}
|
||||
} catch (MageException ex) {
|
||||
logger.fatal("Player event listener error", ex);
|
||||
}
|
||||
@Override
|
||||
public void event(PlayerQueryEvent event) {
|
||||
try {
|
||||
switch (event.getQueryType()) {
|
||||
case CONSTRUCT:
|
||||
construct(event.getPlayerId(), event.getMax());
|
||||
break;
|
||||
}
|
||||
} catch (MageException ex) {
|
||||
logger.fatal("Player event listener error", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
for (TournamentPlayer player : tournament.getPlayers()) {
|
||||
if (!player.getPlayer().isHuman()) {
|
||||
player.setJoined();
|
||||
logger.debug("player " + player.getPlayer().getId() + " has joined tournament " + tournament.getId());
|
||||
ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS);
|
||||
ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS, null);
|
||||
}
|
||||
}
|
||||
checkStart();
|
||||
|
|
@ -185,7 +185,7 @@ public class TournamentController {
|
|||
TournamentPlayer player = tournament.getPlayer(playerId);
|
||||
player.setJoined();
|
||||
logger.debug("player " + player.getPlayer().getName() + " - client has joined tournament " + tournament.getId());
|
||||
ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS);
|
||||
ChatManager.getInstance().broadcast(chatId, "", player.getPlayer().getLogName() + " has joined the tournament", MessageColor.BLACK, true, MessageType.STATUS, null);
|
||||
checkStart();
|
||||
} else {
|
||||
logger.error("User not found userId: " + userId + " tournamentId: " + tournament.getId());
|
||||
|
|
@ -209,11 +209,11 @@ public class TournamentController {
|
|||
if (!started && allJoined()) {
|
||||
ThreadExecutor.getInstance().getCallExecutor().execute(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
startTournament();
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public void run() {
|
||||
startTournament();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -278,7 +278,7 @@ public class TournamentController {
|
|||
logger.fatal("TournamentController startMatch error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void startMultiplayerMatch(MultiplayerRound round, MatchOptions matchOptions) {
|
||||
try {
|
||||
TableManager tableManager = TableManager.getInstance();
|
||||
|
|
@ -286,7 +286,7 @@ public class TournamentController {
|
|||
table.setTournamentSubTable(true);
|
||||
table.setTournament(tournament);
|
||||
table.setState(TableState.WAITING);
|
||||
|
||||
|
||||
for (TournamentPlayer player : round.getAllPlayers()) {
|
||||
tableManager.addPlayer(getPlayerUserId(player.getPlayer().getId()), table.getId(), player.getPlayer(), player.getPlayerType(), player.getDeck());
|
||||
}
|
||||
|
|
@ -302,7 +302,7 @@ public class TournamentController {
|
|||
} catch (GameException ex) {
|
||||
logger.fatal("TournamentController startMatch error", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startDraft(Draft draft) {
|
||||
TableManager.getInstance().startDraft(tableId, draft);
|
||||
|
|
@ -447,7 +447,7 @@ public class TournamentController {
|
|||
user.removeTable(leavingPlayer.getPlayer().getId());
|
||||
user.removeTournament(leavingPlayer.getPlayer().getId());
|
||||
}
|
||||
ChatManager.getInstance().broadcast(chatId, "", leavingPlayer.getPlayer().getLogName() + " was replaced by draftbot", MessageColor.BLACK, true, MessageType.STATUS);
|
||||
ChatManager.getInstance().broadcast(chatId, "", leavingPlayer.getPlayer().getLogName() + " was replaced by draftbot", MessageColor.BLACK, true, MessageType.STATUS, null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
package mage.server.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.repository.CardInfo;
|
||||
import mage.cards.repository.CardRepository;
|
||||
|
|
@ -8,36 +19,30 @@ import mage.game.Game;
|
|||
import mage.players.Player;
|
||||
import mage.util.RandomUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author nantuko
|
||||
*/
|
||||
public class SystemUtil {
|
||||
|
||||
public static final DateFormat dateFormat = new SimpleDateFormat("yy-M-dd HH:mm:ss");
|
||||
|
||||
private static final String INIT_FILE_PATH = "config" + File.separator + "init.txt";
|
||||
private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(SystemUtil.class);
|
||||
private static final org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(SystemUtil.class);
|
||||
|
||||
/**
|
||||
* Replaces cards in player's hands by specified in config/init.txt.<br/>
|
||||
* <br/>
|
||||
* <b>Implementation note:</b><br/>
|
||||
* 1. Read init.txt line by line<br/>
|
||||
* 2. Parse line using the following format: line ::= <zone>:<nickname>:<card name>:<amount><br/>
|
||||
* 2. Parse line using the following format: line ::=
|
||||
* <zone>:<nickname>:<card name>:<amount><br/>
|
||||
* 3. If zone equals to 'hand', add card to player's library<br/>
|
||||
* 3a. Then swap added card with any card in player's hand<br/>
|
||||
* 3b. Parse next line (go to 2.), If EOF go to 4.<br/>
|
||||
* 4. Log message to all players that cards were added (to prevent unfair play).<br/>
|
||||
* 3a. Then swap added card with any card in player's hand<br/>
|
||||
* 3b. Parse next line (go to 2.), If EOF go to 4.<br/>
|
||||
* 4. Log message to all players that cards were added (to prevent unfair
|
||||
* play).<br/>
|
||||
* 5. Exit<br/>
|
||||
*
|
||||
* @param game
|
||||
*/
|
||||
public static void addCardsForTesting(Game game) {
|
||||
|
|
@ -109,8 +114,7 @@ public class SystemUtil {
|
|||
swapWithAnyCard(game, player, card, gameZone);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
scanner.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
|
@ -137,7 +141,7 @@ public class SystemUtil {
|
|||
} else {
|
||||
card.moveToZone(zone, null, game, false);
|
||||
}
|
||||
logger.info("Added card to player's " + zone.toString() + ": " + card.getName() +", player = " + player.getName());
|
||||
logger.info("Added card to player's " + zone.toString() + ": " + card.getName() + ", player = " + player.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -148,7 +152,7 @@ public class SystemUtil {
|
|||
* @return
|
||||
*/
|
||||
private static Player findPlayer(Game game, String name) {
|
||||
for (Player player: game.getPlayers().values()) {
|
||||
for (Player player : game.getPlayers().values()) {
|
||||
if (player.getName().equals(name)) {
|
||||
return player;
|
||||
}
|
||||
|
|
@ -162,7 +166,7 @@ public class SystemUtil {
|
|||
//return matcher.replaceAll("");
|
||||
return input.replaceAll("[^a-zA-Z0-9]", "");
|
||||
}
|
||||
|
||||
|
||||
public static void main(String... args) {
|
||||
System.out.println(sanitize("123"));
|
||||
System.out.println(sanitize("AaAaD_123"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue