package org.onehippo.forge.konakart.site.container;
import com.konakart.al.KKAppEng;
import com.konakartadmin.app.AdminCustomer;
import com.konakartadmin.bl.AdminMgrFactory;
import org.apache.commons.lang.StringUtils;
import org.hippoecm.hst.core.container.ContainerException;
import org.hippoecm.hst.core.container.Valve;
import org.hippoecm.hst.core.container.ValveContext;
import org.hippoecm.hst.core.linking.HstLink;
import org.hippoecm.hst.core.linking.HstLinkCreator;
import org.hippoecm.hst.core.request.HstRequestContext;
import org.onehippo.forge.konakart.common.engine.KKAdminEngine;
import org.onehippo.forge.konakart.common.engine.KKEngine;
import org.onehippo.forge.konakart.common.engine.KKStoreConfig;
import org.onehippo.forge.konakart.common.jcr.HippoModuleConfig;
import org.onehippo.forge.konakart.hst.utils.KKComponentUtils;
import org.onehippo.forge.konakart.site.security.KKUser;
import org.onehippo.forge.konakart.site.service.KKServiceHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
public class KonakartValve implements Valve {
public static Logger log = LoggerFactory.getLogger(KonakartValve.class);
public final static String REDIRECT_LOGOUT_URL = "/j_spring_security_logout";
@Override
public void initialize() throws ContainerException {
}
@Override
public void destroy() {
}
@Override
public void invoke(ValveContext context) throws ContainerException {
HttpServletRequest request = context.getServletRequest();
HttpServletResponse response = context.getServletResponse();
HstRequestContext requestContext = context.getRequestContext();
Session jcrSession;
try {
jcrSession = context.getRequestContext().getSession();
} catch (RepositoryException e) {
throw new IllegalStateException("Failed to retrieve the Jcr Session", e);
}
// Pre-load the checkout activities
try {
HippoModuleConfig.getConfig().preLoadActivityList(jcrSession);
} catch (RepositoryException e) {
throw new IllegalStateException("Failed to load the list of activities. ", e);
}
// Initialize internal Konakart Engine configuration
KKEngine.init(jcrSession);
// Initialize the Konakart Admin Client
try {
KKAdminEngine.init(jcrSession);
} catch (Exception e) {
throw new IllegalStateException("Failed to initialize the Konakart Admin Client", e);
}
KKStoreConfig kkStoreConfig = KKComponentUtils.getKKStoreConfig(context.getRequestContext(), jcrSession);
request.getSession().setAttribute(KKStoreConfig.KK_STORE_CONFIG, kkStoreConfig);
// Retrieve the Konakart client
KKAppEng kkAppEng = KKServiceHelper.getKKEngineService().getKKAppEng(request);
boolean switchKKAppEng = false;
if (kkAppEng != null) {
switchKKAppEng = !StringUtils.equalsIgnoreCase(kkStoreConfig.getStoreId(), kkAppEng.getStoreId());
}
// Initialize the konakart client if it has not been created
if (kkAppEng == null || !StringUtils.equalsIgnoreCase(kkStoreConfig.getStoreId(), kkAppEng.getStoreId())) {
// Check if a previous kkAppEng client has been created.
kkAppEng = (KKAppEng) request.getSession().getAttribute(KKAppEng.KONAKART_KEY + "-" + kkStoreConfig.getStoreId());
// An new kkAppEng will be created.
if (kkAppEng == null || !StringUtils.equalsIgnoreCase(kkStoreConfig.getStoreId(), kkAppEng.getStoreId())) {
// Initialize Konakart Engine
kkAppEng = KKServiceHelper.getKKEngineService().initKKEngine(request, response, requestContext, jcrSession, kkStoreConfig);
}
}
// Validate the current konakart session
int customerId = KKServiceHelper.getKKEngineService().validKKSession(request, response);
// Set the konakart client
request.setAttribute(KKAppEng.KONAKART_KEY, kkAppEng);
// Set within the thread local. KKAppEng will be accessible without a Http request
KKEngine.set(kkAppEng);
// At this stage, the Konakart client engine is created and is configured.
// The authentication is a two-phase process. The first phase uses the current JAAS authentication using
// the KonakartLoginModule. This phase checks if the customer exists and set the roles
// The second phase valids the username/password against Konakart.
Principal userPrincipal = request.getUserPrincipal();
if (userPrincipal instanceof Authentication) {
Authentication authentication = (Authentication) userPrincipal;
KKUser kkUser = (KKUser) authentication.getPrincipal();
int kkCustomerId = kkUser.getCustomerId();
if (kkUser.isRememberMeAuthentication()) {
// Auto login same session
if (kkCustomerId == customerId) {
// The Login should work because the validation of the password has been done during the login process
// by the KonakartLoginModule.
if (!KKServiceHelper.getKKEngineService().loginByAdmin(request, response, kkCustomerId)) {
logout(request, response, requestContext);
return;
}
}
} else {
boolean autoLogin = true;
if (customerId == -1 && switchKKAppEng) {
AdminMgrFactory adminMgrFactory = KKAdminEngine.getInstance().getFactory();
try {
// Retrieve the current logged customer and check if the groupId is accepted by the store
// If it is the case, the user will be logged in within this store
AdminCustomer adminCustomer = adminMgrFactory.getAdminCustMgr(true).getCustomerForId(kkCustomerId);
autoLogin = adminCustomer != null &&
adminCustomer.getGroupId() > 0 &&
kkStoreConfig.acceptSecurityCustomerGroup(String.valueOf(adminCustomer.getGroupId()));
} catch (Exception e) {
log.error("Failed to retrieve the admin customer", e);
}
}
if (autoLogin) {
// Invalid username and password
String username = userPrincipal.getName();
String password = String.valueOf(authentication.getCredentials());
// The Login should work because the validation of the password has been done during the login process
// by the KonakartLoginModule.
if (!KKServiceHelper.getKKEngineService().logIn(request, response,
username, password)) {
logout(request, response, requestContext);
}
} else {
SecurityContextHolder.clearContext();
}
}
} else {
// No user principal has been found. The user has been logged out.
// We need to log-out from Konakart
KKServiceHelper.getKKEngineService().logOut(request, response);
}
// Instantiate the next context
context.invokeNext();
}
private void logout(HttpServletRequest request, HttpServletResponse response, HstRequestContext requestContext) {
try {
HstLinkCreator linkCreator = requestContext.getHstLinkCreator();
HstLink link = linkCreator.create(REDIRECT_LOGOUT_URL, requestContext.getResolvedMount().getMount());
request.getRequestDispatcher(link.getPath()).forward(request, response);
} catch (IOException e) {
log.error("Failed to redirect to the path - " + REDIRECT_LOGOUT_URL);
} catch (ServletException e) {
log.error("Failed to redirect to the path - " + REDIRECT_LOGOUT_URL);
}
}
}