Merge authors: Stian Sandvold (stian-sandvold) ------------------------------------------------------------ revno: 20609 [merge] committer: Stian Sandvold <stian.sandv...@gmail.com> branch nick: dhis2 timestamp: Fri 2015-10-09 23:25:13 +0200 message: dataStore now protected with app authorities IF an app has protected its namespace. protecting namespaces can be done by defining the namespace in webapp.manifest: activities.dhis2.namespace; deleting apps now have the option to delete appData associated with the app. modified: dhis-2/dhis-api/src/main/java/org/hisp/dhis/appmanager/AppDhis.java dhis-2/dhis-api/src/main/java/org/hisp/dhis/appmanager/AppManager.java dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValue.java dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueService.java dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueStore.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-api/src/main/java/org/hisp/dhis/webapi/controller/KeyJsonValueController.java dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/java/org/hisp/dhis/appmanager/action/AddAppAction.java dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/java/org/hisp/dhis/appmanager/action/DeleteAppAction.java dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/resources/org/hisp/dhis/appmanager/i18n_module.properties
-- 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/AppDhis.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/appmanager/AppDhis.java 2015-01-17 07:41:26 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/appmanager/AppDhis.java 2015-10-09 17:01:55 +0000 @@ -45,6 +45,9 @@ @JsonProperty( "href" ) private String href; + @JsonProperty( "namespace" ) + private String namespace; + public String getHref() { return href; @@ -54,4 +57,14 @@ { this.href = href; } + + public String getNamespace() + { + return namespace; + } + + public void setNamespace( String namespace ) + { + this.namespace = namespace; + } } \ No newline at end of file === 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 2015-10-06 22:23:53 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/appmanager/AppManager.java 2015-10-09 21:21:12 +0000 @@ -69,7 +69,7 @@ * @param rootPath the root path of the instance. * @throws IOException if the app manifest file could not be read. */ - void installApp( File file, String fileName, String rootPath ) + AppStatus installApp( File file, String fileName, String rootPath ) throws IOException; /** @@ -84,11 +84,12 @@ * Deletes the app with the given name. * * @param name the app name. + * @param deleteAppData decide if associated data in dataStore should be deleted or not. * @return true if the delete was successful, false if there is no app with * the given name or if the app could not be removed from the file * system. */ - boolean deleteApp( String name ); + boolean deleteApp( String name, boolean deleteAppData ); /** * Reload list of apps. @@ -140,4 +141,12 @@ boolean isAccessible( App app ); boolean isAccessible( App app, User user ); + + /** + * Returns the app associated with the namespace, or null if no app is associated. + * @param namespace the namespace to check + * @return App or null + */ + App getAppByNamespace( String namespace); + } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValue.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValue.java 2015-10-01 09:03:27 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValue.java 2015-10-05 10:45:53 +0000 @@ -37,10 +37,19 @@ public class KeyJsonValue extends BaseIdentifiableObject { + /** + * A namespace represents a collection of keys + */ private String namespace; + /** + * A key belongs to a namespace, and represent a value + */ private String key; + /** + * A value referenced by a key and namespace, json-formatted data stored as a string. + */ private String value; @JsonProperty === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueService.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueService.java 2015-10-01 09:03:27 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueService.java 2015-10-05 10:45:53 +0000 @@ -35,17 +35,49 @@ */ public interface KeyJsonValueService { + /** + * Retrieves a list of existing namespaces + * @return a list of strings representing the existing namespaces + */ List<String> getNamespaces(); + /** + * Retrieves a list of keys from a namespace + * @param namespace the namespace to retrieve keys from + * @return a list of strings representing the keys from the namespace + */ List<String> getKeysInNamespace( String namespace ); + /** + * Deletes all keys associated with a given namespace + * @param namespace the namespace to delete + */ void deleteNamespace( String namespace ); + /** + * Retrieves a KeyJsonValue based on a namespace and key + * @param namespace the namespace where the key is associated + * @param key the key referencing the value + * @return the KeyJsonValue matching the key and namespace + */ KeyJsonValue getKeyJsonValue( String namespace, String key ); + /** + * Adds a new KeyJsonValue + * @param keyJsonValue the KeyJsonValue to be stored + * @return the id of the KeyJsonValue stored + */ int addKeyJsonValue( KeyJsonValue keyJsonValue ); + /** + * Updates a KeyJsonValue + * @param keyJsonValue the updated KeyJsonValue + */ void updateKeyJsonValue( KeyJsonValue keyJsonValue ); + /** + * Deletes a keyJsonValue + * @param keyJsonValue the KeyJsonValue to be deleted. + */ void deleteKeyJsonValue( KeyJsonValue keyJsonValue ); } === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueStore.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueStore.java 2015-10-01 10:55:33 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/keyjsonvalue/KeyJsonValueStore.java 2015-10-05 10:45:53 +0000 @@ -38,11 +38,31 @@ public interface KeyJsonValueStore extends GenericIdentifiableObjectStore<KeyJsonValue> { + /** + * Retrieves a list of all namespaces + * @return a list of strings representing each existing namespace + */ List<String> getNamespaces(); + /** + * Retrieves a list of keys associated with a given namespace. + * @param namespace the namespace to retrieve keys from + * @return a list of strings representing the different keys in the namespace + */ List<String> getKeysInNamespace( String namespace ); + /** + * Retrieves a list of KeyJsonValue objects based on a given namespace + * @param namespace the namespace to retrieve KeyJsonValues from + * @return a List of KeyJsonValues + */ List<KeyJsonValue> getKeyJsonValueByNamespace( String namespace ); + /** + * Retrieves a KeyJsonValue based on the associated key and namespace + * @param namespace the namespace where the key is stored + * @param key the key referencing the value + * @return the KeyJsonValue retrieved + */ KeyJsonValue getKeyJsonValue( String namespace, String key ); } === 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 2015-10-06 22:23:53 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/appmanager/DefaultAppManager.java 2015-10-09 21:21:12 +0000 @@ -37,6 +37,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hisp.dhis.datavalue.DefaultDataValueService; +import org.hisp.dhis.keyjsonvalue.KeyJsonValueService; import org.hisp.dhis.setting.Setting; import org.hisp.dhis.setting.SystemSettingManager; import org.hisp.dhis.user.CurrentUserService; @@ -50,7 +51,9 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.function.BiConsumer; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -68,6 +71,11 @@ */ private List<App> apps = new ArrayList<>(); + /** + * Mapping dataStore-namespaces and apps + */ + private HashMap<String, App> appNamespaces = new HashMap<>(); + @PostConstruct private void init() { @@ -80,6 +88,9 @@ @Autowired private CurrentUserService currentUserService; + @Autowired + private KeyJsonValueService keyJsonValueService; + // ------------------------------------------------------------------------- // AppManagerService implementation // ------------------------------------------------------------------------- @@ -120,7 +131,7 @@ } @Override - public void installApp( File file, String fileName, String rootPath ) + public AppStatus installApp( File file, String fileName, String rootPath ) throws IOException { ZipFile zip = new ZipFile( file ); @@ -133,15 +144,26 @@ App app = mapper.readValue( inputStream, App.class ); // --------------------------------------------------------------------- + // Check for namespace and if it's already taken by another app + // --------------------------------------------------------------------- + String appNamespace = app.getActivities().getDhis().getNamespace(); + if ( appNamespace != null && + ( this.appNamespaces.containsKey( appNamespace ) && !app.equals( appNamespaces.get( appNamespace ) ) ) ) + { + return AppStatus.NAMESPACE_TAKEN; + } + + + // --------------------------------------------------------------------- // Delete if app is already installed // --------------------------------------------------------------------- - if ( getApps().contains( app ) ) { String folderPath = getAppFolderPath() + File.separator + app.getFolderName(); FileUtils.forceDelete( new File( folderPath ) ); } + String dest = getAppFolderPath() + File.separator + fileName.substring( 0, fileName.lastIndexOf( '.' ) ); Unzip unzip = new Unzip(); unzip.setSrc( file ); @@ -167,6 +189,8 @@ zip.close(); reloadApps(); // Reload app state + + return AppStatus.OK; } @Override @@ -184,7 +208,7 @@ } @Override - public boolean deleteApp( String name ) + public boolean deleteApp( String name, boolean deleteAppData ) { for ( App app : getApps() ) { @@ -195,6 +219,17 @@ String folderPath = getAppFolderPath() + File.separator + app.getFolderName(); FileUtils.forceDelete( new File( folderPath ) ); + // If deleteAppData is true and a namespace associated with the app exists, delete it. + if(deleteAppData && appNamespaces.containsValue( app )) + { + appNamespaces.forEach( ( namespace, app1 ) -> { + if( app1 == app) + { + keyJsonValueService.deleteNamespace( namespace ); + } + } ); + } + return true; } catch ( IOException ex ) @@ -275,6 +310,7 @@ public void reloadApps() { List<App> appList = new ArrayList<>(); + HashMap<String, App> appNamespaces = new HashMap<>( ); ObjectMapper mapper = new ObjectMapper(); mapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false ); @@ -299,6 +335,13 @@ App app = mapper.readValue( appManifest, App.class ); app.setFolderName( folder.getName() ); appList.add( app ); + + // Add namespace + String appNamespace = app.getActivities().getDhis().getNamespace(); + if ( appNamespace != null ) + { + appNamespaces.put(appNamespace, app); + } } catch ( IOException ex ) { @@ -311,6 +354,7 @@ } this.apps = appList; + this.appNamespaces = appNamespaces; log.info( "Detected apps: " + apps ); } @@ -335,4 +379,10 @@ userCredentials.getAllAuthorities().contains( "M_dhis-web-maintenance-appmanager" ) || userCredentials.getAllAuthorities().contains( "See " + app.getName().trim() ); } + + @Override + public App getAppByNamespace( String namespace ) + { + return appNamespaces.get( namespace ); + } } === 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 2015-10-06 22:23:53 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AppController.java 2015-10-09 21:21:12 +0000 @@ -41,6 +41,7 @@ import org.apache.commons.lang3.StringUtils; import org.hisp.dhis.appmanager.App; import org.hisp.dhis.appmanager.AppManager; +import org.hisp.dhis.appmanager.AppStatus; import org.hisp.dhis.dxf2.render.DefaultRenderService; import org.hisp.dhis.dxf2.render.RenderService; import org.hisp.dhis.dxf2.webmessage.WebMessageException; @@ -91,35 +92,37 @@ private final ResourceLoader resourceLoader = new DefaultResourceLoader(); @RequestMapping( method = RequestMethod.GET, produces = ContextUtils.CONTENT_TYPE_JSON ) - public void getApps( @RequestParam(required=false) String key, HttpServletResponse response ) + public void getApps( @RequestParam( required = false ) String key, HttpServletResponse response ) throws IOException { List<App> apps = new ArrayList<>(); - + if ( key != null ) { App app = appManager.getApp( key ); - + if ( app == null ) { response.sendError( HttpServletResponse.SC_NOT_FOUND ); return; } - + apps.add( app ); } else { apps = appManager.getApps(); } - + renderService.toJson( response.getOutputStream(), apps ); } @RequestMapping( method = RequestMethod.POST ) @ResponseStatus( HttpStatus.NO_CONTENT ) @PreAuthorize( "hasRole('ALL') or hasRole('M_dhis-web-maintenance-appmanager')" ) - public void installApp( @RequestParam( "file" ) MultipartFile file, HttpServletRequest request, HttpServletResponse response ) throws IOException, WebMessageException + public void installApp( @RequestParam( "file" ) MultipartFile file, HttpServletRequest request, + HttpServletResponse response ) + throws IOException, WebMessageException { File tempFile = File.createTempFile( "IMPORT_", "_ZIP" ); file.transferTo( tempFile ); @@ -128,7 +131,14 @@ try { - appManager.installApp( tempFile, file.getOriginalFilename(), contextPath ); + AppStatus appStatus = appManager.installApp( tempFile, file.getOriginalFilename(), contextPath ); + + if ( appStatus.equals( AppStatus.NAMESPACE_TAKEN ) ) + { + throw new WebMessageException( + WebMessageUtils.conflict( "The namespace defined in manifest.webapp is already protected." ) ); + } + } catch ( JsonParseException ex ) { @@ -136,7 +146,8 @@ } catch ( IOException ex ) { - throw new WebMessageException( WebMessageUtils.conflict( "App could not not be installed on file system, check permissions" ) ); + throw new WebMessageException( + WebMessageUtils.conflict( "App could not not be installed on file system, check permissions" ) ); } } @@ -149,7 +160,8 @@ } @RequestMapping( value = "/{app}/**", method = RequestMethod.GET ) - public void renderApp( @PathVariable( "app" ) String app, HttpServletRequest request, HttpServletResponse response ) throws IOException + public void renderApp( @PathVariable( "app" ) String app, HttpServletRequest request, HttpServletResponse response ) + throws IOException { Iterable<Resource> locations = Lists.newArrayList( resourceLoader.getResource( "file:" + appManager.getAppFolderPath() + "/" + app + "/" ), @@ -215,14 +227,15 @@ @RequestMapping( value = "/{app}", method = RequestMethod.DELETE ) @PreAuthorize( "hasRole('ALL') or hasRole('M_dhis-web-maintenance-appmanager')" ) - public void deleteApp( @PathVariable( "app" ) String app, HttpServletRequest request, HttpServletResponse response ) throws WebMessageException + public void deleteApp( @PathVariable( "app" ) String app, @RequestParam(value = "deleteappdata", required = false, defaultValue = "false") boolean deleteAppData, HttpServletRequest request, HttpServletResponse response ) + throws WebMessageException { if ( !appManager.exists( app ) ) { throw new WebMessageException( WebMessageUtils.notFound( "App does not exist: " + app ) ); } - if ( !appManager.deleteApp( app ) ) + if ( !appManager.deleteApp( app, deleteAppData ) ) { throw new WebMessageException( WebMessageUtils.conflict( "There was an error deleting app: " + app ) ); } @@ -231,7 +244,8 @@ @SuppressWarnings( "unchecked" ) @RequestMapping( value = "/config", method = RequestMethod.POST, consumes = ContextUtils.CONTENT_TYPE_JSON ) @PreAuthorize( "hasRole('ALL') or hasRole('M_dhis-web-maintenance-appmanager')" ) - public void setConfig( HttpServletRequest request, HttpServletResponse response ) throws IOException, WebMessageException + public void setConfig( HttpServletRequest request, HttpServletResponse response ) + throws IOException, WebMessageException { Map<String, String> config = renderService.fromJson( request.getInputStream(), Map.class ); @@ -277,7 +291,8 @@ // Helpers //-------------------------------------------------------------------------- - private Resource findResource( Iterable<Resource> locations, String resourceName ) throws IOException + private Resource findResource( Iterable<Resource> locations, String resourceName ) + throws IOException { for ( Resource location : locations ) { === modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/KeyJsonValueController.java' --- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/KeyJsonValueController.java 2015-10-01 10:02:47 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/KeyJsonValueController.java 2015-10-09 17:01:55 +0000 @@ -34,6 +34,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.hisp.dhis.appmanager.App; +import org.hisp.dhis.appmanager.AppManager; import org.hisp.dhis.dxf2.render.RenderService; import org.hisp.dhis.dxf2.webmessage.WebMessage; import org.hisp.dhis.dxf2.webmessage.WebMessageException; @@ -57,6 +59,17 @@ @Autowired private RenderService renderService; + @Autowired + private AppManager appManager; + + /** + * Returns a json-array of strings representing the different namespaces used. + * If no namespace exists, an empty array is returned. + * + * @param response + * @return the list of namespaces + * @throws IOException + */ @RequestMapping( value = "", method = RequestMethod.GET, produces = "application/json" ) public @ResponseBody @@ -66,6 +79,15 @@ return keyJsonValueService.getNamespaces(); } + /** + * Returns a list of strings representing keys in the given namespace. + * + * @param namespace the namespace requested + * @param response + * @return a list of keys + * @throws IOException + * @throws WebMessageException + */ @RequestMapping( value = "/{namespace}", method = RequestMethod.GET, produces = "application/json" ) public @ResponseBody @@ -83,6 +105,14 @@ return keyJsonValueService.getKeysInNamespace( namespace ); } + /** + * Deletes all keys with the given namespace. + * + * @param namespace the namespace to be deleted. + * @param response + * @return + * @throws WebMessageException + */ @RequestMapping( value = "/{namespace}", method = RequestMethod.DELETE ) public @ResponseBody @@ -91,6 +121,11 @@ HttpServletResponse response ) throws WebMessageException { + if ( !hasAccess( namespace ) ) + { + throw new WebMessageException( WebMessageUtils.forbidden( "The namespace '" + namespace + + "' is protected, and you don't have the right authority to access it." ) ); + } if ( !keyJsonValueService.getNamespaces().contains( namespace ) ) { @@ -103,6 +138,16 @@ return WebMessageUtils.ok( "Namespace '" + namespace + "' deleted." ); } + /** + * Retrieves the KeyJsonValue represented by the given key from the given namespace. + * + * @param namespace where the key is associated + * @param key representing the json stored + * @param response + * @return a KeyJsonValue object + * @throws IOException + * @throws WebMessageException + */ @RequestMapping( value = "/{namespace}/{key}", method = RequestMethod.GET, produces = "application/json" ) public @ResponseBody @@ -112,6 +157,12 @@ HttpServletResponse response ) throws IOException, WebMessageException { + if ( !hasAccess( namespace ) ) + { + throw new WebMessageException( WebMessageUtils.forbidden( "The namespace '" + namespace + + "' is protected, and you don't have the right authority to access it." ) ); + } + KeyJsonValue keyJsonValue = keyJsonValueService.getKeyJsonValue( namespace, key ); if ( keyJsonValue == null ) @@ -123,6 +174,17 @@ return keyJsonValue; } + /** + * Creates a new KeyJsonValue Object on the given namespace with the key and value supplied. + * + * @param namespace where the key is associated + * @param key representing the value + * @param body the value to be stored (json format) + * @param response + * @return the object created + * @throws IOException + * @throws WebMessageException + */ @RequestMapping( value = "/{namespace}/{key}", method = RequestMethod.POST, produces = "application/json", consumes = "application/json" ) public @ResponseBody @@ -133,6 +195,12 @@ HttpServletResponse response ) throws IOException, WebMessageException { + if ( !hasAccess( namespace ) ) + { + throw new WebMessageException( WebMessageUtils.forbidden( "The namespace '" + namespace + + "' is protected, and you don't have the right authority to access it." ) ); + } + if ( keyJsonValueService.getKeyJsonValue( namespace, key ) != null ) { throw new WebMessageException( WebMessageUtils @@ -156,6 +224,18 @@ return keyJsonValue; } + /** + * Update a key in the given namespace + * + * @param namespace namespace where the key is associated + * @param key key to be updated + * @param body the new value to be stored + * @param request + * @param response + * @return The updated object + * @throws WebMessageException + * @throws IOException + */ @RequestMapping( value = "/{namespace}/{key}", method = RequestMethod.PUT, produces = "application/json", consumes = "application/json" ) public @ResponseBody @@ -167,6 +247,13 @@ HttpServletResponse response ) throws WebMessageException, IOException { + + if ( !hasAccess( namespace ) ) + { + throw new WebMessageException( WebMessageUtils.forbidden( "The namespace '" + namespace + + "' is protected, and you don't have the right authority to access it." ) ); + } + KeyJsonValue keyJsonValue = keyJsonValueService.getKeyJsonValue( namespace, key ); if ( keyJsonValue == null ) @@ -187,6 +274,15 @@ return keyJsonValue; } + /** + * Delete a key from the given namespace + * + * @param namespace namespace where the key is associated + * @param key key to be deleted + * @param response + * @return the success of the deletion + * @throws WebMessageException + */ @RequestMapping( value = "/{namespace}/{key}", method = RequestMethod.DELETE, produces = "application/json" ) public @ResponseBody @@ -196,6 +292,12 @@ HttpServletResponse response ) throws WebMessageException { + if ( !hasAccess( namespace ) ) + { + throw new WebMessageException( WebMessageUtils.forbidden( "The namespace '" + namespace + + "' is protected, and you don't have the right authority to access it." ) ); + } + KeyJsonValue keyJsonValue = keyJsonValueService.getKeyJsonValue( namespace, key ); if ( keyJsonValue == null ) @@ -208,4 +310,10 @@ return WebMessageUtils.ok( "Key '" + key + "' deleted from namespace '" + namespace + "'." ); } + + private boolean hasAccess( String namespace ) + { + App app = appManager.getAppByNamespace( namespace ); + return app == null || appManager.isAccessible( app ); + } } === modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/java/org/hisp/dhis/appmanager/action/AddAppAction.java' --- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/java/org/hisp/dhis/appmanager/action/AddAppAction.java 2015-06-15 13:44:20 +0000 +++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/java/org/hisp/dhis/appmanager/action/AddAppAction.java 2015-10-09 17:01:55 +0000 @@ -41,6 +41,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.struts2.ServletActionContext; import org.hisp.dhis.appmanager.AppManager; +import org.hisp.dhis.appmanager.AppStatus; import org.hisp.dhis.i18n.I18n; import org.hisp.dhis.commons.util.StreamUtils; import org.hisp.dhis.webapi.utils.ContextUtils; @@ -138,8 +139,14 @@ { String contextPath = ContextUtils.getContextPath( request ); - appManager.installApp( file, fileName, contextPath ); - + AppStatus appStatus = appManager.installApp( file, fileName, contextPath ); + + if(appStatus == AppStatus.NAMESPACE_TAKEN) + { + message = i18n.getString( "appmanager_namespace_taken" ); + log.warn( "Namespace in the app's manifest already taken." ); + return FAILURE; + } message = i18n.getString( "appmanager_install_success" ); return SUCCESS; === modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/java/org/hisp/dhis/appmanager/action/DeleteAppAction.java' --- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/java/org/hisp/dhis/appmanager/action/DeleteAppAction.java 2015-08-18 20:08:20 +0000 +++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/java/org/hisp/dhis/appmanager/action/DeleteAppAction.java 2015-10-09 21:21:12 +0000 @@ -76,7 +76,7 @@ public String execute() throws Exception { - if ( appName != null && appManager.deleteApp( appName ) ) + if ( appName != null && appManager.deleteApp( appName, false ) ) { message = i18n.getString( "appmanager_delete_success" ); } === modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/resources/org/hisp/dhis/appmanager/i18n_module.properties' --- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/resources/org/hisp/dhis/appmanager/i18n_module.properties 2015-08-18 20:08:20 +0000 +++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-appmanager/src/main/resources/org/hisp/dhis/appmanager/i18n_module.properties 2015-10-09 17:01:55 +0000 @@ -20,4 +20,5 @@ appmanager_you_have_no_apps_installed=You have no apps installed at the moment appmanager_author=Author appmanager_version=Version -appmanager_set_to_default=Set to default \ No newline at end of file +appmanager_set_to_default=Set to default +appmanager_namespace_taken=The namespace defined in manifest.webapp is already protected by another app \ No newline at end of file
_______________________________________________ Mailing list: https://launchpad.net/~dhis2-devs Post to : dhis2-devs@lists.launchpad.net Unsubscribe : https://launchpad.net/~dhis2-devs More help : https://help.launchpad.net/ListHelp