/*
* Copyright 2015-Present Entando Inc. (http://www.entando.com) All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*/
package com.agiletec.plugins.jacms.aps.system.services.dispenser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.entando.entando.aps.system.services.cache.CacheableInfo;
import org.entando.entando.aps.system.services.cache.ICacheInfoManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import com.agiletec.aps.system.RequestContext;
import com.agiletec.aps.system.SystemConstants;
import com.agiletec.aps.system.common.AbstractService;
import com.agiletec.aps.system.common.entity.model.attribute.AttributeRole;
import com.agiletec.aps.system.services.authorization.Authorization;
import com.agiletec.aps.system.services.authorization.IAuthorizationManager;
import com.agiletec.aps.system.services.group.Group;
import com.agiletec.aps.system.services.user.UserDetails;
import com.agiletec.plugins.jacms.aps.system.JacmsSystemConstants;
import com.agiletec.plugins.jacms.aps.system.services.content.IContentManager;
import com.agiletec.plugins.jacms.aps.system.services.content.helper.IContentAuthorizationHelper;
import com.agiletec.plugins.jacms.aps.system.services.content.helper.PublicContentAuthorizationInfo;
import com.agiletec.plugins.jacms.aps.system.services.content.model.Content;
import com.agiletec.plugins.jacms.aps.system.services.linkresolver.ILinkResolverManager;
import com.agiletec.plugins.jacms.aps.system.services.renderer.IContentRenderer;
/**
* Fornisce i contenuti formattati.
* Il compito del servizio, in fase di richiesta di un contenuto formattato, รจ quello di
* controllare preliminarmente le autorizzazzioni dell'utente corrente all'accesso al contenuto;
* successivamente (in caso di autorizzazioni valide) restituisce il contenuto formattato.
* @author M.Diana - E.Santoboni
*/
public class BaseContentDispenser extends AbstractService implements IContentDispenser {
private static final Logger _logger = LoggerFactory.getLogger(BaseContentDispenser.class);
@Override
public void init() throws Exception {
_logger.debug("{} ready", this.getClass().getName());
}
@Override
@Deprecated
public String getRenderedContent(String contentId, long modelId, String langCode, RequestContext reqCtx) {
ContentRenderizationInfo renderInfo = this.getRenderizationInfo(contentId, modelId, langCode, reqCtx);
if (null == renderInfo) {
return "";
}
return renderInfo.getCachedRenderedContent();
}
@Override
@Cacheable(value = ICacheInfoManager.DEFAULT_CACHE_NAME,
key = "T(com.agiletec.plugins.jacms.aps.system.services.dispenser.BaseContentDispenser).getRenderizationInfoCacheKey(#contentId, #modelId, #langCode, #reqCtx)")
@CacheableInfo(groups = "T(com.agiletec.plugins.jacms.aps.system.services.dispenser.BaseContentDispenser).getRenderizationInfoCacheGroupsCsv(#contentId, #modelId)")
public ContentRenderizationInfo getRenderizationInfo(String contentId, long modelId, String langCode, RequestContext reqCtx) {
PublicContentAuthorizationInfo authInfo = this.getContentAuthorizationHelper().getAuthorizationInfo(contentId, true);
if (null == authInfo) {
return null;
}
return this.getRenderizationInfo(authInfo, contentId, modelId, langCode, reqCtx);
}
@Override
@Cacheable(value = ICacheInfoManager.DEFAULT_CACHE_NAME, condition = "#cacheable",
key = "T(com.agiletec.plugins.jacms.aps.system.services.dispenser.BaseContentDispenser).getRenderizationInfoCacheKey(#contentId, #modelId, #langCode, #reqCtx)")
@CacheableInfo(groups = "T(com.agiletec.plugins.jacms.aps.system.services.dispenser.BaseContentDispenser).getRenderizationInfoCacheGroupsCsv(#contentId, #modelId)")
public ContentRenderizationInfo getRenderizationInfo(String contentId,
long modelId, String langCode, RequestContext reqCtx, boolean cacheable) {
PublicContentAuthorizationInfo authInfo = this.getContentAuthorizationHelper().getAuthorizationInfo(contentId, cacheable);
if (null == authInfo) {
return null;
}
return this.getRenderizationInfo(authInfo, contentId, modelId, langCode, reqCtx, cacheable);
}
protected ContentRenderizationInfo getRenderizationInfo(PublicContentAuthorizationInfo authInfo,
String contentId, long modelId, String langCode, RequestContext reqCtx) {
return this.getRenderizationInfo(authInfo, contentId, modelId, langCode, reqCtx, true);
}
protected ContentRenderizationInfo getRenderizationInfo(PublicContentAuthorizationInfo authInfo,
String contentId, long modelId, String langCode, RequestContext reqCtx, boolean cacheable) {
ContentRenderizationInfo renderInfo = null;
try {
UserDetails currentUser = (null != reqCtx) ? (UserDetails) reqCtx.getRequest().getSession().getAttribute(SystemConstants.SESSIONPARAM_CURRENT_USER) : null;
List<Group> userGroups = (null != currentUser) ? this.getAuthorizationManager().getUserGroups(currentUser) : new ArrayList<Group>();
if (authInfo.isUserAllowed(userGroups)) {
renderInfo = this.getBaseRenderizationInfo(authInfo, contentId, modelId, langCode, currentUser, reqCtx, cacheable);
if (null == renderInfo) {
return null;
}
} else {
String renderedContent = "Current user '" + currentUser.getUsername() + "' can't view this content";
Content contentToRender = this.getContentManager().loadContent(contentId, true, cacheable);
renderInfo = new ContentRenderizationInfo(contentToRender, renderedContent, modelId, langCode, null);
renderInfo.setRenderedContent(renderedContent);
return renderInfo;
}
} catch (Throwable t) {
_logger.error("Error while rendering content {}", contentId, t);
return null;
}
return renderInfo;
}
@Override
public void resolveLinks(ContentRenderizationInfo renderizationInfo, RequestContext reqCtx) {
if (null == renderizationInfo) {
return;
}
try {
String finalRenderedContent = this.getLinkResolverManager().resolveLinks(renderizationInfo.getCachedRenderedContent(), renderizationInfo.getContentId(), reqCtx);
renderizationInfo.setRenderedContent(finalRenderedContent);
} catch (Throwable t) {
_logger.error("Error while resolve links for content {}", renderizationInfo.getContentId(), t);
}
}
public ContentRenderizationInfo getBaseRenderizationInfo(PublicContentAuthorizationInfo authInfo,
String contentId, long modelId, String langCode, UserDetails currentUser, RequestContext reqCtx) {
return this.getBaseRenderizationInfo(authInfo, contentId, modelId, langCode, currentUser, reqCtx, true);
}
public ContentRenderizationInfo getBaseRenderizationInfo(PublicContentAuthorizationInfo authInfo,
String contentId, long modelId, String langCode, UserDetails currentUser, RequestContext reqCtx, boolean cacheable) {
ContentRenderizationInfo renderInfo = null;
try {
List<Group> userGroups = (null != currentUser) ? this.getAuthorizationManager().getUserGroups(currentUser) : new ArrayList<Group>();
if (authInfo.isUserAllowed(userGroups)) {
Content contentToRender = this.getContentManager().loadContent(contentId, true, cacheable);
String renderedContent = this.buildRenderedContent(contentToRender, modelId, langCode, reqCtx);
if (null != renderedContent && renderedContent.trim().length() > 0) {
List<AttributeRole> roles = this.getContentManager().getAttributeRoles();
renderInfo = new ContentRenderizationInfo(contentToRender, renderedContent, modelId, langCode, roles);
}
}
} catch (Throwable t) {
_logger.error("Error while rendering content {}", contentId, t);
return null;
}
return renderInfo;
}
protected synchronized String buildRenderedContent(Content content, long modelId, String langCode, RequestContext reqCtx) {
if (null == content) {
_logger.warn("Null The content can't be rendered");
return null;
}
String renderedContent = null;
boolean ok = false;
try {
renderedContent = this.getContentRender().render(content, modelId, langCode, reqCtx);
ok = true;
} catch (Throwable t) {
_logger.error("error in buildRenderedContent", t);
}
if (!ok) {
_logger.warn("The content {} can't be rendered", content.getId());
}
return renderedContent;
}
public static String getRenderizationInfoCacheKey(String contentId, long modelId, String langCode, RequestContext reqCtx) {
UserDetails currentUser = (null != reqCtx) ? (UserDetails) reqCtx.getRequest().getSession().getAttribute(SystemConstants.SESSIONPARAM_CURRENT_USER) : null;
StringBuffer key = new StringBuffer();
key.append(contentId).append("_").append(modelId).append("_").append(langCode).append("_RENDER_INFO_CacheKey");
if (null != currentUser && !currentUser.getUsername().equals(SystemConstants.GUEST_USER_NAME)) {
List<String> codes = new ArrayList<String>();
if (null != currentUser.getAuthorizations()) {
for (int i = 0; i < currentUser.getAuthorizations().size(); i++) {
Authorization auth = currentUser.getAuthorizations().get(i);
if (null != auth && null != auth.getGroup()) {
String code = auth.getGroup().getAuthority() + "_";
if (null != auth.getRole()) {
code += auth.getRole().getAuthority();
} else {
code += "null";
}
codes.add(code);
}
}
}
if (!codes.isEmpty()) {
key.append("_AUTHS:");
appendAuthCodes(codes, key);
}
}
return key.toString();
}
private static void appendAuthCodes(List<String> codes, StringBuffer key) {
Collections.sort(codes);
for (int i = 0; i < codes.size(); i++) {
if (i > 0) {
key.append("-");
}
key.append(codes.get(i));
}
}
public static String getRenderizationInfoCacheGroupsCsv(String contentId, long modelId) {
StringBuilder builder = new StringBuilder();
String typeCode = contentId.substring(0, 3);
String contentCacheGroupId = JacmsSystemConstants.CONTENT_CACHE_GROUP_PREFIX + contentId;
String modelCacheGroupId = JacmsSystemConstants.CONTENT_MODEL_CACHE_GROUP_PREFIX + modelId;
String typeCacheGroupId = JacmsSystemConstants.CONTENT_TYPE_CACHE_GROUP_PREFIX + typeCode;
builder.append(contentCacheGroupId).append(",").append(modelCacheGroupId).append(",").append(typeCacheGroupId);
return builder.toString();
}
protected IContentAuthorizationHelper getContentAuthorizationHelper() {
return _contentAuthorizationHelper;
}
public void setContentAuthorizationHelper(IContentAuthorizationHelper contentAuthorizationHelper) {
this._contentAuthorizationHelper = contentAuthorizationHelper;
}
protected IContentManager getContentManager() {
return _contentManager;
}
public void setContentManager(IContentManager manager) {
this._contentManager = manager;
}
protected IContentRenderer getContentRender() {
return _contentRenderer;
}
public void setContentRenderer(IContentRenderer renderer) {
this._contentRenderer = renderer;
}
protected ILinkResolverManager getLinkResolverManager() {
return _linkResolver;
}
public void setLinkResolver(ILinkResolverManager resolver) {
this._linkResolver = resolver;
}
protected IAuthorizationManager getAuthorizationManager() {
return _authorizationManager;
}
public void setAuthorizationManager(IAuthorizationManager authorizationManager) {
this._authorizationManager = authorizationManager;
}
private IContentAuthorizationHelper _contentAuthorizationHelper;
private IContentRenderer _contentRenderer;
private IContentManager _contentManager;
private ILinkResolverManager _linkResolver;
private IAuthorizationManager _authorizationManager;
}