/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jsecurity.web.session;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jsecurity.authz.AuthorizationException;
import org.jsecurity.authz.HostUnauthorizedException;
import org.jsecurity.session.InvalidSessionException;
import org.jsecurity.session.Session;
import org.jsecurity.session.mgt.DefaultSessionManager;
import org.jsecurity.web.WebUtils;
import org.jsecurity.web.attr.CookieAttribute;
import org.jsecurity.web.attr.RequestParamAttribute;
import org.jsecurity.web.attr.WebAttribute;
import org.jsecurity.web.servlet.JSecurityHttpServletRequest;
import org.jsecurity.web.servlet.JSecurityHttpSession;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;
import java.net.InetAddress;

/**
 * Web-application capable <tt>SessionManager</tt> implementation.
 *
 * @author Les Hazlewood
 * @since 0.9
 */
public class DefaultWebSessionManager extends DefaultSessionManager implements WebSessionManager {

    private static final Log log = LogFactory.getLog(DefaultWebSessionManager.class);

    /**
     * Property specifying if, after a session object is acquired from the request, if that session should be
     * validated to ensure the starting origin of the session is the same as the incoming request.
     */
    private boolean validateRequestOrigin = false; //default

    protected CookieAttribute<Serializable> sessionIdCookieAttribute = null;
    protected RequestParamAttribute<Serializable> sessionIdRequestParamAttribute = null;

    public DefaultWebSessionManager() {
        ensureCookieSessionIdStore();
        ensureRequestParamSessionIdStore();
    }

    public CookieAttribute<Serializable> getSessionIdCookieAttribute() {
        return sessionIdCookieAttribute;
    }

    public void setSessionIdCookieAttribute(CookieAttribute<Serializable> sessionIdCookieAttribute) {
        this.sessionIdCookieAttribute = sessionIdCookieAttribute;
    }

    public RequestParamAttribute<Serializable> getSessionIdRequestParamAttribute() {
        return sessionIdRequestParamAttribute;
    }

    public void setSessionIdRequestParamAttribute(RequestParamAttribute<Serializable> sessionIdRequestParamAttribute) {
        this.sessionIdRequestParamAttribute = sessionIdRequestParamAttribute;
    }

    /**
     * If set to <tt>true</tt>, this implementation will ensure that any
     * <tt>HttpRequest</tt> attempting
     * to join a session (i.e. via {@link #getSession getSession} must have the same
     * IP Address of the <tt>HttpRequest</tt> that started the session.
     *
     * <p> If set to <tt>false</tt>, any <tt>HttpRequest</tt> with a reference to a valid
     * session id may acquire that <tt>Session</tt>.
     *
     * <p>Although convenient, this should only be enabled in environments where the
     * system can <em>guarantee</em> that each IP address represents one and only one
     * machine accessing the system.
     *
     * <p>Public websites are not good candidates for enabling this
     * feature since many browser clients often sit behind NAT routers (in
     * which case many machines are viewed to come from the same IP, thereby making this
     * validation check useless).  Also, some internet service providers (e.g. AOL) may change a
     * client's IP in mid-session, making subsequent requests appear to come from a different
     * location.  Again, this feature should only be enabled where IP Addresses can be guaranteed a
     * 1-to-1 relationship with a user's session.
     *
     * <p>For the reasons specified above, this property is <tt>false</tt> by default.
     *
     * @return true if this factory will verify each HttpRequest joining a session
     */
    public boolean isValidateRequestOrigin() {
        return validateRequestOrigin;
    }

    /**
     * Sets whether or not a request's origin will be validated when accessing a session.  See
     * the {@link #isValidateRequestOrigin} JavaDoc for an in-depth explanation of this property.
     *
     * @param validateRequestOrigin whether or not to validate the request's origin when accessing
     *                              a session.
     * @see #isValidateRequestOrigin
     */
    public void setValidateRequestOrigin(boolean validateRequestOrigin) {
        this.validateRequestOrigin = validateRequestOrigin;
    }

    public void setSessionIdCookieName(String name) {
        getSessionIdCookieAttribute().setName(name);
    }

    public void setSessionIdCookiePath(String path) {
        getSessionIdCookieAttribute().setPath(path);
    }

    public void setSessionIdCookieMaxAge(int maxAge) {
        getSessionIdCookieAttribute().setMaxAge(maxAge);
    }

    public void setSessionIdCookieSecure(boolean secure) {
        getSessionIdCookieAttribute().setSecure(secure);
    }

    protected void ensureCookieSessionIdStore() {
        CookieAttribute<Serializable> cookieStore = getSessionIdCookieAttribute();
        if (cookieStore == null) {
            cookieStore = new CookieAttribute<Serializable>(JSecurityHttpSession.DEFAULT_SESSION_ID_NAME);
            cookieStore.setCheckRequestParams(false);
            setSessionIdCookieAttribute(cookieStore);
        }
    }

    protected void ensureRequestParamSessionIdStore() {
        RequestParamAttribute<Serializable> reqParamStore = getSessionIdRequestParamAttribute();
        if (reqParamStore == null) {
            reqParamStore = new RequestParamAttribute<Serializable>(JSecurityHttpSession.DEFAULT_SESSION_ID_NAME);
            setSessionIdRequestParamAttribute(reqParamStore);
        }
    }

    protected void validateSessionOrigin(ServletRequest request, Session session)
            throws HostUnauthorizedException {
        InetAddress requestIp = WebUtils.getInetAddress(request);
        InetAddress originIp = session.getHostAddress();
        Serializable sessionId = session.getId();

        if (originIp == null) {
            if (requestIp != null) {
                String msg = "No IP Address was specified when creating session with id [" +
                        sessionId + "].  Attempting to access session from " +
                        "IP [" + requestIp + "].  Origin IP and request IP must match.";
                throw new HostUnauthorizedException(msg);
            }
        } else {
            if (requestIp != null) {
                if (!requestIp.equals(originIp)) {
                    String msg = "Session with id [" + sessionId + "] originated from [" +
                            originIp + "], but the current HttpServletRequest originated " +
                            "from [" + requestIp + "].  Disallowing session access: " +
                            "session origin and request origin must match to allow access.";
                    throw new HostUnauthorizedException(msg);
                }

            } else {
                String msg = "No IP Address associated with the current HttpServletRequest.  " +
                        "Session with id [" + sessionId + "] originated from " +
                        "[" + originIp + "].  Request IP must match the session's origin " +
                        "IP in order to gain access to that session.";
                throw new HostUnauthorizedException(msg);
            }
        }
    }

    protected void storeSessionId(Serializable currentId, ServletRequest request, ServletResponse response) {
        if (currentId == null) {
            String msg = "sessionId cannot be null when persisting for subsequent requests.";
            throw new IllegalArgumentException(msg);
        }
        //ensure that the id has been set in the idStore, or if it already has, that it is not different than the
        //'real' session value:
        Serializable existingId = retrieveSessionId(request, response);
        if (existingId == null || !currentId.equals(existingId)) {
            getSessionIdCookieAttribute().storeValue(currentId, request, response);
        }
    }

    protected Serializable retrieveSessionId(ServletRequest request, ServletResponse response) {
        WebAttribute<Serializable> cookieSessionIdAttribute = getSessionIdCookieAttribute();
        Serializable id = cookieSessionIdAttribute.retrieveValue(request, response);
        if (id != null) {
            request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
                    JSecurityHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
        } else {
            id = getSessionIdRequestParamAttribute().retrieveValue(request, response);
            if (id != null) {
                request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
                        JSecurityHttpServletRequest.URL_SESSION_ID_SOURCE);
            }
        }
        return id;
    }

    public Serializable start(InetAddress hostAddress) throws HostUnauthorizedException, IllegalArgumentException {
        ServletRequest request = WebUtils.getRequiredServletRequest();
        ServletResponse response = WebUtils.getRequiredServletResponse();
        return start(request, response, hostAddress);
    }

    protected Serializable start(ServletRequest request, ServletResponse response, InetAddress inetAddress) {
        Serializable sessionId = super.start(inetAddress);
        storeSessionId(sessionId, request, response);
        request.removeAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
        request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
        return sessionId;
    }

    public Session retrieveSession(Serializable sessionId) throws InvalidSessionException, AuthorizationException {
        if (sessionId != null) {
            return super.retrieveSession(sessionId);
        } else {
            ServletRequest request = WebUtils.getRequiredServletRequest();
            ServletResponse response = WebUtils.getRequiredServletResponse();
            return getSession(request, response);
        }
    }

    /**
     * Returns the Session associated with the specified request if it is valid or <tt>null</tt> if a Session doesn't
     * exist or it was invalid.
     *
     * @param request  incoming servlet request
     * @param response outgoing servlet response
     * @return the Session associated with the incoming request or <tt>null</tt> if one does not exist.
     * @throws org.jsecurity.session.InvalidSessionException
     *          if the associated Session has expired prior to invoking this method.
     * @throws org.jsecurity.authz.AuthorizationException
     *          if the caller is not authorized to access the session associated with the request.
     */
    public final Session getSession(ServletRequest request, ServletResponse response)
            throws InvalidSessionException, AuthorizationException {

        Session session;
        try {
            session = doGetSession(request, response);
        } catch (InvalidSessionException ise) {
            if (log.isTraceEnabled()) {
                log.trace("Request Session is invalid, message: [" + ise.getMessage() + "].  Removing any " +
                        "associated session cookie...");
            }
            getSessionIdCookieAttribute().removeValue(request, response);

            //give subclass a chance to do something additional if necessary.  Otherwise returning null is just fine:
            session = handleInvalidSession(request, response, ise);
        }

        return session;
    }

    protected Session doGetSession(ServletRequest request, ServletResponse response) {

        Session session = null;
        Serializable sessionId = retrieveSessionId(request, response);

        if (sessionId != null) {
            request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
            session = super.retrieveSession(sessionId);
            if (isValidateRequestOrigin()) {
                if (log.isDebugEnabled()) {
                    log.debug("Validating request origin against session origin");
                }
                validateSessionOrigin(request, session);
            }
            if (session != null) {
                request.setAttribute(JSecurityHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            }
        } else {
            if (log.isTraceEnabled()) {
                log.trace("No JSecurity session id associated with the given " +
                        "HttpServletRequest.  A Session will not be returned.");
            }
        }

        return session;
    }

    protected Session handleInvalidSession(ServletRequest request,
                                           ServletResponse response,
                                           InvalidSessionException ise) {
        if (log.isTraceEnabled()) {
            log.trace("Sesssion associated with the current request is nonexistent or invalid.  Returning null.");
        }
        return null;
    }

    protected void onStop(Session session) {
        super.onStop(session);
        ServletRequest request = WebUtils.getRequiredServletRequest();
        ServletResponse response = WebUtils.getRequiredServletResponse();
        getSessionIdCookieAttribute().removeValue(request, response);
    }
}
