← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 17710: support app authorities, app menu is now filtered by accessible apps, user needs all, app-mgmt or...

 

------------------------------------------------------------
revno: 17710
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2014-12-16 14:31:39 +0100
message:
  support app authorities, app menu is now filtered by accessible apps, user needs all, app-mgmt or a specific app authority for an app to be available
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/appmanager/AppManager.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/appmanager/DefaultAppManager.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AppController.java
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/webportal/module/DefaultModuleManager.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/appmanager/AppManager.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/appmanager/AppManager.java	2014-06-16 13:59:43 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/appmanager/AppManager.java	2014-12-16 13:31:39 +0000
@@ -28,6 +28,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import org.hisp.dhis.user.User;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.List;
@@ -51,6 +53,8 @@
      */
     List<App> getApps();
 
+    List<App> getAccessibleApps();
+
     /**
      * Installs the app.
      *
@@ -126,4 +130,8 @@
      * @param appStoreUrl
      */
     void setAppStoreUrl( String appStoreUrl );
+
+    boolean isAccessible( App app );
+
+    boolean isAccessible( App app, User user );
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/appmanager/DefaultAppManager.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/appmanager/DefaultAppManager.java	2014-09-26 06:26:22 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/appmanager/DefaultAppManager.java	2014-12-16 13:31:39 +0000
@@ -28,16 +28,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import javax.annotation.PostConstruct;
-
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.ant.compress.taskdefs.Unzip;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
@@ -45,10 +37,20 @@
 import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.datavalue.DefaultDataValueService;
 import org.hisp.dhis.setting.SystemSettingManager;
+import org.hisp.dhis.user.CurrentUserService;
+import org.hisp.dhis.user.User;
+import org.hisp.dhis.user.UserCredentials;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
+import javax.annotation.PostConstruct;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 
 /**
  * @author Saptarshi Purkayastha
@@ -72,6 +74,9 @@
     @Autowired
     private SystemSettingManager appSettingManager;
 
+    @Autowired
+    private CurrentUserService currentUserService;
+
     // -------------------------------------------------------------------------
     // AppManagerService implementation
     // -------------------------------------------------------------------------
@@ -90,6 +95,25 @@
     }
 
     @Override
+    public List<App> getAccessibleApps()
+    {
+        List<App> applications = new ArrayList<>( getApps() );
+        Iterator<App> iterator = applications.iterator();
+
+        while ( iterator.hasNext() )
+        {
+            App app = iterator.next();
+
+            if ( !isAccessible( app ) )
+            {
+                iterator.remove();
+            }
+        }
+
+        return applications;
+    }
+
+    @Override
     public void installApp( File file, String fileName, String rootPath )
         throws IOException
     {
@@ -99,7 +123,7 @@
         InputStream inputStream = zip.getInputStream( entry );
         ObjectMapper mapper = new ObjectMapper();
         mapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
-        
+
         App app = mapper.readValue( inputStream, App.class );
 
         // ---------------------------------------------------------------------
@@ -178,7 +202,7 @@
 
         return false;
     }
-    
+
     @Override
     public String getAppFolderPath()
     {
@@ -224,7 +248,7 @@
     {
         return StringUtils.trimToNull( (String) appSettingManager.getSystemSetting( KEY_APP_STORE_URL, DEFAULT_APP_STORE_URL ) );
     }
-    
+
     @Override
     public void setAppStoreUrl( String appStoreUrl )
     {
@@ -248,14 +272,17 @@
         if ( null != getAppFolderPath() )
         {
             File appFolderPath = new File( getAppFolderPath() );
+
             if ( appFolderPath.isDirectory() )
             {
                 File[] listFiles = appFolderPath.listFiles();
+
                 for ( File folder : listFiles )
                 {
                     if ( folder.isDirectory() )
                     {
                         File appManifest = new File( folder, "manifest.webapp" );
+
                         if ( appManifest.exists() )
                         {
                             try
@@ -278,4 +305,25 @@
 
         log.info( "Detected apps: " + apps );
     }
+
+    @Override
+    public boolean isAccessible( App app )
+    {
+        return isAccessible( app, currentUserService.getCurrentUser() );
+    }
+
+    @Override
+    public boolean isAccessible( App app, User user )
+    {
+        if ( user == null || user.getUserCredentials() == null || app == null || app.getName() == null )
+        {
+            return false;
+        }
+
+        UserCredentials userCredentials = user.getUserCredentials();
+
+        return userCredentials.getAllAuthorities().contains( "ALL" ) ||
+            userCredentials.getAllAuthorities().contains( "M_dhis-web-maintenance-appmanager" ) ||
+            userCredentials.getAllAuthorities().contains( "See " + app.getName().trim() );
+    }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AppController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AppController.java	2014-11-11 12:51:06 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AppController.java	2014-12-16 13:31:39 +0000
@@ -32,6 +32,7 @@
 import org.hisp.dhis.appmanager.App;
 import org.hisp.dhis.appmanager.AppManager;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
+import org.hisp.dhis.hibernate.exception.ReadAccessDeniedException;
 import org.hisp.dhis.system.util.DateUtils;
 import org.hisp.dhis.webapi.utils.ContextUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -101,7 +102,6 @@
     }
 
     @RequestMapping( value = "/apps/{app}/**", method = RequestMethod.GET )
-    @PreAuthorize( "hasRole('ALL') or hasRole('M_dhis-web-maintenance-appmanager')" )
     public void renderApp( @PathVariable( "app" ) String app, HttpServletRequest request, HttpServletResponse response ) throws IOException
     {
         Iterable<Resource> locations = Lists.newArrayList(
@@ -118,6 +118,12 @@
         }
 
         App application = JacksonUtils.getJsonMapper().readValue( manifest.getInputStream(), App.class );
+
+        if ( application.getName() == null || !appManager.isAccessible( application ) )
+        {
+            throw new ReadAccessDeniedException( "You don't have access to application " + app + "." );
+        }
+
         String pageName = findPage( request.getPathInfo(), app );
 
         // if request was for manifest.webapp, check for * and replace with host

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/webportal/module/DefaultModuleManager.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/webportal/module/DefaultModuleManager.java	2014-10-16 06:17:19 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/webportal/module/DefaultModuleManager.java	2014-12-16 13:31:39 +0000
@@ -28,6 +28,18 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.entities.PackageConfig;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts2.dispatcher.Dispatcher;
+import org.hisp.dhis.appmanager.App;
+import org.hisp.dhis.appmanager.AppManager;
+import org.hisp.dhis.security.ActionAccessResolver;
+import org.hisp.dhis.user.CurrentUserService;
+import org.hisp.dhis.user.User;
+import org.springframework.beans.factory.annotation.Autowired;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -38,17 +50,6 @@
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.struts2.dispatcher.Dispatcher;
-import org.hisp.dhis.appmanager.App;
-import org.hisp.dhis.appmanager.AppManager;
-import org.hisp.dhis.security.ActionAccessResolver;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.opensymphony.xwork2.config.Configuration;
-import com.opensymphony.xwork2.config.entities.PackageConfig;
-
 /**
  * @author Torgeir Lorange Ostby
  * @version $Id: DefaultModuleManager.java 4883 2008-04-12 13:12:54Z larshelg $
@@ -65,7 +66,7 @@
     private Map<String, Module> modulesByNamespace = new HashMap<>();
 
     private List<Module> menuModules = new ArrayList<>();
-    
+
     private ThreadLocal<Module> currentModule = new ThreadLocal<>();
 
     // -------------------------------------------------------------------------
@@ -74,7 +75,10 @@
 
     @Autowired
     private AppManager appManager;
-    
+
+    @Autowired
+    private CurrentUserService currentUserService;
+
     private ActionAccessResolver actionAccessResolver;
 
     public void setActionAccessResolver( ActionAccessResolver actionAccessResolver )
@@ -95,14 +99,14 @@
     {
         this.defaultActionName = defaultActionName;
     }
-    
+
     private Set<String> menuModuleExclusions = new HashSet<>();
-    
+
     public void setMenuModuleExclusions( Set<String> menuModuleExclusions )
     {
         this.menuModuleExclusions = menuModuleExclusions;
     }
-    
+
     // -------------------------------------------------------------------------
     // ModuleManager
     // -------------------------------------------------------------------------
@@ -122,7 +126,7 @@
 
         return modulesByNamespace.get( namespace );
     }
-    
+
     @Override
     public boolean moduleExists( String name )
     {
@@ -141,22 +145,21 @@
     public List<Module> getAccessibleMenuModules()
     {
         detectModules();
-        
+
         return getAccessibleModules( menuModules );
     }
-    
+
     @Override
     public List<Module> getAccessibleMenuModulesAndApps()
     {
         List<Module> modules = getAccessibleMenuModules();
-        
-        List<App> apps = appManager.getApps();
-        
+        List<App> apps = appManager.getAccessibleApps();
+
         for ( App app : apps )
-        {   
+        {
             modules.add( Module.getModule( app ) );
         }
-        
+
         return modules;
     }
 
@@ -167,7 +170,7 @@
 
         return new ArrayList<>( modulesByName.values() );
     }
-    
+
     @Override
     public Module getCurrentModule()
     {
@@ -192,12 +195,12 @@
         }
 
         for ( PackageConfig packageConfig : getPackageConfigs() )
-        {            
+        {
             String name = packageConfig.getName();
             String namespace = packageConfig.getNamespace();
 
             log.debug( "Package config: " + name + ", " + namespace );
-            
+
             if ( packageConfig.getAllActionConfigs().size() == 0 )
             {
                 log.debug( "Ignoring action package with no actions: " + name );
@@ -219,14 +222,14 @@
             {
                 Module module = modulesByNamespace.get( namespace );
 
-                throw new RuntimeException( "These action packages have the same namespace: " + 
+                throw new RuntimeException( "These action packages have the same namespace: " +
                     name + " and " + module.getName() );
             }
 
             Module module = new Module( name, namespace );
             modulesByName.put( name, module );
             modulesByNamespace.put( namespace, module );
-            
+
             boolean include = !menuModuleExclusions.contains( name );
 
             if ( packageConfig.getActionConfigs().containsKey( defaultActionName ) && include )
@@ -246,7 +249,7 @@
         Collections.sort( menuModules, moduleComparator );
 
         log.debug( "Menu modules detected: " + menuModules );
-        
+
         modulesDetected = true;
     }
 
@@ -262,11 +265,11 @@
 
         return packageConfigs.values();
     }
-    
+
     private List<Module> getAccessibleModules( List<Module> modules )
     {
         List<Module> allowed = new ArrayList<>();
-        
+
         for ( Module module : modules )
         {
             if ( module != null && actionAccessResolver.hasAccess( module.getName(), defaultActionName ) )
@@ -274,15 +277,15 @@
                 allowed.add( module );
             }
         }
-        
+
         if ( modules.size() > allowed.size() )
         {
             List<Module> denied = new ArrayList<>( modules );
             denied.removeAll( allowed );
-            
+
             log.debug( "User denied access to modules: " + denied );
         }
-        
+
         return allowed;
     }
 }