package org.openslx.imagemaster.server; import java.io.File; import java.util.HashMap; import org.apache.ftpserver.ftplet.FtpException; import org.apache.log4j.Logger; import org.apache.thrift.TException; import org.openslx.imagemaster.Globals; import org.openslx.imagemaster.db.DbSatellite; import org.openslx.imagemaster.db.ImageProcessor; import org.openslx.imagemaster.serversession.ServerAuthenticator; import org.openslx.imagemaster.serversession.ServerSession; import org.openslx.imagemaster.serversession.ServerSessionManager; import org.openslx.imagemaster.serversession.ServerUser; import org.openslx.imagemaster.session.Authenticator; import org.openslx.imagemaster.session.Session; import org.openslx.imagemaster.session.SessionManager; import org.openslx.imagemaster.session.User; import org.openslx.imagemaster.thrift.iface.AuthenticationError; import org.openslx.imagemaster.thrift.iface.AuthenticationException; import org.openslx.imagemaster.thrift.iface.AuthorizationError; import org.openslx.imagemaster.thrift.iface.AuthorizationException; import org.openslx.imagemaster.thrift.iface.FtpCredentials; import org.openslx.imagemaster.thrift.iface.ImageData; import org.openslx.imagemaster.thrift.iface.InvalidTokenException; import org.openslx.imagemaster.thrift.iface.ServerAuthenticationError; import org.openslx.imagemaster.thrift.iface.ServerAuthenticationException; import org.openslx.imagemaster.thrift.iface.ServerSessionData; import org.openslx.imagemaster.thrift.iface.SessionData; import org.openslx.imagemaster.thrift.iface.UserInfo; import org.openslx.imagemaster.util.RandomString; /** * API Server This is where all the requests from the outside arrive. We don't * handle them directly in the Thrift handlers, as we might be adding other APIs * later, like JSON/SOAP/REST/HTTP/XML or some other stuff. They'd all just * interface with this static class here. Note that we use the exceptions from * the thrift interface that you can simply catch in any other API handler and * eg. transform into error codes, if the API doesn't support exceptions. * * This will be accessed from multiple threads, so use synchronization when * needed (or in doubt) */ public class ApiServer { private static Logger log = Logger.getLogger(ApiServer.class); /** * Request for authentication * * @param login The user's login in the form "user@organization.com" * @param password user's password * @return SessionData struct with session id/token iff login successful * @throws AuthenticationException if login not successful */ public static SessionData authenticate(String login, String password) throws AuthenticationException { if (login == null || password == null) { throw new AuthenticationException( AuthenticationError.INVALID_CREDENTIALS, "Empty username or password!"); } final User user = Authenticator.authenticate(login, password); final Session session = new Session(user); return SessionManager.addSession(session); } /** * Request information about user for given token * * @param token a user's token * @return UserInfo struct for given token's user * @throws InvalidTokenException if no user matches the given token */ public static UserInfo getUserFromToken(String token) throws InvalidTokenException { final Session session = SessionManager.getSession(token); if (session == null) throw new InvalidTokenException(); return new UserInfo(session.getUserId(), session.getFirstName(), session.getLastName(), session.getEMail()); } /** * Request ftp credentials to upload a new image to the masterserver. * @param imageDescription MetaData of the new image * @param serverSessionData the session data of the authenticated uni/hs server * @return the genereated ftp credentials * @throws AuthorizationException if the uni/hs server has no valid session * @throws TException */ public static FtpCredentials submitImage(String serverSessionId, ImageData imageDescription) throws AuthorizationException, TException { if (ServerSessionManager.getSession(serverSessionId) == null) { throw new AuthorizationException(AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionData"); } // create new user FtpCredentials ftpCredentials = Globals.ftpServer.addUser(serverSessionId); if (!ImageProcessor.addImageDataToProcess(imageDescription, ftpCredentials.username)) { Globals.ftpServer.removeUser(serverSessionId); throw new TException("ImageData is not valid."); } return ftpCredentials; } /** * Start the server authentication of a uni/hs satellite server. * @param organization the organization that the server belongs to * @return a random string that needs to be encrypted with the private * key of the requesting satellite server * @throws ServerAuthenticationException when organization is invalid/unknown */ public static String startServerAuthentication(String organization) throws ServerAuthenticationException { if (organization == null || organization == "") { throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization"); } if (DbSatellite.fromOrganization(organization) == null) { throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization"); } return ServerAuthenticator.startServerAuthentication(organization); } /** * Authenticate the uni/hs satellite server with the encrypted string. * @param organization the organization that the server belongs to * @param challengeResponse the encrypted string * @return session data iff the authentication was successful * @throws AuthenticationException * @throws TException */ public static ServerSessionData serverAuthenticate(String organization, String challengeResponse) throws AuthenticationException, TException { if (organization == null || challengeResponse == null) { throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Empty organization or challengeResponse"); } DbSatellite satellite = DbSatellite.fromOrganization(organization); if (satellite == null) { throw new ServerAuthenticationException(ServerAuthenticationError.INVALID_ORGANIZATION, "Unknown organization"); } final ServerUser serverUser = ServerAuthenticator.serverAuthenticate( organization, satellite.getAddress(), challengeResponse); final ServerSession session = new ServerSession(serverUser); return ServerSessionManager.addSession(session); } /** * Tell the masterserver that the image upload finished. * @param serverSessionId The session id of the hs/uni server * @param imageDescription the description of the uploaded image * @return if nothing went wrong * @throws AuthorizationException if no valid session exists */ public static boolean finishedUpload(String serverSessionId, ImageData imageDescription) throws AuthorizationException { // check if valid session exists if (ServerSessionManager.getSession(serverSessionId) == null) { throw new AuthorizationException(AuthorizationError.NOT_AUTHENTICATED, "No valid serverSessionData"); } // process the image String username = Globals.ftpServer.getCredentialsFromSessionId(serverSessionId).username; File userDirectory = new File(Globals.properties.getProperty(Globals.ftpBaseDir) + "/" + username); File[] list = userDirectory.listFiles(); if (list.length != 1) return false; log.info(username + " is done with upload"); // remove user that is not needed anymore Globals.ftpServer.removeUser(username); log.info("Removed user: " + username); ImageProcessor.processImageAfterUpload(username, list[0].getName()); Globals.ftpServer.removeUser(serverSessionId); return true; } }