Author: adrianc
Date: Mon Dec  2 04:19:48 2013
New Revision: 1546891

URL: http://svn.apache.org/r1546891
Log:
Added a new attribute to the ofbiz-component.xml <webapp> element - 
access-permission. It is used to specify an explicit permission to allow access 
to the web application, instead of the implied permissions specified in the 
base-permission attribute (which causes unpredictable behavior).

Also moved web access authorization code from the Flat Grey visual theme to 
LoginWorker.java. This change needs to be copied to other visual themes as well.

Modified:
    ofbiz/trunk/framework/base/dtd/ofbiz-component.xsd
    ofbiz/trunk/framework/base/src/org/ofbiz/base/component/ComponentConfig.java
    ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java
    ofbiz/trunk/themes/flatgrey/includes/appbar.ftl

Modified: ofbiz/trunk/framework/base/dtd/ofbiz-component.xsd
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/dtd/ofbiz-component.xsd?rev=1546891&r1=1546890&r2=1546891&view=diff
==============================================================================
--- ofbiz/trunk/framework/base/dtd/ofbiz-component.xsd (original)
+++ ofbiz/trunk/framework/base/dtd/ofbiz-component.xsd Mon Dec  2 04:19:48 2013
@@ -198,8 +198,24 @@ under the License.
         <xs:attribute type="xs:string" name="server" use="required"/>
         <xs:attribute type="xs:string" name="location" use="required"/>
         <xs:attribute type="xs:string" name="mount-point"/>
+        <xs:attribute type="xs:string" name="access-permission">
+            <xs:annotation>
+                <xs:documentation>
+                    A user must have this permission to access the application.
+                    When omitted, the application can be used by anyone. This
+                    attribute takes precedence over the base-permission 
attribute -
+                    if both attributes are not empty, this attribute will be 
used.
+                </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
         <xs:attribute type="xs:string" name="base-permission">
-            <xs:annotation><xs:documentation>A user must have ALL of the 
permissions in the list to access the 
application</xs:documentation></xs:annotation>
+            <xs:annotation>
+                <xs:documentation>
+                    Deprecated - use access-permission.
+                    A user must have ALL of the permissions in the list to 
access the application.
+                    When set to "NONE", the application can be used by anyone.
+                </xs:documentation>
+            </xs:annotation>
         </xs:attribute>
         <xs:attribute name="privileged" default="false">
             <xs:simpleType>

Modified: 
ofbiz/trunk/framework/base/src/org/ofbiz/base/component/ComponentConfig.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/component/ComponentConfig.java?rev=1546891&r1=1546890&r2=1546891&view=diff
==============================================================================
--- 
ofbiz/trunk/framework/base/src/org/ofbiz/base/component/ComponentConfig.java 
(original)
+++ 
ofbiz/trunk/framework/base/src/org/ofbiz/base/component/ComponentConfig.java 
Mon Dec  2 04:19:48 2013
@@ -829,6 +829,7 @@ public final class ComponentConfig {
         public final boolean privileged;
         // CatalinaContainer modifies this field.
         private volatile boolean appBarDisplay;
+        private final String accessPermission;
 
         private WebappInfo(ComponentConfig componentConfig, Element element) {
             this.componentConfig = componentConfig;
@@ -872,6 +873,7 @@ public final class ComponentConfig {
             this.appBarDisplay = 
!"false".equals(element.getAttribute("app-bar-display"));
             this.sessionCookieAccepted = 
!"false".equals(element.getAttribute("session-cookie-accepted"));
             this.privileged = 
!"false".equals(element.getAttribute("privileged"));
+            this.accessPermission = element.getAttribute("access-permission");
             String basePermStr = element.getAttribute("base-permission");
             if (!basePermStr.isEmpty()) {
                 this.basePermission = basePermStr.split(",");
@@ -921,6 +923,10 @@ public final class ComponentConfig {
             return this.appBarDisplay;
         }
 
+        public String getAccessPermission() {
+            return this.accessPermission;
+        }
+
         public String[] getBasePermission() {
             return this.basePermission;
         }

Modified: 
ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java?rev=1546891&r1=1546890&r2=1546891&view=diff
==============================================================================
--- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java 
(original)
+++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/LoginWorker.java 
Mon Dec  2 04:19:48 2013
@@ -23,6 +23,8 @@ import static org.ofbiz.base.util.UtilGe
 import java.math.BigInteger;
 import java.security.cert.X509Certificate;
 import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
@@ -1058,35 +1060,70 @@ public class LoginWorker {
                 "Y".equalsIgnoreCase(userLogin.getString("hasLoggedOut")) : 
false);
     }
 
+    /**
+     * Returns <code>true</code> if the specified user is authorized to access 
the specified web application.
+     * @param info
+     * @param security
+     * @param userLogin
+     * @return <code>true</code> if the specified user is authorized to access 
the specified web application
+     */
+    public static boolean hasApplicationPermission(ComponentConfig.WebappInfo 
info, Security security, GenericValue userLogin) {
+        // New authorization attribute takes precedence.
+        String accessPermission = info.getAccessPermission();
+        if (!accessPermission.isEmpty()) {
+            return security.hasPermission(accessPermission, userLogin);
+        }
+        for (String permission: info.getBasePermission()) {
+            if (!"NONE".equals(permission) && 
!security.hasEntityPermission(permission, "_VIEW", userLogin)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     public static boolean hasBasePermission(GenericValue userLogin, 
HttpServletRequest request) {
         Security security = (Security) request.getAttribute("security");
         if (security != null) {
             ServletContext context = (ServletContext) 
request.getAttribute("servletContext");
             String serverId = (String) context.getAttribute("_serverId");
-            
             // get a context path from the request, if it is empty then assume 
it is the root mount point
             String contextPath = request.getContextPath();
             if (UtilValidate.isEmpty(contextPath)) {
                 contextPath = "/";
             }
-            
             ComponentConfig.WebappInfo info = 
ComponentConfig.getWebAppInfo(serverId, contextPath);
             if (info != null) {
-                for (String permission: info.getBasePermission()) {
-                    if (!"NONE".equals(permission) && 
!security.hasEntityPermission(permission, "_VIEW", userLogin)) {
-                        return false;
-                    }
-                }
+                return hasApplicationPermission(info, security, userLogin);
             } else {
                 Debug.logInfo("No webapp configuration found for : " + 
serverId + " / " + contextPath, module);
             }
         } else {
             Debug.logWarning("Received a null Security object from 
HttpServletRequest", module);
         }
-
         return true;
     }
 
+    /**
+     * Returns a <code>Collection</code> of <code>WebappInfo</code> instances 
that the specified
+     * user is authorized to access.
+     * @param security
+     * @param userLogin
+     * @param serverName
+     * @param menuName
+     * @return A <code>Collection</code> <code>WebappInfo</code> instances 
that the specified
+     * user is authorized to access
+     */
+    public static Collection<ComponentConfig.WebappInfo> 
getAppBarWebInfos(Security security, GenericValue userLogin, String serverName, 
String menuName) {
+        Collection<ComponentConfig.WebappInfo> allInfos = 
ComponentConfig.getAppBarWebInfos(serverName, menuName);
+        Collection<ComponentConfig.WebappInfo> allowedInfos = new 
ArrayList<ComponentConfig.WebappInfo>(allInfos.size());
+        for (ComponentConfig.WebappInfo info : allInfos) {
+            if (hasApplicationPermission(info, security, userLogin)) {
+                allowedInfos.add(info);
+            }
+        }
+        return allowedInfos;
+    }
+
     public static Map<String, Object> getUserLoginSession(GenericValue 
userLogin) {
         Delegator delegator = userLogin.getDelegator();
         GenericValue userLoginSession;

Modified: ofbiz/trunk/themes/flatgrey/includes/appbar.ftl
URL: 
http://svn.apache.org/viewvc/ofbiz/trunk/themes/flatgrey/includes/appbar.ftl?rev=1546891&r1=1546890&r2=1546891&view=diff
==============================================================================
--- ofbiz/trunk/themes/flatgrey/includes/appbar.ftl (original)
+++ ofbiz/trunk/themes/flatgrey/includes/appbar.ftl Mon Dec  2 04:19:48 2013
@@ -21,8 +21,8 @@ under the License.
 <#if (externalLoginKey)?exists><#assign externalKeyParam = 
"?externalLoginKey=" + requestAttributes.externalLoginKey?if_exists></#if>
 <#assign ofbizServerName = 
application.getAttribute("_serverId")?default("default-server")>
 <#assign contextPath = request.getContextPath()>
-<#assign displayApps = 
Static["org.ofbiz.base.component.ComponentConfig"].getAppBarWebInfos(ofbizServerName,
 "main")>
-<#assign displaySecondaryApps = 
Static["org.ofbiz.base.component.ComponentConfig"].getAppBarWebInfos(ofbizServerName,
 "secondary")>
+<#assign displayApps = 
Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, 
userLogin, ofbizServerName, "main")>
+<#assign displaySecondaryApps = 
Static["org.ofbiz.webapp.control.LoginWorker"].getAppBarWebInfos(security, 
userLogin, ofbizServerName, "secondary")>
 
 <#if userLogin?has_content>
   <div id="main-navigation">
@@ -31,53 +31,34 @@ under the License.
       <#assign firstApp = true>
       <#list displayApps as display>
         <#assign thisApp = display.getContextRoot()>
-        <#assign permission = true>
         <#assign selected = false>
-        <#assign permissions = display.getBasePermission()>
-        <#list permissions as perm>
-          <#if (perm != "NONE" && !security.hasEntityPermission(perm, "_VIEW", 
session))>
-            <#-- User must have ALL permissions in the base-permission list -->
-            <#assign permission = false>
-          </#if>
-        </#list>
-        <#if permission == true>
-          <#if thisApp == contextPath || contextPath + "/" == thisApp>
-            <#assign selected = true>
-          </#if>
-          <#assign servletPath = 
Static["org.ofbiz.webapp.WebAppUtil"].getControlServletPath(display)>
-          <#assign thisURL = StringUtil.wrapString(servletPath)>
-          <#if thisApp != "/">
-            <#assign thisURL = thisURL + "main">
-          </#if>
-          <#if layoutSettings.suppressTab?exists && display.name == 
layoutSettings.suppressTab>
-            <#-- do not display this component-->
-          <#else>
-            <#if appCount % 4 == 0>
-              <#if firstApp>
-                <li class="first">
-                <#assign firstApp = false>
-              <#else>
-                </li>
-                <li>
-              </#if>
+        <#if thisApp == contextPath || contextPath + "/" == thisApp>
+          <#assign selected = true>
+        </#if>
+        <#assign servletPath = 
Static["org.ofbiz.webapp.WebAppUtil"].getControlServletPath(display)>
+        <#assign thisURL = StringUtil.wrapString(servletPath)>
+        <#if thisApp != "/">
+          <#assign thisURL = thisURL + "main">
+        </#if>
+        <#if layoutSettings.suppressTab?exists && display.name == 
layoutSettings.suppressTab>
+          <#-- do not display this component-->
+        <#else>
+          <#if appCount % 4 == 0>
+            <#if firstApp>
+              <li class="first">
+              <#assign firstApp = false>
+            <#else>
+              </li>
+              <li>
             </#if>
-            <a href="${thisURL}${externalKeyParam}"<#if selected> 
class="selected"</#if><#if uiLabelMap?exists> 
title="${uiLabelMap[display.description]}">${uiLabelMap[display.title]}<#else> 
title="${display.description}">${display.title}</#if></a>
-            <#assign appCount = appCount + 1>
           </#if>
+          <a href="${thisURL}${externalKeyParam}"<#if selected> 
class="selected"</#if><#if uiLabelMap?exists> 
title="${uiLabelMap[display.description]}">${uiLabelMap[display.title]}<#else> 
title="${display.description}">${display.title}</#if></a>
+          <#assign appCount = appCount + 1>
         </#if>
       </#list>
       <#list displaySecondaryApps as display>
-      <#assign thisApp = display.getContextRoot()>
-      <#assign permission = true>
-      <#assign selected = false>
-      <#assign permissions = display.getBasePermission()>
-      <#list permissions as perm>
-        <#if (perm != "NONE" && !security.hasEntityPermission(perm, "_VIEW", 
session))>
-          <#-- User must have ALL permissions in the base-permission list -->
-          <#assign permission = false>
-        </#if>
-      </#list>
-      <#if permission == true>
+        <#assign thisApp = display.getContextRoot()>
+        <#assign selected = false>
         <#if thisApp == contextPath || contextPath + "/" == thisApp>
           <#assign selected = true>
         </#if>
@@ -97,12 +78,11 @@ under the License.
         </#if>
         <a href="${thisURL}${externalKeyParam}"<#if selected> 
class="selected"</#if><#if uiLabelMap?exists> 
title="${uiLabelMap[display.description]}">${uiLabelMap[display.title]}<#else> 
title="${display.description}">${display.title}</#if></a>
         <#assign appCount = appCount + 1>
+      </#list>
+      <#if appCount != 0>
+        </li>
+        <li class="last"></li>
       </#if>
-    </#list>
-    <#if appCount != 0>
-      </li>
-      <li class="last"></li>
-    </#if>
     </ul>
   </div>
 </#if>


Reply via email to