blob: 1f36adfb90308fd51239d82914649ee550957553 (
plain) (
tree)
|
|
package org.openslx.bwlp.sat.thrift;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.openslx.bwlp.sat.database.mappers.DbUser;
import org.openslx.bwlp.sat.permissions.User;
import org.openslx.bwlp.thrift.iface.AuthorizationError;
import org.openslx.bwlp.thrift.iface.Role;
import org.openslx.bwlp.thrift.iface.TAuthorizationException;
import org.openslx.bwlp.thrift.iface.TInvalidTokenException;
import org.openslx.bwlp.thrift.iface.UserInfo;
import org.openslx.thrifthelper.ThriftManager;
import org.openslx.util.QuickTimer;
import org.openslx.util.QuickTimer.Task;
/**
* Manages user sessions. Mainly used to map tokens to users.
*
*/
public class SessionManager {
private static final Logger LOGGER = Logger.getLogger(SessionManager.class);
private static class Entry {
private static final long SESSION_TIMEOUT = TimeUnit.DAYS.toMillis(1);
private final UserInfo user;
private long validUntil;
private Entry(UserInfo user) {
this.user = user;
this.validUntil = System.currentTimeMillis() + SESSION_TIMEOUT;
}
public void touch(long now) {
this.validUntil = now + SESSION_TIMEOUT;
}
public boolean isTooOld(long now) {
return validUntil < now;
}
}
// saves the current tokens and the mapped userdata, returning from the server
private static final Map<String, Entry> tokenManager = new ConcurrentHashMap<>();
static {
// Clean cached session periodically
QuickTimer.scheduleAtFixedDelay(new Task() {
@Override
public void fire() {
final long now = System.currentTimeMillis();
for (Iterator<Entry> it = tokenManager.values().iterator(); it.hasNext();) {
Entry e = it.next();
if (e == null || e.isTooOld(now))
it.remove();
}
}
}, 60000, 1200600);
}
/**
* Get the user corresponding to the given token.
*
* @param token user's token
* @return UserInfo for the matching user
* @throws TAuthorizationException if the token is not known or the session
* expired
*/
public static UserInfo getOrFail(String token) throws TAuthorizationException {
UserInfo ui = get(token);
if (ui != null)
return ui;
throw new TAuthorizationException(AuthorizationError.NOT_AUTHENTICATED,
"Your session token is not known to the server");
}
/**
* Get the user corresponding to the given token. Returns null if the token
* is not known, or the session already timed out.
*
* @param token user's token
* @return UserInfo for the matching user
*/
public static UserInfo get(String token) {
Entry e = tokenManager.get(token);
if (e == null)
return getRemote(token);
// User session already cached
final long now = System.currentTimeMillis();
if (e.isTooOld(now)) {
tokenManager.remove(token);
return getRemote(token);
}
e.touch(now);
return e.user;
}
/**
* Remove session matching the given token
*
* @param token
*/
public static void remove(String token) {
tokenManager.remove(token);
}
/**
* Get {@link UserInfo} from master server.
*
* @param token token of user to get
* @return
*/
private static UserInfo getRemote(String token) {
UserInfo ui = null;
try {
ui = ThriftManager.getMasterClient().getUserFromToken(token);
} catch (TInvalidTokenException ite) {
return null; // Token not known to master server
} catch (Exception e) {
LOGGER.warn("Could not reach master server to query for user token of a client!", e);
}
// Valid reply, check if user is allowed to communicate with this satellite server
if (!User.canLogin(ui))
return null;
// Is valid, insert/update db record, but ignore students
if (ui.role != Role.STUDENT) {
try {
DbUser.writeUserOnLogin(ui);
} catch (SQLException e) {
return null;
}
}
tokenManager.put(token, new Entry(ui));
return ui;
}
}
|