package com.mozu.api.sample.controller;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
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.SessionAttributes;
import com.mozu.api.ApiContext;
import com.mozu.api.ApiException;
import com.mozu.api.MozuApiContext;
import com.mozu.api.MozuConfig;
import com.mozu.api.contracts.appdev.AppAuthInfo;
import com.mozu.api.contracts.commerceruntime.orders.OrderCollection;
import com.mozu.api.contracts.core.UserAuthInfo;
import com.mozu.api.contracts.productadmin.ProductCollection;
import com.mozu.api.contracts.tenant.Site;
import com.mozu.api.contracts.tenant.Tenant;
import com.mozu.api.resources.commerce.OrderResource;
import com.mozu.api.resources.commerce.catalog.admin.ProductResource;
import com.mozu.api.resources.platform.TenantResource;
import com.mozu.api.sample.model.MozuAuthorization;
import com.mozu.api.sample.model.SiteSelector;
import com.mozu.api.security.AppAuthenticator;
import com.mozu.api.security.AuthenticationProfile;
import com.mozu.api.security.AuthenticationScope;
import com.mozu.api.security.Scope;
import com.mozu.api.security.UserAuthenticator;
/**
* Handles requests for the application home page.
*/
@Controller
@SessionAttributes ("tenantAuthorization")
/**
* Spring MVC Controller for the Mozu Sample Web Application for Java API
* @author bob_hewett
*
*/
public class MozuController {
private static final Logger logger = LoggerFactory.getLogger(MozuController.class);
@Resource (name="environments")
protected Map<String, String> environments;
public MozuController () {
}
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
this.setupHomePage(locale, model);
return "home";
}
@RequestMapping(value = "/authorization", method = RequestMethod.POST)
/**
* Authorizes the application with the AppID and Shared Secret. Authenticates the tenant user supplied.
* @param authorization login auth form data
* @param locale
* @param model
* @return
*/
public String authorize (@ModelAttribute MozuAuthorization authorization, Locale locale, Model model) {
// Authorize Application
AppAuthInfo appAuthInfo = new AppAuthInfo();
appAuthInfo.setApplicationId(authorization.getAppId());
appAuthInfo.setSharedSecret(authorization.getSharedSecret());
String baseUrl = environments.get(authorization.getEnvironment());
try {
MozuConfig.setBaseUrl(baseUrl);
AppAuthenticator.initialize(appAuthInfo, null);
} catch (ApiException ae){
model.addAttribute("errorString", "Error Validating Application: " + ae.getMessage());
setupHomePage (locale, model);
logger.error("Unable to authenticate application");
return "home";
}
// Authorize user and get tenants
UserAuthInfo userAuth = new UserAuthInfo();
userAuth.setEmailAddress(authorization.getEmail());
userAuth.setPassword(authorization.getPassword());
try {
// Authorize user
AuthenticationProfile authProfile = UserAuthenticator.authenticate(userAuth, AuthenticationScope.Tenant);
// get list of tenants a user has access to
List<Scope> tenants = authProfile.getAuthorizedScopes();
List<Site> sites = null;
// if there is only only one tenant, the user is assigned to that tenant...no need to have them select on.
if (tenants != null && tenants.size() > 0) {
// find first tenant that we have access to.
for (Scope tenant : tenants) {
Integer tenantId = tenant.getId();
try {
sites = getAvailableTenantSites(tenantId);
// you must refresh the auth ticket with a valid tenant id...for this sample, we pick the first one and refresh the auth.
// if there is only one tenant, it doesn't need to be refreshed as the active scope will be set with the tenant ID.
if (authProfile.getActiveScope() == null) {
authProfile = UserAuthenticator.refreshUserAuthTicket(authProfile.getAuthTicket(), tenantId);
}
break;
} catch (ApiException ae) {
logger.info ("Application ID cannot access tenant" + tenantId + ": " + ae.getMessage());
}
}
} else {
sites = new ArrayList<Site>();
}
model.addAttribute("tenantAuthorization", authProfile);
model.addAttribute("user", authProfile.getUserProfile());
model.addAttribute("availableTenants", tenants);
model.addAttribute("sites", sites);
} catch (ApiException ae) {
setupHomePage (locale, model);
model.addAttribute("errorString", "Error Validating User: " + ae.getMessage());
return "home";
}
return "tenants";
}
/**
* This method is used when the application and user have been authorized
* @param tenantId
* @param locale
* @param modelMap
* @param model
* @return
*/
@RequestMapping(value = "/tenants", method = RequestMethod.GET)
public String getTenants(@RequestParam ("tenantId") Integer tenantId, Locale locale, ModelMap modelMap, Model model) {
AuthenticationProfile authenticationProfile = (AuthenticationProfile)modelMap.get("tenantAuthorization");
//if there is no active user, go to the auth page.
if (authenticationProfile == null) {
setupHomePage (locale, model);
return "home";
}
// if no tenant id was supplied just use the active tenantID in the user auth.
if (tenantId == null) {
tenantId = authenticationProfile.getActiveScope().getId();
}
// we need to get a new auth ticket for the tenant and update the authenticationProfile in session.
if (tenantId != null && !tenantId.equals(authenticationProfile.getActiveScope().getId())) {
authenticationProfile = UserAuthenticator.refreshUserAuthTicket(authenticationProfile.getAuthTicket(), tenantId);
model.addAttribute("tenantAuthorization", authenticationProfile);
}
// Authorize user and get tenants
List<Scope> tenants = authenticationProfile.getAuthorizedScopes();
if (tenants == null) {
tenants = new ArrayList<Scope>();
tenants.add(authenticationProfile.getActiveScope());
}
model.addAttribute("user", authenticationProfile.getUserProfile());
model.addAttribute("availableTenants", tenants);
model.addAttribute("tenantId", tenantId);
List<Site> sites = null;
if (tenants != null && tenants.size() > 0) {
sites = getAvailableTenantSites(tenantId);
} else {
sites = new ArrayList<Site>();
}
model.addAttribute("sites", sites);
return "tenants";
}
@RequestMapping(value = "/products", method = RequestMethod.POST)
public String getProducts (@ModelAttribute SiteSelector siteSelector, Locale locale, ModelMap modelMap, Model model)
throws Exception {
AuthenticationProfile userAuthentication = (AuthenticationProfile)modelMap.get("tenantAuthorization");
//if there is no active user, go to the auth page.
if (userAuthentication == null) {
setupHomePage (locale, model);
return "home";
}
Integer tenantId = Integer.valueOf(siteSelector.getTenant());
ApiContext apiContext = new MozuApiContext(tenantId, Integer.valueOf(siteSelector.getSite()));
apiContext.setUserAuthTicket(userAuthentication.getAuthTicket());
ProductResource prodResource = new ProductResource (apiContext);
try {
ProductCollection prodCollection = prodResource.getProducts(0, 100, null, null, null, null, false, null);
modelMap.addAttribute("products", prodCollection.getItems());
return "products";
} catch (Exception ae) {
model.addAttribute("errorString", "Unable to get products: " + ae.getMessage());
return getTenants(tenantId, locale, modelMap, model);
}
}
@RequestMapping(value = "/orders", method = RequestMethod.POST)
public String getOrders (@ModelAttribute SiteSelector siteSelector, Locale locale, ModelMap modelMap, Model model)
throws Exception {
AuthenticationProfile userAuthentication = (AuthenticationProfile)modelMap.get("tenantAuthorization");
//if there is no active user, go to the auth page.
if (userAuthentication == null) {
setupHomePage (locale, model);
return "home";
}
Integer tenantId = Integer.valueOf(siteSelector.getTenant());
ApiContext apiContext = new MozuApiContext(tenantId, Integer.valueOf(siteSelector.getSite()));
apiContext.setUserAuthTicket(userAuthentication.getAuthTicket());
OrderResource orderResourceResource = new OrderResource(apiContext);
try {
OrderCollection orderCollection = orderResourceResource.getOrders(0, 100, null, null, null, null, null);
model.addAttribute("orders", orderCollection.getItems());
return "orders";
} catch (Exception ae) {
model.addAttribute("errorString", "Unable to get products: " + ae.getMessage());
return getTenants(tenantId, locale, modelMap, model);
}
}
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout (Locale locale, ModelMap modelMap, Model model) {
AuthenticationProfile userAuthentication = (AuthenticationProfile)modelMap.get("tenantAuthorization");
UserAuthenticator.logout(userAuthentication.getAuthTicket());
AppAuthenticator.invalidateAuth();
modelMap.remove("tenantAuthorization");
return home(locale, model);
}
private void setupHomePage (Locale locale,Model model) {
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
model.addAttribute("environments", environments.keySet());
}
private List<Site> getAvailableTenantSites(Integer tenantId) {
TenantResource tenantResource = new TenantResource();
try {
Tenant tenant = tenantResource.getTenant(tenantId);
return tenant.getSites();
} catch (Exception e) {
throw new ApiException("Unable to get tenant: " + e.getMessage());
}
}
}