All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.integratedmodelling.kmodeler.controller.SessionController Maven / Gradle / Ivy

The newest version!
package org.integratedmodelling.kmodeler.controller;

import javax.servlet.http.HttpServletRequest;

import org.integratedmodelling.api.auth.IUser;
import org.integratedmodelling.api.configuration.IResourceConfiguration;
import org.integratedmodelling.api.configuration.IResourceConfiguration.StaticResource;
import org.integratedmodelling.api.engine.ILock;
import org.integratedmodelling.api.engine.IModelingEngine;
import org.integratedmodelling.api.knowledge.IObservation;
import org.integratedmodelling.api.network.API;
import org.integratedmodelling.api.runtime.IContext;
import org.integratedmodelling.api.runtime.ISession;
import org.integratedmodelling.common.auth.KlabCertificate;
import org.integratedmodelling.common.auth.User;
import org.integratedmodelling.common.beans.Session;
import org.integratedmodelling.common.beans.requests.RunScriptRequest;
import org.integratedmodelling.common.beans.requests.SessionRequest;
import org.integratedmodelling.common.beans.responses.AuthorizationResponse;
import org.integratedmodelling.common.beans.responses.LockResponse;
import org.integratedmodelling.common.beans.responses.RunScriptResponse;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.network.EngineNetwork;
import org.integratedmodelling.engine.ModelingEngine;
import org.integratedmodelling.exceptions.KlabAuthenticationException;
import org.integratedmodelling.exceptions.KlabAuthorizationException;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.kmodeler.components.SessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @author ferdinando.villa
 *
 */
@RestController
public class SessionController {

    @Autowired
    SessionManager sessionManager;

    /**
     * We get here with a user who has read its certificate and authenticated successfully
     * with the primary server(s) mentioned in it. The user sends the authentication token
     * received by the server and the endpoint it used to retrieve it, along with
     * session-related information.
     * 
     * In order to know which groups the user belongs to, and to add another layer of
     * security, we retrieve the user profile from the same server, using the same token,
     * and rebuild the user info at our end. Then based on the user's permissions, we open
     * a session and return its id along with the view of the network that the user can
     * access.
     * 
     * The call used to validate the token server side should produce both the user
     * profile and the network view.
     * 
     * @param request
     * @param servletRequest
     * @return a descriptor for the session requested
     * @throws KlabException
     */
    @RequestMapping(value = API.OPEN_SESSION, method = RequestMethod.POST)
    public @ResponseBody Session openSession(@RequestBody SessionRequest request, HttpServletRequest servletRequest)
            throws KlabException {

        IResourceConfiguration rconf = KLAB.ENGINE.getResourceConfiguration();
        RestTemplate restTemplate = new RestTemplate();

        /*
         * if we're requesting to join a known previous session and we have just one that
         * can be reopened, just get that w/o reauthenticating.
         */
        if (request.getSessionId() != null) {
            org.integratedmodelling.common.model.runtime.Session s = sessionManager
                    .getSession(request.getSessionId());
            if (s != null) {
                return s.serialize(Session.class);
            }
        }
        if (request.isReopenExisting()) {
            org.integratedmodelling.common.model.runtime.Session s = sessionManager
                    .getReopenableSessionFor(request.getSessionId());
            if (s != null) {
                return s.serialize(Session.class);
            }
        }

        /*
         * get user profile from primary server; abort if authentication fails
         */
        IUser user = null;
        if (KLAB.CONFIG.isOffline()) {

            KlabCertificate certificate = new KlabCertificate(request.getCertificate());
            if (!certificate.isValid()) {
                throw new KlabAuthenticationException("session manager: certificate is invalid: "
                        + certificate.getCause());
            }
            user = new User(certificate);
            KLAB.info("session manager: offline user " + user.getUsername()
                + " authenticated successfully");
            
            ((EngineNetwork)KLAB.ENGINE.getNetwork()).setUser(user);
            
        } else {
            try {

                KLAB.info("session manager: authenticating through primary server "
                        + request.getPrimaryServerUrl());

                AuthorizationResponse ret = restTemplate
                        .postForObject(request.getPrimaryServerUrl()
                                + API.AUTHENTICATION_CERT_FILE, request
                                        .getCertificate(), AuthorizationResponse.class);
                user = new User(ret.getProfile(), ret.getAuthToken());

                KLAB.info("session manager: user " + user.getUsername()
                        + " authenticated successfully");

                /*
                 * user only retains privileges up to those of the certified engine owner.
                 */
                ((User) user)
                        .restrictPrivileges(((IModelingEngine) KLAB.ENGINE).getUser());

            } catch (Throwable e) {
                throw new KlabAuthenticationException("session manager: could not validate user: "
                        + e.getMessage());
            }
        }

        /*
         * check if user can connect
         */
        if (!rconf.isAuthorized(user, servletRequest.getRemoteAddr())) {
            throw new KlabAuthenticationException("session manager: user "
                    + user.getUsername()
                    + " is valid but has no permission to open a session");
        }

        /*
         * if requested, check if user can lock
         */
        if (request.isRequestingExclusive()
                && !rconf.isAuthorized(StaticResource.ENGINE_LOCK, user, servletRequest
                        .getRemoteAddr())) {
            throw new KlabAuthenticationException("session manager: user "
                    + user.getUsername()
                    + " is valid but has no permission to lock this engine");
        }

        /*
         * all clear, get me a session
         */
        return sessionManager.getNewSessionForRequest(request, user)
                .serialize(Session.class);
    }

    /**
     * Lock the engine until unlock is explicitly called.
     * 
     * @param headers requires session authorization
     * @return true if lock is successful
     * @throws KlabAuthorizationException
     */
    @RequestMapping(value = API.LOCK_ENGINE, method = RequestMethod.GET)
    public @ResponseBody LockResponse lockEngine(@RequestHeader HttpHeaders headers)
            throws KlabAuthorizationException {

        boolean wasLocked = false;
        ISession session = sessionManager
                .getSession(headers.get(API.AUTHENTICATION_HEADER));
        if (session == null || !session.isExclusive()) {
            throw new KlabAuthorizationException("only a session with exclusive rights can lock an engine");
        }
        ILock lock = ((ModelingEngine) KLAB.ENGINE).getLock();
        if ((wasLocked = lock.isLocked())) {
            if (!lock.getUser().equals(session.getUser())) {
                throw new KlabAuthorizationException("engine is locked by "
                        + lock.getUser().getUsername()
                        + ": cannot create exclusive session");
            }
        }

        boolean locked = lock.lock(session.getUser(), false);

        LockResponse ret = new LockResponse();

        ret.setLocked(locked
                || lock.isLocked() && lock.getUser().getUsername()
                        .equals(session.getUser().getUsername()));
        ret.setWasLocked(wasLocked);
        ret.setLockingUser(lock.getUser().getUsername());

        return ret;

    }

    /**
     * Unlock the engine.
     * 
     * @param headers requires session authorization
     * @return true if unlock is successful
     * @throws KlabAuthorizationException
     */
    @RequestMapping(value = API.UNLOCK_ENGINE, method = RequestMethod.GET)
    public @ResponseBody LockResponse unlockEngine(@RequestHeader HttpHeaders headers)
            throws KlabAuthorizationException {

        boolean wasLocked = false;
        ILock lock = ((ModelingEngine) KLAB.ENGINE).getLock();
        ISession session = sessionManager
                .getSession(headers.get(API.AUTHENTICATION_HEADER));
        if (session == null || !session.isExclusive()) {
            throw new KlabAuthorizationException("only a session with exclusive rights can unlock an engine");
        }
        boolean locked = false;
        if ((wasLocked = lock.isLocked())) {
            if (lock.unlock(session.getUser())) {
                locked = false;
            }
        }

        LockResponse ret = new LockResponse();

        ret.setLocked(locked);
        ret.setWasLocked(wasLocked);

        return ret;
    }

    @RequestMapping(value = API.RUN_SCRIPT, method = RequestMethod.POST)
    public @ResponseBody RunScriptResponse runScript(@RequestBody RunScriptRequest request, @RequestHeader HttpHeaders headers, HttpServletRequest servletRequest)
            throws KlabException {

        ISession session = sessionManager
                .getSession(headers.get(API.AUTHENTICATION_HEADER));
        if (session == null) {
            throw new KlabAuthorizationException("observe: session authentication failed");
        }

        RunScriptResponse ret = new RunScriptResponse();

        IContext context = null;
        IObservation observation = null;

        if (request.getContextId() != null) {
            context = sessionManager.getContext(request.getContextId());
            if (context != null && request.getObservationPath() != null) {
                observation = context.get(request.getObservationPath());
            }
        }

        return ret;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy