diff --git a/source/java/org/alfresco/web/bean/BaseDetailsBean.java b/source/java/org/alfresco/web/bean/BaseDetailsBean.java index 9e73c6b16b..bdb2b5c2f9 100644 --- a/source/java/org/alfresco/web/bean/BaseDetailsBean.java +++ b/source/java/org/alfresco/web/bean/BaseDetailsBean.java @@ -43,7 +43,9 @@ import org.alfresco.service.cmr.repository.FileTypeImageSize; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.TemplateImageResolver; +import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.OwnableService; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; import org.alfresco.web.app.Application; import org.alfresco.web.app.context.UIContextService; @@ -80,6 +82,9 @@ public abstract class BaseDetailsBean /** CopyService bean reference */ protected CopyService copyService; + /** The PermissionService reference */ + protected PermissionService permissionService; + /** Selected template Id */ protected String template; @@ -103,7 +108,7 @@ public abstract class BaseDetailsBean // Bean property getters and setters /** - * Sets the BrowseBean instance to use to retrieve the current Space + * Sets the BrowseBean instance to use to retrieve the current node * * @param browseBean BrowseBean instance */ @@ -148,6 +153,14 @@ public abstract class BaseDetailsBean this.copyService = copyService; } + /** + * @param permissionService The PermissionService to set. + */ + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + /** * @return Returns the panels expanded state map. */ @@ -172,7 +185,7 @@ public abstract class BaseDetailsBean public abstract Node getNode(); /** - * Returns the id of the current space + * Returns the id of the current node * * @return The id */ @@ -182,9 +195,9 @@ public abstract class BaseDetailsBean } /** - * Returns the name of the current space + * Returns the name of the current node * - * @return Name of the current space + * @return Name of the current */ public String getName() { @@ -208,8 +221,8 @@ public abstract class BaseDetailsBean */ public String getWebdavUrl() { - Node space = getLinkResolvedNode(); - return Utils.generateURL(FacesContext.getCurrentInstance(), space, URLMode.WEBDAV); + Node node = getLinkResolvedNode(); + return Utils.generateURL(FacesContext.getCurrentInstance(), node, URLMode.WEBDAV); } /** @@ -219,8 +232,8 @@ public abstract class BaseDetailsBean */ public String getCifsPath() { - Node space = getLinkResolvedNode(); - return Utils.generateURL(FacesContext.getCurrentInstance(), space, URLMode.CIFS); + Node node = getLinkResolvedNode(); + return Utils.generateURL(FacesContext.getCurrentInstance(), node, URLMode.CIFS); } /** @@ -259,18 +272,42 @@ public abstract class BaseDetailsBean } /** - * @return true if the current document has the 'templatable' aspect applied and - * references a template that currently exists in the system. + * @return true if the current node has a custom Template or Webscript view applied and + * references a template/webscript that currently exists in the system. */ - public boolean isTemplatable() + public boolean getHasCustomView() { - NodeRef templateRef = (NodeRef)getNode().getProperties().get(ContentModel.PROP_TEMPLATE); - return (getNode().hasAspect(ContentModel.ASPECT_TEMPLATABLE) && - templateRef != null && nodeService.exists(templateRef)); + return getHasWebscriptView() || getHasTemplateView(); } /** - * @return String of the NodeRef for the dashboard template used by the space if any + * @return true if the current node has a Template based custom view available + */ + public boolean getHasTemplateView() + { + if (getNode().hasAspect(ContentModel.ASPECT_TEMPLATABLE)) + { + NodeRef templateRef = (NodeRef)getNode().getProperties().get(ContentModel.PROP_TEMPLATE); + return (templateRef != null && this.nodeService.exists(templateRef) && + this.permissionService.hasPermission(templateRef, PermissionService.READ) == AccessStatus.ALLOWED); + } + return false; + } + + /** + * @return true if the current node has a Webscript based custom view available + */ + public boolean getHasWebscriptView() + { + if (getNode().hasAspect(ContentModel.ASPECT_WEBSCRIPTABLE)) + { + return (getNode().getProperties().get(ContentModel.PROP_WEBSCRIPT) != null); + } + return false; + } + + /** + * @return String of the NodeRef for the custom view for the node */ public String getTemplateRef() { @@ -278,6 +315,14 @@ public abstract class BaseDetailsBean return ref != null ? ref.toString() : null; } + /** + * @return Webscript URL for the custom view for the node + */ + public String getWebscriptUrl() + { + return (String)getNode().getProperties().get(ContentModel.PROP_WEBSCRIPT); + } + /** * Returns a model for use by a template on the Details page. * @@ -304,7 +349,7 @@ public abstract class BaseDetailsBean if (this.workflowProperties == null && getNode().hasAspect(ApplicationModel.ASPECT_SIMPLE_WORKFLOW)) { - // get the exisiting properties for the document + // get the exisiting properties for the node Map props = getNode().getProperties(); String approveStepName = (String)props.get( @@ -364,7 +409,7 @@ public abstract class BaseDetailsBean /** * Saves the details of the workflow stored in workflowProperties - * to the current document + * to the current node * * @return The outcome string */ @@ -447,7 +492,7 @@ public abstract class BaseDetailsBean }; txnHelper.doInTransaction(callback); - // reset the state of the current document so it reflects the changes just made + // reset the state of the current node so it reflects the changes just made getNode().reset(); outcome = "finish"; @@ -510,7 +555,7 @@ public abstract class BaseDetailsBean }; txnHelper.doInTransaction(callback); - // if this was called via the document details dialog we need to reset the document node + // if this was called via the node details dialog we need to reset the node if (getNode() != null) { getNode().reset(); @@ -575,7 +620,7 @@ public abstract class BaseDetailsBean }; txnHelper.doInTransaction(callback); - // if this was called via the document details dialog we need to reset the document node + // if this was called via the node details dialog we need to reset the node if (getNode() != null) { getNode().reset(); @@ -596,7 +641,7 @@ public abstract class BaseDetailsBean // Action event handlers /** - * Action handler to apply the selected Template and Templatable aspect to the current Space + * Action handler to apply the selected Template and Templatable aspect to the current node */ public void applyTemplate(ActionEvent event) { @@ -628,7 +673,7 @@ public abstract class BaseDetailsBean } /** - * Action handler to remove a dashboard template from the current Space + * Action handler to remove a custom view template from the current node */ public void removeTemplate(ActionEvent event) { @@ -649,7 +694,7 @@ public abstract class BaseDetailsBean } /** - * Action Handler to take Ownership of the current Space + * Action Handler to take Ownership of the current node */ public void takeOwnership(final ActionEvent event) { diff --git a/source/java/org/alfresco/web/bean/NavigationBean.java b/source/java/org/alfresco/web/bean/NavigationBean.java index bd9c871d43..2a20d6a5cd 100644 --- a/source/java/org/alfresco/web/bean/NavigationBean.java +++ b/source/java/org/alfresco/web/bean/NavigationBean.java @@ -49,6 +49,7 @@ import org.alfresco.service.cmr.repository.TemplateImageResolver; import org.alfresco.service.cmr.repository.TemplateService; import org.alfresco.service.cmr.rule.RuleService; import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; @@ -155,6 +156,14 @@ public class NavigationBean { this.authService = authService; } + + /** + * @param permissionService The PermissionService to set. + */ + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } /** * @return the User object representing the current instance for this user @@ -444,38 +453,56 @@ public class NavigationBean } /** - * @return true if the current node has a template view available + * @return true if the current node has a custom view available */ - public boolean getCurrentNodeHasTemplate() + public boolean getHasCustomView() + { + return getHasWebscriptView() || getHasTemplateView(); + } + + /** + * @return true if the current node has a Template based custom view available + */ + public boolean getHasTemplateView() { - boolean templateView = false; Node node = getCurrentNode(); if (node.hasAspect(ContentModel.ASPECT_TEMPLATABLE)) { NodeRef templateRef = (NodeRef)node.getProperties().get(ContentModel.PROP_TEMPLATE); - try - { - templateView = (templateRef != null && this.nodeService.exists(templateRef)); - } - catch (AccessDeniedException err) - { - // default to false if no access to template - } + return (templateRef != null && this.nodeService.exists(templateRef) && + this.permissionService.hasPermission(templateRef, PermissionService.READ) == AccessStatus.ALLOWED); } - return templateView; + return false; } /** - * @return the NodeRef.toString() for the current node template view if it has one set + * @return true if the current node has a Webscript based custom view available + */ + public boolean getHasWebscriptView() + { + Node node = getCurrentNode(); + if (node.hasAspect(ContentModel.ASPECT_WEBSCRIPTABLE)) + { + return (node.getProperties().get(ContentModel.PROP_WEBSCRIPT) != null); + } + return false; + } + + /** + * @return the NodeRef.toString() for the current node Template custom view if it has one */ public String getCurrentNodeTemplate() { - String strRef = null; - if (getCurrentNodeHasTemplate() == true) - { - strRef = getCurrentNode().getProperties().get(ContentModel.PROP_TEMPLATE).toString(); - } - return strRef; + NodeRef ref = (NodeRef)getCurrentNode().getProperties().get(ContentModel.PROP_TEMPLATE); + return ref != null ? ref.toString() : null; + } + + /** + * @return the service url for the current node Webscript custom view if it has one + */ + public String getCurrentNodeWebscript() + { + return (String)getCurrentNode().getProperties().get(ContentModel.PROP_WEBSCRIPT); } /** @@ -486,8 +513,8 @@ public class NavigationBean @SuppressWarnings("unchecked") public Map getTemplateModel() { - HashMap model = new HashMap(1, 1.0f); - + HashMap model = new HashMap(2, 1.0f); + model.put("space", getCurrentNode().getNodeRef()); model.put(TemplateService.KEY_IMAGE_RESOLVER, new TemplateImageResolver() @@ -928,6 +955,9 @@ public class NavigationBean /** The Authentication service bean reference */ protected AuthenticationService authService; + /** The PermissionService reference */ + protected PermissionService permissionService; + /** Cached path to our CIFS server and top level node DIR */ private String cifsServerPath; diff --git a/source/java/org/alfresco/web/scripts/jsf/UIWebScript.java b/source/java/org/alfresco/web/scripts/jsf/UIWebScript.java index 746e8782d3..ae47c97576 100644 --- a/source/java/org/alfresco/web/scripts/jsf/UIWebScript.java +++ b/source/java/org/alfresco/web/scripts/jsf/UIWebScript.java @@ -67,6 +67,10 @@ public class UIWebScript extends SelfRenderingComponent /** WebScript URL to execute */ private String scriptUrl = null; + + /** User defined script context value */ + private Object context = null; + private boolean scriptUrlModified = false; private WebScriptRegistry registry; @@ -104,6 +108,7 @@ public class UIWebScript extends SelfRenderingComponent super.restoreState(context, values[0]); this.scriptUrl = (String)values[1]; this.scriptUrlModified = (Boolean)values[2]; + this.context = values[3]; } /** @@ -112,7 +117,7 @@ public class UIWebScript extends SelfRenderingComponent public Object saveState(FacesContext context) { Object values[] = new Object[] { - super.saveState(context), this.scriptUrl, this.scriptUrlModified}; + super.saveState(context), this.scriptUrl, this.scriptUrlModified, this.context}; return values; } @@ -163,11 +168,35 @@ public class UIWebScript extends SelfRenderingComponent @Override public void encodeBegin(FacesContext context) throws IOException { + String scriptUrl = getScriptUrl(); + + Object scriptContext = getContext(); + if (scriptContext != null) + { + // context object supplied, perform simple variable substitution + if (scriptContext instanceof Map) + { + Map scriptContextMap = (Map)scriptContext; + for (String key : scriptContextMap.keySet()) + { + scriptUrl = scriptUrl.replace(key, scriptContextMap.get(key).toString()); + } + } + else + { + // currently we only support {noderef} replacement directly + // TODO: move the variable substitution into the WebScript engine - pass in + // a bag of context objects i.e. name/value pairs of well known keys + // allow common values such as noderef, nodeid, path, user etc. + scriptUrl = scriptUrl.replace("{noderef}", scriptContext.toString()); + } + } + // execute WebScript if (logger.isDebugEnabled()) - logger.debug("Processing UIWebScript encodeBegin(): " + getScriptUrl()); + logger.debug("Processing UIWebScript encodeBegin(): " + scriptUrl); - WebScriptRuntime runtime = new WebScriptJSFRuntime(context, getScriptUrl()); + WebScriptRuntime runtime = new WebScriptJSFRuntime(context, scriptUrl); runtime.executeScript(); } @@ -191,12 +220,34 @@ public class UIWebScript extends SelfRenderingComponent ValueBinding vb = getValueBinding("scriptUrl"); if (vb != null) { - this.scriptUrl = (String)vb.getValue(getFacesContext()); + this.scriptUrl = getFacesContext().getExternalContext().getRequestContextPath() + + (String)vb.getValue(getFacesContext()); } } return this.scriptUrl; } + /** + * @return the user defined script context object + */ + public Object getContext() + { + ValueBinding vb = getValueBinding("context"); + if (vb != null) + { + this.context = vb.getValue(getFacesContext()); + } + return this.context; + } + + /** + * @param context the user defined script context to set + */ + public void setContext(Object context) + { + this.context = context; + } + // ------------------------------------------------------------------------------ // Inner classes @@ -209,7 +260,7 @@ public class UIWebScript extends SelfRenderingComponent public WebScriptEvent(UIComponent component, String url) { super(component); - Url = url; + this.Url = url; } public String Url = null; diff --git a/source/java/org/alfresco/web/scripts/jsf/WebScriptTag.java b/source/java/org/alfresco/web/scripts/jsf/WebScriptTag.java index 8e5ae65410..2eeea14222 100644 --- a/source/java/org/alfresco/web/scripts/jsf/WebScriptTag.java +++ b/source/java/org/alfresco/web/scripts/jsf/WebScriptTag.java @@ -61,6 +61,7 @@ public class WebScriptTag extends BaseComponentTag { super.setProperties(component); setStringProperty(component, "scriptUrl", this.scriptUrl); + setStringProperty(component, "context", this.context); } /** @@ -70,19 +71,33 @@ public class WebScriptTag extends BaseComponentTag { super.release(); this.scriptUrl = null; + this.context = null; } /** - * Set the scriptUrl + * Set the script service Url * - * @param scriptUrl the scriptUrl + * @param scriptUrl the script service Url */ public void setScriptUrl(String scriptUrl) { this.scriptUrl = scriptUrl; } + + /** + * Set the script context + * + * @param context the script context + */ + public void setContext(String context) + { + this.context = context; + } + /** the script context */ + private String context; + /** the scriptUrl */ private String scriptUrl; } diff --git a/source/java/org/alfresco/web/ui/repo/component/template/UITemplate.java b/source/java/org/alfresco/web/ui/repo/component/template/UITemplate.java index bb6078a2b6..2b0bb5c348 100644 --- a/source/java/org/alfresco/web/ui/repo/component/template/UITemplate.java +++ b/source/java/org/alfresco/web/ui/repo/component/template/UITemplate.java @@ -58,8 +58,6 @@ import org.apache.log4j.Logger; */ public class UITemplate extends SelfRenderingComponent { - //private final static String ENGINE_DEFAULT = "freemarker"; - private static Logger logger = Logger.getLogger(UITemplate.class); /** Template name/classpath */ @@ -182,34 +180,30 @@ public class UITemplate extends SelfRenderingComponent */ private Object getTemplateModel(Object model, String template) { - //if (getEngine().equals(ENGINE_DEFAULT)) - //{ - // create an instance of the default FreeMarker template object model - FacesContext fc = FacesContext.getCurrentInstance(); - ServiceRegistry services = Repository.getServiceRegistry(fc); - User user = Application.getCurrentUser(fc); + // create an instance of the default FreeMarker template object model + FacesContext fc = FacesContext.getCurrentInstance(); + ServiceRegistry services = Repository.getServiceRegistry(fc); + User user = Application.getCurrentUser(fc); + + // add the template itself to the model + NodeRef templateRef = null; + if (template.indexOf(StoreRef.URI_FILLER) != -1) + { + // found a noderef template + templateRef = new NodeRef(template); + } + + Map root = DefaultModelHelper.buildDefaultModel(services, user, templateRef); + + // merge models + if (model instanceof Map) + { + if (logger.isDebugEnabled()) + logger.debug("Found valid Map model to merge with FreeMarker: " + model); - // add the template itself to the model - NodeRef templateRef = null; - if (template.indexOf(StoreRef.URI_FILLER) != -1) - { - // found a noderef template - templateRef = new NodeRef(template); - } - - Map root = DefaultModelHelper.buildDefaultModel(services, user, templateRef); - - // merge models - if (model instanceof Map) - { - if (logger.isDebugEnabled()) - logger.debug("Found valid Map model to merge with FreeMarker: " + model); - - root.putAll((Map)model); - } - - model = root; - // } + root.putAll((Map)model); + } + model = root; return model; } diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml index 2e005b9543..05af4501fb 100644 --- a/source/web/WEB-INF/faces-config-beans.xml +++ b/source/web/WEB-INF/faces-config-beans.xml @@ -240,6 +240,10 @@ authenticationService #{AuthenticationService} + + permissionService + #{PermissionService} + @@ -1363,6 +1367,10 @@ editionService #{EditionService} + + permissionService + #{PermissionService} + @@ -1396,6 +1404,10 @@ copyService #{CopyService} + + permissionService + #{PermissionService} + diff --git a/source/web/WEB-INF/repo.tld b/source/web/WEB-INF/repo.tld index c4f0304003..6e2d68895c 100644 --- a/source/web/WEB-INF/repo.tld +++ b/source/web/WEB-INF/repo.tld @@ -2100,6 +2100,12 @@ true true + + + context + false + true + diff --git a/source/web/jsp/browse/browse.jsp b/source/web/jsp/browse/browse.jsp index 4d221d2505..b720c735fa 100644 --- a/source/web/jsp/browse/browse.jsp +++ b/source/web/jsp/browse/browse.jsp @@ -193,7 +193,7 @@ - + @@ -211,14 +211,15 @@ <%-- Custom Template View --%> - + - + + diff --git a/source/web/jsp/browse/dashboard.jsp b/source/web/jsp/browse/dashboard.jsp index f0f3802925..9b05232ec1 100644 --- a/source/web/jsp/browse/dashboard.jsp +++ b/source/web/jsp/browse/dashboard.jsp @@ -120,7 +120,8 @@ - + + diff --git a/source/web/jsp/dashboards/dashlets/doclist-webscript.jsp b/source/web/jsp/dashboards/dashlets/doclist-webscript.jsp index e498115b7a..eb6cfceae8 100644 --- a/source/web/jsp/dashboards/dashlets/doclist-webscript.jsp +++ b/source/web/jsp/dashboards/dashlets/doclist-webscript.jsp @@ -24,4 +24,4 @@ --%> <%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> - \ No newline at end of file + \ No newline at end of file diff --git a/source/web/jsp/dashboards/dashlets/myspaces-webscript.jsp b/source/web/jsp/dashboards/dashlets/myspaces-webscript.jsp index a6bc630fc2..8635630631 100644 --- a/source/web/jsp/dashboards/dashlets/myspaces-webscript.jsp +++ b/source/web/jsp/dashboards/dashlets/myspaces-webscript.jsp @@ -24,4 +24,4 @@ --%> <%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> - \ No newline at end of file + \ No newline at end of file diff --git a/source/web/jsp/dashboards/dashlets/mytasks-webscript.jsp b/source/web/jsp/dashboards/dashlets/mytasks-webscript.jsp index 571487a8aa..fa04dd1d07 100644 --- a/source/web/jsp/dashboards/dashlets/mytasks-webscript.jsp +++ b/source/web/jsp/dashboards/dashlets/mytasks-webscript.jsp @@ -24,4 +24,4 @@ --%> <%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> - \ No newline at end of file + \ No newline at end of file diff --git a/source/web/jsp/dashboards/dashlets/mywebforms-webscript.jsp b/source/web/jsp/dashboards/dashlets/mywebforms-webscript.jsp index 9febd32fcd..3e0d071bf6 100644 --- a/source/web/jsp/dashboards/dashlets/mywebforms-webscript.jsp +++ b/source/web/jsp/dashboards/dashlets/mywebforms-webscript.jsp @@ -24,4 +24,4 @@ --%> <%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> - \ No newline at end of file + \ No newline at end of file diff --git a/source/web/jsp/dialog/document-details.jsp b/source/web/jsp/dialog/document-details.jsp index cddbb2b515..f790b84924 100644 --- a/source/web/jsp/dialog/document-details.jsp +++ b/source/web/jsp/dialog/document-details.jsp @@ -158,11 +158,12 @@ - + - +
- + +
diff --git a/source/web/jsp/dialog/space-details.jsp b/source/web/jsp/dialog/space-details.jsp index f495c315b3..fa6b1c20f9 100644 --- a/source/web/jsp/dialog/space-details.jsp +++ b/source/web/jsp/dialog/space-details.jsp @@ -146,11 +146,12 @@ - + - +
- + +