dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #34549
[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;
}
}