Java tutorial
/* * [y] hybris Platform * * Copyright (c) 2017 SAP SE or an SAP affiliate company. * All rights reserved. * * This software is the confidential and proprietary information of SAP * ("Confidential Information"). You shall not disclose such Confidential * Information and shall use it only in accordance with the terms of the * license agreement you entered into with SAP. * * */ package de.hybris.platform.assistedservicestorefront.controllers.cms; import de.hybris.platform.acceleratorstorefrontcommons.controllers.AbstractController; import de.hybris.platform.assistedservicefacades.AssistedServiceFacade; import de.hybris.platform.assistedserviceservices.exception.AssistedServiceException; import de.hybris.platform.assistedservicestorefront.constants.AssistedservicestorefrontConstants; import de.hybris.platform.assistedservicestorefront.redirect.AssistedServiceRedirectStrategy; import de.hybris.platform.assistedservicestorefront.security.AssistedServiceAgentAuthoritiesManager; import de.hybris.platform.assistedservicestorefront.security.impl.AssistedServiceAgentLoginStrategy; import de.hybris.platform.assistedservicestorefront.security.impl.AssistedServiceAuthenticationToken; import de.hybris.platform.assistedservicestorefront.util.SubscriptionFacadeReflectionWrapper; import de.hybris.platform.commercefacades.order.data.CartData; import de.hybris.platform.commercefacades.user.data.CustomerData; import de.hybris.platform.core.model.order.CartModel; import de.hybris.platform.core.model.order.payment.CreditCardPaymentInfoModel; import de.hybris.platform.core.model.user.CustomerModel; import de.hybris.platform.core.model.user.UserGroupModel; import de.hybris.platform.core.model.user.UserModel; import de.hybris.platform.jalo.JaloSession; import de.hybris.platform.order.CartService; import de.hybris.platform.servicelayer.session.SessionService; import de.hybris.platform.servicelayer.user.UserService; import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Set; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.sap.security.core.server.csi.XSSEncoder; @Controller @RequestMapping(value = "/assisted-service") public class AssistedServiceComponentController extends AbstractController { private static final String ASSISTED_SERVICE_COMPONENT = "addon:/assistedservicestorefront/cms/asm/assistedServiceComponent"; private static final String ASM_MESSAGE_ATTRIBUTE = "asm_message"; private static final String ASM_REDIRECT_URL_ATTRIBUTE = "redirect_url"; private static final String ASM_ALERT_CLASS = "asm_alert_class"; private static final String ENABLE_360_VIEW = "enable360View"; private static final Logger LOG = Logger.getLogger(AssistedServiceComponentController.class); @Resource(name = "assistedServiceFacade") private AssistedServiceFacade assistedServiceFacade; @Resource(name = "userService") private UserService userService; @Resource(name = "cartService") private CartService cartService; @Resource(name = "assistedServiceAgentLoginStrategy") private AssistedServiceAgentLoginStrategy assistedServiceAgentLoginStrategy; @Resource(name = "sessionService") private SessionService sessionService; @Resource(name = "subscriptionFacadeWrapper") private SubscriptionFacadeReflectionWrapper subscriptionFacadeWrapper; @Resource(name = "assistedServiceRedirectStrategy") private AssistedServiceRedirectStrategy assistedServiceRedirectStrategy; @Resource(name = "assistedServiceAgentAuthoritiesManager") private AssistedServiceAgentAuthoritiesManager authoritiesManager; @RequestMapping(value = "/quit", method = RequestMethod.POST) @ResponseStatus(HttpStatus.OK) public void quitAssistedServiceMode() { assistedServiceFacade.quitAssistedServiceMode(); } @RequestMapping(value = "/login", method = RequestMethod.POST) public String loginAssistedServiceAgent(final Model model, final HttpServletRequest request, final HttpServletResponse response, @RequestParam("username") final String username, @RequestParam("password") final String password) { try { assistedServiceFacade.loginAssistedServiceAgent(username, password); assistedServiceAgentLoginStrategy.login(username, request, response); assistedServiceFacade.emulateAfterLogin(); refreshSpringSecurityToken(); setSessionTimeout(); model.addAttribute(ASM_REDIRECT_URL_ATTRIBUTE, assistedServiceRedirectStrategy.getRedirectPath()); } catch (final AssistedServiceException e) { model.addAttribute(ASM_MESSAGE_ATTRIBUTE, e.getMessageCode()); model.addAttribute(ASM_ALERT_CLASS, e.getAlertClass()); model.addAttribute("username", this.encodeValue(username)); LOG.debug(e.getMessage(), e); } model.addAllAttributes(assistedServiceFacade.getAssistedServiceSessionAttributes()); return ASSISTED_SERVICE_COMPONENT; } @RequestMapping(value = "/logoutasm", method = RequestMethod.POST) public String logoutAssistedServiceAgent(final Model model) { try { assistedServiceFacade.logoutAssistedServiceAgent(); } catch (final AssistedServiceException e) { model.addAttribute(ASM_MESSAGE_ATTRIBUTE, e.getMessage()); LOG.debug(e.getMessage(), e); } model.addAllAttributes(assistedServiceFacade.getAssistedServiceSessionAttributes()); model.addAttribute("customerReload", "reload"); return ASSISTED_SERVICE_COMPONENT; } @RequestMapping(value = "/personify-customer", method = RequestMethod.POST) public String emulateCustomer(final Model model, @RequestParam("customerId") final String customerId, @RequestParam("customerName") final String customerName, @RequestParam("cartId") final String cartId) { try { assistedServiceFacade.emulateCustomer(customerId, cartId); refreshSpringSecurityToken(); model.addAttribute(ASM_REDIRECT_URL_ATTRIBUTE, assistedServiceRedirectStrategy.getRedirectPath()); } catch (final AssistedServiceException e) { model.addAttribute(ASM_MESSAGE_ATTRIBUTE, e.getMessageCode()); model.addAttribute(ASM_ALERT_CLASS, e.getAlertClass()); model.addAttribute("customerId", this.encodeValue(customerId)); model.addAttribute("cartId", this.encodeValue(cartId)); model.addAttribute("customerName", this.encodeValue(customerName)); LOG.debug(e.getMessage(), e); } model.addAllAttributes(assistedServiceFacade.getAssistedServiceSessionAttributes()); return ASSISTED_SERVICE_COMPONENT; } @RequestMapping(value = "/emulate", method = RequestMethod.GET) public String emulateCustomerByLink(final RedirectAttributes redirectAttrs, @RequestParam(value = "customerId", required = false) final String customerId, @RequestParam(value = "cartId", required = false) final String cartId, @RequestParam(value = "orderId", required = false) final String orderId, @RequestParam(value = "fwd", required = false) final String fwd, @RequestParam(value = "enable360View", required = false) final boolean enable360View) { try { // launch AS mode in case it has not been launched yet if (!assistedServiceFacade.isAssistedServiceModeLaunched()) { LOG.debug("ASM launched after link-emulate request"); assistedServiceFacade.launchAssistedServiceMode(); } if (assistedServiceFacade.isAssistedServiceAgentLoggedIn()) { assistedServiceFacade.stopEmulateCustomer(); refreshSpringSecurityToken(); LOG.debug(String.format("Previous emulation for customerId:[%s] has been stopped.", userService.getCurrentUser().getUid())); } //only set the flash attribute if this value is true and will only happen in case 360 view is initiated from customer list if (false != enable360View) { redirectAttrs.addFlashAttribute(ENABLE_360_VIEW, Boolean.valueOf(enable360View)); } assistedServiceFacade.emulateCustomer(customerId, cartId, orderId); LOG.debug(String.format( "Link-emulate request successfuly started an emulation with parameters: customerId:[%s], cartId:[%s]", customerId, cartId)); refreshSpringSecurityToken(); return REDIRECT_PREFIX + assistedServiceRedirectStrategy.getRedirectPath(); } catch (final AssistedServiceException e) { LOG.debug(e.getMessage(), e); redirectAttrs.addFlashAttribute(ASM_MESSAGE_ATTRIBUTE, e.getMessageCode()); redirectAttrs.addFlashAttribute(ASM_ALERT_CLASS, e.getAlertClass()); redirectAttrs.addFlashAttribute("customerId", this.encodeValue(customerId)); redirectAttrs.addFlashAttribute("customerName", this.encodeValue(customerId)); redirectAttrs.addFlashAttribute("cartId", this.encodeValue(cartId)); assistedServiceFacade.getAsmSession().setForwardUrl(fwd); } return REDIRECT_PREFIX + assistedServiceRedirectStrategy.getErrorRedirectPath(); } @RequestMapping(value = "/create-account", method = RequestMethod.POST) public String createCustomer(final Model model, @RequestParam("customerId") final String customerId, @RequestParam("customerName") final String customerName) { String redirectTo = ASSISTED_SERVICE_COMPONENT; try { assistedServiceFacade.createCustomer(customerId, customerName); // customerId is lower cased when user registered using customer account service final String customerIdLowerCased = customerId.toLowerCase(); final CartModel sessionCart = cartService.getSessionCart(); if (sessionCart != null && userService.isAnonymousUser(sessionCart.getUser()) && CollectionUtils.isNotEmpty(sessionCart.getEntries())) { // if there's already an anonymous cart with entries - bind it to customer bindCart(customerIdLowerCased, null, model); redirectTo = emulateCustomer(model, customerIdLowerCased, null, cartService.getSessionCart().getCode()); } else { redirectTo = emulateCustomer(model, customerIdLowerCased, null, null); } try { subscriptionFacadeWrapper.updateProfile(new HashMap<String, String>()); } catch (final Exception ex) { LOG.error("Subscription profile updating failed", ex); throw new AssistedServiceException("Subscription profile updating failed", ex); } } catch (final AssistedServiceException e) { if (e.getMessage() != null && e.getMessage().toLowerCase().contains("duplicate")) { model.addAttribute(ASM_MESSAGE_ATTRIBUTE, "asm.createCustomer.duplicate.error"); model.addAttribute(ASM_ALERT_CLASS, "ASM_alert_customer ASM_alert_create_new"); } else { model.addAttribute(ASM_MESSAGE_ATTRIBUTE, "asm.createCustomer.error"); } model.addAttribute("customerId", this.encodeValue(customerId)); model.addAttribute("customerName", this.encodeValue(customerName + ", " + customerId)); LOG.debug(e.getMessage(), e); } model.addAllAttributes(assistedServiceFacade.getAssistedServiceSessionAttributes()); return redirectTo; } @RequestMapping(value = "/personify-stop", method = RequestMethod.POST) public String endEmulateCustomer(final Model model) { authoritiesManager.restoreInitialAuthorities(); assistedServiceFacade.stopEmulateCustomer(); refreshSpringSecurityToken(); model.addAllAttributes(assistedServiceFacade.getAssistedServiceSessionAttributes()); model.addAttribute(ASM_REDIRECT_URL_ATTRIBUTE, "/"); return ASSISTED_SERVICE_COMPONENT; } @RequestMapping(value = "/resetSession", method = RequestMethod.POST) @ResponseStatus(HttpStatus.OK) public void resetSession() { return; } @RequestMapping(value = "/autocomplete", method = RequestMethod.GET) @ResponseBody public String autocomplete(@RequestParam("customerId") final String customerId, @RequestParam("callback") final String callback) { final StringBuilder autocompleteResult = new StringBuilder(); try { final List<CustomerData> customers = assistedServiceFacade.getSuggestedCustomerList(customerId); // because of jsonp callback parameter - I have to construct JSON manually ( autocompleteResult.append(this.encodeValue(callback)).append("(["); if (CollectionUtils.isNotEmpty(customers)) { for (final CustomerData customer : customers) { final CustomerModel customerModel = (CustomerModel) userService .getUserForUID(customer.getUid()); // TODO REFACTOR THAT try { autocompleteResult.append(getCustomerJSON(customerModel)); } catch (final UnsupportedEncodingException e) { LOG.error("Error occured during encoding customer data: " + customer.getUid(), e); } final Collection<CartData> carts = assistedServiceFacade.getCartListForCustomer(customerModel); if (CollectionUtils.isNotEmpty(carts)) { autocompleteResult.append(", carts:["); final Collection<CartData> cartsForCustomer = carts; for (final CartData cart : cartsForCustomer) { autocompleteResult.append("\"").append(cart.getCode()).append("\","); } autocompleteResult.deleteCharAt(autocompleteResult.length() - 1); autocompleteResult.append("]"); } autocompleteResult.append("},"); } autocompleteResult.deleteCharAt(autocompleteResult.length() - 1); } else { autocompleteResult.append("{label:\"No results found\", value: \"\" }"); } autocompleteResult.append("])"); } catch (final AssistedServiceException e) { // just do nothing and return empty string LOG.debug(e.getMessage(), e); } return autocompleteResult.toString(); } protected String getCustomerJSON(final CustomerModel customer) throws UnsupportedEncodingException { final String cardNumber = customer.getDefaultPaymentInfo() instanceof CreditCardPaymentInfoModel ? ((CreditCardPaymentInfoModel) customer.getDefaultPaymentInfo()).getNumber() : null; final String last4Digits = cardNumber == null ? "----" : cardNumber .subSequence(cardNumber.length() >= 4 ? cardNumber.length() - 4 : 0, cardNumber.length()) .toString(); final String formattedCreationDate = customer.getCreationtime() != null ? new SimpleDateFormat("dd/MM/YYYY").format(customer.getCreationtime()) : "--/--/----"; return String.format("{email:'%s',value:'%s',date:'%s',card:'%s'", XSSEncoder.encodeJavaScript(customer.getUid()), XSSEncoder.encodeJavaScript(customer.getName()), formattedCreationDate, last4Digits); } @RequestMapping(value = "/bind-cart", method = RequestMethod.POST) public String bindCart(@RequestParam(value = "customerId", required = false) final String customerId, @RequestParam(value = "cartId", required = false) final String cartId, final Model model) { try { assistedServiceFacade.bindCustomerToCart(customerId, cartId); refreshSpringSecurityToken(); model.addAttribute(ASM_REDIRECT_URL_ATTRIBUTE, "/"); } catch (final AssistedServiceException e) { model.addAttribute(ASM_MESSAGE_ATTRIBUTE, e.getMessage()); model.addAttribute("customerId", this.encodeValue(customerId)); LOG.debug(e.getMessage(), e); } model.addAllAttributes(assistedServiceFacade.getAssistedServiceSessionAttributes()); return ASSISTED_SERVICE_COMPONENT; } @RequestMapping(value = "/add-to-cart", method = RequestMethod.POST) public String addToCartEventHandler(final Model model) { try { // since cart isn't empty anymore - emulate mode should be on assistedServiceFacade.emulateCustomer(userService.getCurrentUser().getUid(), cartService.getSessionCart().getCode()); } catch (final AssistedServiceException e) { LOG.debug(e.getMessage(), e); return null; // there will be 'page not found' response in case of exception } return refresh(model); } @RequestMapping(value = "/refresh", method = RequestMethod.POST) public String refresh(final Model model) { model.addAllAttributes(assistedServiceFacade.getAssistedServiceSessionAttributes()); return ASSISTED_SERVICE_COMPONENT; } protected void setSessionTimeout() { JaloSession.getCurrentSession().setTimeout(assistedServiceFacade.getAssistedServiceSessionTimeout()); // since agent is logged in - change session timeout to the value from properties ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest().getSession() .setMaxInactiveInterval(assistedServiceFacade.getAssistedServiceSessionTimeout()); // in seconds } /** * This method should be called after any facade method where user substitution may occur */ protected void refreshSpringSecurityToken() { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication instanceof AssistedServiceAuthenticationToken) { final UserModel currentUser = userService.getCurrentUser(); if (currentUser == null || userService.isAnonymousUser(currentUser) || isASAgent(currentUser)) { ((AssistedServiceAuthenticationToken) authentication).setEmulating(false); } else { ((AssistedServiceAuthenticationToken) authentication).setEmulating(true); authoritiesManager.addCustomerAuthoritiesToAgent(currentUser.getUid()); } } } protected boolean isASAgent(final UserModel currentUser) { final Set<UserGroupModel> userGroups = userService.getAllUserGroupsForUser(currentUser); for (final UserGroupModel userGroup : userGroups) { if (AssistedservicestorefrontConstants.AS_AGENT_GROUP_UID.equals(userGroup.getUid())) { return true; } } return false; } protected String encodeValue(final String inputValue) { final String trimmedInputValue = StringUtils.isEmpty(inputValue) ? "" : inputValue.trim(); try { return XSSEncoder.encodeHTML(trimmedInputValue); } catch (final UnsupportedEncodingException e) { LOG.error("Error occured during encoding the input value: " + inputValue, e); } return null; } }