summaryrefslogblamecommitdiffstats
path: root/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/thrift/SessionManager.java
blob: 1f36adfb90308fd51239d82914649ee550957553 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                    
 

                             




                                              

                                                    
                                                        
                                          
                                                             
                                                            
                                              
                                              

                                        





















                                                                                       



                                                   


                                                                                      



                                                                                         
                                                            
                                 
                                            








                                                                                                            

           















                                                                                       


                                                                                   
                                    



                                                  






                                                            
                 

                              










                                                  





                                                   



                                                                                     

                                                                        


                                                                                                             


                                                                                                  






                                                                         
                 



                                                       
 
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;
	}

}