package net.sf.colossus.webcommon; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import net.sf.colossus.util.Glob; /** * One user at the WebServer side. * Also used on client side, because interface requires so, but * basically only to store the username, everything else is unused. * * @author Clemens Katzer */ public class User { static final Logger LOGGER = Logger.getLogger(User.class.getName()); private final static String TYPE_USER = "user"; private final static String TYPE_ADMIN = "admin"; private final static String USERLINE_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private final static SimpleDateFormat userlineDateFormatter = new SimpleDateFormat( USERLINE_DATE_FORMAT); // We use the same separator as for Web Protocol also for UserLines in user file: private final static String SEP = IWebServer.WebProtocolSeparator; // At the moment conf-code is 3 numbers between 00 and 99: private final static int MAX_RANDOM = 99; public final static String PROVIDE_CONFCODE = "Provide the confirmation code"; public final static String WRONG_CONFCODE = "Wrong confirmation code!"; public final static String TEMPLATE_CONFCODE = "10 20 30"; public final static String TEMPLATE_CONFCODE_REPLACEMENT = "11 21 31"; private IWebClient webserverClient; private long id; private final String name; private String password; private String email; private boolean isAdmin; private String created; private String lastLogin; private String lastLogout; private long onlineSecs; private long sessionStarted = -1L; // Only needed during registration: private String lastSentConfirmationCode; private final List<String> ignoredUsers = new ArrayList<String>(); public User(String name) { this.name = name; } public User(long id, String name, String password, String email, boolean isAdmin, String created, String lastLogin, String lastLogout, long onlineSecs) { this.id = id; this.name = name; this.password = password; this.email = email; this.isAdmin = isAdmin; if (created == null) { String now = makeUserlineDate(new Date().getTime()); this.created = now; this.lastLogin = now; this.lastLogout = now; this.lastSentConfirmationCode = makeConfirmationCode(); this.onlineSecs = 0; } else { this.created = created; this.lastLogin = lastLogin; this.lastLogout = lastLogout; this.lastSentConfirmationCode = ""; this.onlineSecs = onlineSecs; } } public long getId() { return this.id; } public String getName() { return this.name; } public boolean isCorrectPassword(String providedPassword) { return providedPassword.equals(this.password); } public String getEmail() { return email; } public String getCreated() { return this.created; } public long getOnlineTime() { return this.onlineSecs; } // Make sure it is a 2 digit number, to avoid problems in // comparison between "56 5 12" and "56 05 12". private static long atLeast10(long original) { return (original < 10L ? original + 10L : original); } public static String makeConfirmationCode() { long n1 = atLeast10(Math.round((MAX_RANDOM * Math.random()))); long n2 = atLeast10((new Date().getTime()) % MAX_RANDOM); long n3 = atLeast10(Math.round((MAX_RANDOM * Math.random()))); String confCode = n1 + " " + n2 + " " + n3; // Do not let happen it to be exactly the template code // - the client GUI verifies that user has typed something different if (confCode.equals(TEMPLATE_CONFCODE)) { confCode = TEMPLATE_CONFCODE_REPLACEMENT; } return confCode; } // Only used during while registration is pending. String getLastConfirmationCode() { return lastSentConfirmationCode; } public boolean isAdmin() { return isAdmin; } public void setIsAdmin(boolean val) { isAdmin = val; } public void setProperties(String pw, String email, Boolean isAdminObj) { if (pw != null) { password = pw; } if (email != null) { this.email = email; } if (isAdminObj != null) { isAdmin = isAdminObj.booleanValue(); } } public IWebClient getWebserverClient() { return this.webserverClient; } public void setWebClient(IWebClient wsc) { this.webserverClient = wsc; } private String makeUserlineDate(long when) { Date whenDate = new Date(when); String whenString = userlineDateFormatter.format(whenDate); return whenString; } public void updateLastLogin() { sessionStarted = new Date().getTime(); lastLogin = makeUserlineDate(sessionStarted); } public void updateLastLogout() { if (sessionStarted == -1) { LOGGER.info("sessionStarted already -1, skip updateLogout"); return; } long sessionEnded = new Date().getTime(); long duration = (sessionEnded - sessionStarted) / 1000; if (duration >= 0 && sessionStarted > 0) { onlineSecs += duration; LOGGER.info("User " + name + " was " + duration + " seconds online, total now " + onlineSecs); } else { LOGGER.warning("SessionDuration or sessionStarted for user " + name + " negative? Started=" + sessionStarted + ", Ended=" + sessionEnded + ", duration=" + duration + ", previously onlineSecs=" + onlineSecs); } lastLogout = makeUserlineDate(sessionEnded); sessionStarted = -1; } public static User makeUserFromUserLine(String line) { List<String> tokens = new LinkedList<String>(); tokens.addAll(Arrays.asList(line.split(SEP))); if (tokens.size() != 9) { User.LOGGER.log(Level.WARNING, "invalid line '" + line + "' in user file!"); return null; } long id = Long.parseLong(tokens.remove(0)); String name = tokens.remove(0).trim(); String password = tokens.remove(0).trim(); String email = tokens.remove(0).trim(); String type = tokens.remove(0).trim(); String created = tokens.remove(0).trim(); String lastLogin = tokens.remove(0).trim(); String lastLogout = tokens.remove(0).trim(); long onlineSecs = Long.parseLong(tokens.remove(0)); boolean isAdmin = false; if (type.equals(User.TYPE_ADMIN)) { isAdmin = true; } else if (type.equals(User.TYPE_USER)) { isAdmin = false; } else { User.LOGGER.log(Level.WARNING, "invalid type '" + type + "' in user file line '" + line + "'"); } User u = new User(id, name, password, email, isAdmin, created, lastLogin, lastLogout, onlineSecs); return u; } public String makeLine() { String type = (isAdmin ? TYPE_ADMIN : TYPE_USER); String line = this.id + SEP + this.name + SEP + password + SEP + email + SEP + type + SEP + created + SEP + lastLogin + SEP + lastLogout + SEP + onlineSecs; return line; } public List<String> getListOfIgnoredUsers() { List<String> list = new ArrayList<String>(ignoredUsers); return list; } public boolean isUserInIgnoredList(String username) { return ignoredUsers.contains(username); } public void addToIgnoredUsers(String username) { if (!isUserInIgnoredList(username)) { ignoredUsers.add(username); } LOGGER.finest("addToIgnore: " + Glob.glob(":", getListOfIgnoredUsers())); } public void removeFromIgnoredUsers(String username) { ignoredUsers.remove(username); LOGGER.finest("removeFromToIgnore: " + Glob.glob(":", getListOfIgnoredUsers())); } }