dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #40594
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 20609: dataStore now protected with app authorities IF an app has protected its namespace. protecting na...
Merge authors:
Stian Sandvold (stian-sandvold)
------------------------------------------------------------
revno: 20609 [merge]
committer: Stian Sandvold <stian.sandvold@xxxxxxxxx>
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