/* * Tanaguru - Automated webpage assessment * Copyright (C) 2008-2015 Tanaguru.org * * This file is part of Tanaguru. * * Tanaguru is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Contact us by mail: tanaguru AT tanaguru DOT org */ package org.tanaguru.webapp.controller; import java.util.*; import java.util.regex.Pattern; import javax.persistence.NoResultException; import javax.servlet.http.HttpServletRequest; import org.displaytag.pagination.PaginatedList; import org.tanaguru.entity.audit.Audit; import org.tanaguru.entity.audit.AuditStatus; import org.tanaguru.entity.parameterization.Parameter; import org.tanaguru.entity.reference.Scope; import org.tanaguru.entity.service.audit.AuditDataService; import org.tanaguru.entity.service.audit.ContentDataService; import org.tanaguru.entity.service.parameterization.ParameterDataService; import org.tanaguru.entity.service.reference.ScopeDataService; import org.tanaguru.entity.service.reference.TestDataService; import org.tanaguru.entity.service.subject.WebResourceDataService; import org.tanaguru.entity.subject.WebResource; import org.tanaguru.webapp.entity.contract.Act; import org.tanaguru.webapp.entity.contract.Contract; import org.tanaguru.webapp.entity.decorator.tanaguru.parameterization.ParameterDataServiceDecorator; import org.tanaguru.webapp.entity.service.contract.ActDataService; import org.tanaguru.webapp.entity.service.statistics.StatisticsDataService; import org.tanaguru.webapp.entity.user.User; import org.tanaguru.webapp.exception.ForbiddenPageException; import org.tanaguru.webapp.exception.ForbiddenUserException; import org.tanaguru.webapp.exception.OrphanWebResourceException; import org.tanaguru.webapp.presentation.data.AuditStatistics; import org.tanaguru.webapp.presentation.factory.AuditStatisticsFactory; import org.tanaguru.webapp.report.pagination.factory.TgolPaginatedListFactory; import org.tanaguru.webapp.util.HttpStatusCodeFamily; import org.tanaguru.webapp.util.TgolKeyStore; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.ServletRequestUtils; import org.springframework.web.servlet.LocaleResolver; /** * This abstract controller handles methods to retrieve and format audit data * @author jkowalczyk */ @Controller public abstract class AbstractAuditDataHandlerController extends AbstractController { private int pageScopeId = 1; public void setPageScopeId(int pageScopeId) { this.pageScopeId = pageScopeId; } private int siteScopeId = 2; public void setSiteScopeId(int siteScopeId) { this.siteScopeId = siteScopeId; } private Scope siteScope; /** * * @return the scope instance */ public Scope getSiteScope() { return siteScope; } private Scope pageScope; public Scope getPageScope() { return pageScope; } /* * Displaying bounds */ protected static final String FROM_VALUE = "fromValue"; protected static final String TO_VALUE = "toValue"; /* * Authorized elements depending on the context. */ private final Set<Integer> authorizedPageSize = new LinkedHashSet<>(); public Set<Integer> getAuthorizedPageSize() { return authorizedPageSize; } public final void setAuthorizedPageSizeList(Set<String> authorizedPageSizeList) { for (String size : authorizedPageSizeList) { this.authorizedPageSize.add(Integer.valueOf(size)); } } private final Set<String> authorizedSortCriterion = new LinkedHashSet<>(); public Set<String> getAuthorizedSortCriterion() { return authorizedSortCriterion; } /** * This method initializes the siteScope and the pageScope instances through * their persistence Id. * @param scopeDataService */ @Autowired public final void setScopeDataService(ScopeDataService scopeDataService) { siteScope = scopeDataService.read(Long.valueOf(siteScopeId)); pageScope = scopeDataService.read(Long.valueOf(pageScopeId)); } private WebResourceDataService webResourceDataService; public WebResourceDataService getWebResourceDataService() { return webResourceDataService; } @Autowired public final void setWebResourceDataService(WebResourceDataService webResourceDataService) { this.webResourceDataService = webResourceDataService; } private StatisticsDataService statisticsDataService; public StatisticsDataService getStatisticsDataService() { return statisticsDataService; } @Autowired public final void setStatisticsDataService(StatisticsDataService statisticsDataService) { this.statisticsDataService = statisticsDataService; } /** * The AuditDataService */ private AuditDataService auditDataService; public AuditDataService getAuditDataService() { return auditDataService; } @Autowired public void setAuditDataService(AuditDataService auditDataService) { this.auditDataService = auditDataService; } private ActDataService actDataService; public ActDataService getActDataService() { return actDataService; } @Autowired public final void setActDataService(ActDataService actDataService) { this.actDataService = actDataService; } private ContentDataService contentDataService; public ContentDataService getContentDataService() { return contentDataService; } @Autowired public final void setContentDataService(ContentDataService contentDataService) { this.contentDataService = contentDataService; } private TestDataService testDataService; public TestDataService getTestDataService() { return testDataService; } @Autowired public final void setTestDataService(TestDataService testDataService) { this.testDataService = testDataService; } private ParameterDataServiceDecorator parameterDataService; public ParameterDataServiceDecorator getParameterDataService() { return parameterDataService; } @Autowired public final void setParameterDataService(ParameterDataServiceDecorator parameterDataService) { this.parameterDataService = parameterDataService; // the audit Set up factory needs to be initialised with the unique instance // of ParameterDataServiceDecorator setDefaultParamSet(parameterDataService); } private Set<Parameter> defaultParamSet; public Set<Parameter> getDefaultParamSet() { return ((Set) ((HashSet) defaultParamSet).clone()); } public final void setDefaultParamSet(ParameterDataService parameterDataService) { this.defaultParamSet = parameterDataService.getDefaultParameterSet(); } private final Map<String, String> parametersToDisplay = new LinkedHashMap<>(); public Map<String, String> getParametersToDisplay() { return parametersToDisplay; } public void setParametersToDisplay(Map<String, String> parametersToDisplay) { this.parametersToDisplay.putAll(parametersToDisplay); } private LocaleResolver localeResolver; public LocaleResolver getLocaleResolver() { return localeResolver; } private final List<String> authorizedScopeForPageList = new ArrayList<>(); public void setAuthorizedScopeForPageList(List<String> authorizedScopeForPageList) { this.authorizedScopeForPageList.addAll(authorizedScopeForPageList); } public List<String> getAuthorizedScopeForPageList() { return authorizedScopeForPageList; } protected boolean isAuthorizedScopeForPageList(Audit audit) { String scope = getActDataService().getActFromAudit(audit).getScope().getCode().name(); return authorizedScopeForPageList.contains(scope); } @Autowired public final void setLocaleResolver(LocaleResolver localeResolver) { this.localeResolver = localeResolver; } private static final String INVALID_TEST_VALUE_CHECKER_REGEXP = "\\d\\d?\\.\\d\\d?\\.?\\d?\\d?"; private final Pattern invalidTestValueCheckerPattern = Pattern.compile(INVALID_TEST_VALUE_CHECKER_REGEXP); public AbstractAuditDataHandlerController() {} /** * Add a populated auditStatistics instance to the model * * @param webResource * @param model * @param displayScope */ protected void addAuditStatisticsToModel(WebResource webResource, Model model, String displayScope) { model.addAttribute( TgolKeyStore.STATISTICS_KEY, getAuditStatistics(webResource, model, displayScope, false)); // default is false for manual audit } /** * * @param webResource * @param model * @param displayScope * @param isAuditManual * @return */ protected AuditStatistics getAuditStatistics(WebResource webResource, Model model, String displayScope, boolean isAuditManual){ return AuditStatisticsFactory.getInstance().getAuditStatistics( webResource, getParametersToDisplay(), displayScope, isAuditManual); } /** * This methods checks whether the current user is allowed to display the * audit result of a given audit. To do so, we verify that the act * associated with the audit belongs to the current user and * that the current contract is not expired * * @param audit * @return * true if the user is allowed to display the result, false otherwise. */ protected boolean isUserAllowedToDisplayResult(Audit audit) { if (audit == null) { throw new ForbiddenPageException(); } User user = getCurrentUser(); Contract contract = getActDataService().getActFromAudit(audit).getContract(); if (isAdminUser() || (!isContractExpired(contract) && user.getId().compareTo( contract.getUser().getId()) == 0)) { return true; } throw new ForbiddenUserException(); } /** * * @param webResource * @return an audit for a given webResource */ protected Audit getAuditFromWebResource(WebResource webResource) { if (webResource.getAudit() != null) { return webResource.getAudit(); } else if (webResource.getParent() != null) { return webResource.getParent().getAudit(); } throw new OrphanWebResourceException(); } /** * @param audit * @return The Contract associated with the given audit (through the * Act associated with the given audit). * */ protected Contract retrieveContractFromAudit(Audit audit) { Act act = null; try { act = getActDataService().getActFromAudit(audit); } catch (NoResultException e) {} if (act!= null && act.getContract() != null) { return act.getContract(); } return null; } /** * * @param audit * @return */ protected String computeAuditStatus(Audit audit) { if (audit.getStatus().equals(AuditStatus.COMPLETED)) { return TgolKeyStore.COMPLETED_KEY; } else if (!contentDataService.hasContent(audit)) { return TgolKeyStore.ERROR_LOADING_KEY; } else if (!contentDataService.hasAdaptedSSP(audit)) { return TgolKeyStore.ERROR_ADAPTING_KEY; } else { return TgolKeyStore.ERROR_UNKNOWN_KEY; } } /** * This method determines which page to display when an error occured * while processing * @param audit * @param model * @return */ protected String prepareFailedAuditData(Audit audit, Model model) { String returnViewName = TgolKeyStore.OUPS_VIEW_NAME; model.addAttribute(TgolKeyStore.AUDIT_URL_KEY, audit.getSubject().getURL()); model.addAttribute(TgolKeyStore.AUDIT_DATE_KEY, audit.getDateOfCreation()); String status = this.computeAuditStatus(audit); if (status.equalsIgnoreCase(TgolKeyStore.ERROR_LOADING_KEY)) { returnViewName = TgolKeyStore.LOADING_ERROR_VIEW_NAME; } else if (status.equalsIgnoreCase(TgolKeyStore.ERROR_ADAPTING_KEY)) { returnViewName = TgolKeyStore.ADAPTING_ERROR_VIEW_NAME; } return returnViewName; } /** * * @param audit * @param model * @param httpStatusCode * @param request * @param returnRedirectView * @return * @throws ServletRequestBindingException */ protected String preparePageListStatsByHttpStatusCode( Audit audit, Model model, HttpStatusCodeFamily httpStatusCode, HttpServletRequest request, boolean returnRedirectView) throws ServletRequestBindingException { String invalidTest = ServletRequestUtils.getStringParameter(request, TgolPaginatedListFactory.INVALID_TEST_PARAM); if (invalidTest != null && !this.invalidTestValueCheckerPattern.matcher(invalidTest).matches()) { throw new ForbiddenPageException(); } PaginatedList paginatedList = TgolPaginatedListFactory.getInstance().getPaginatedList( httpStatusCode, ServletRequestUtils.getStringParameter(request, TgolPaginatedListFactory.PAGE_SIZE_PARAM), ServletRequestUtils.getStringParameter(request, TgolPaginatedListFactory.SORT_DIRECTION_PARAM), ServletRequestUtils.getStringParameter(request, TgolPaginatedListFactory.SORT_CRITERION_PARAM), ServletRequestUtils.getStringParameter(request, TgolPaginatedListFactory.PAGE_PARAM), ServletRequestUtils.getStringParameter(request, TgolPaginatedListFactory.SORT_CONTAINING_URL_PARAM), invalidTest, authorizedPageSize, authorizedSortCriterion, audit.getId()); model.addAttribute(TgolKeyStore.PAGE_LIST_KEY, paginatedList); model.addAttribute(TgolKeyStore.AUTHORIZED_PAGE_SIZE_KEY, authorizedPageSize); model.addAttribute(TgolKeyStore.AUTHORIZED_SORT_CRITERION_KEY, authorizedSortCriterion); setFromToValues(paginatedList, model); // don't forge to add audit statistics to model // addAuditStatisticsToModel(audit, model, TgolKeyStore.TEST_DISPLAY_SCOPE_VALUE); return (returnRedirectView) ? TgolKeyStore.PAGE_LIST_XXX_VIEW_REDIRECT_NAME : TgolKeyStore.PAGE_LIST_XXX_VIEW_NAME; } /** * * @param pageResultList * @param model * @return */ private void setFromToValues(PaginatedList pageResultList, Model model) { model.addAttribute(FROM_VALUE, (pageResultList.getPageNumber()-1) * pageResultList.getObjectsPerPage() +1); if (pageResultList.getList().size() < pageResultList.getObjectsPerPage()) { model.addAttribute(TO_VALUE, (pageResultList.getPageNumber()-1) * pageResultList.getObjectsPerPage() + pageResultList.getList().size()); } else { model.addAttribute(TO_VALUE, (pageResultList.getPageNumber()) * pageResultList.getObjectsPerPage()); } } }