Add password when soft deleting an application Will need the password when attempting to restore.
Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/38c7313d Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/38c7313d Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/38c7313d Branch: refs/heads/master Commit: 38c7313dce04550e72e5bac434d831675ad5bf2d Parents: 0632cef Author: Mike Dunker <[email protected]> Authored: Fri Apr 6 16:04:38 2018 -0700 Committer: Keyur Karnik <[email protected]> Committed: Tue Aug 28 16:41:44 2018 -0700 ---------------------------------------------------------------------- .../usergrid/corepersistence/CoreModule.java | 2 + .../ApplicationRestorePasswordService.java | 25 +++++++ .../ApplicationRestorePasswordServiceImpl.java | 72 ++++++++++++++++++++ .../org/apache/usergrid/rest/ApiResponse.java | 7 ++ .../org/apache/usergrid/rest/RootResource.java | 5 +- .../applications/ApplicationResource.java | 37 ++++++++++ 6 files changed, 146 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/38c7313d/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java index 909c073..841e978 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CoreModule.java @@ -181,6 +181,8 @@ public class CoreModule extends AbstractModule { bind( ApplicationService.class ).to( ApplicationServiceImpl.class ); bind( StatusService.class ).to( StatusServiceImpl.class ); + + bind(ApplicationRestorePasswordService.class).to(ApplicationRestorePasswordServiceImpl.class); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/38c7313d/stack/core/src/main/java/org/apache/usergrid/corepersistence/service/ApplicationRestorePasswordService.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/service/ApplicationRestorePasswordService.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/service/ApplicationRestorePasswordService.java new file mode 100644 index 0000000..99ef57d --- /dev/null +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/service/ApplicationRestorePasswordService.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.usergrid.corepersistence.service; + +import java.util.UUID; + +public interface ApplicationRestorePasswordService { + String getApplicationRestorePassword(final UUID applicationId); + void setApplicationRestorePassword(final UUID applicationId, final String restorePassword); + void removeApplicationRestorePassword(final UUID applicationId); +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/38c7313d/stack/core/src/main/java/org/apache/usergrid/corepersistence/service/ApplicationRestorePasswordServiceImpl.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/service/ApplicationRestorePasswordServiceImpl.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/service/ApplicationRestorePasswordServiceImpl.java new file mode 100644 index 0000000..e56bba7 --- /dev/null +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/service/ApplicationRestorePasswordServiceImpl.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.usergrid.corepersistence.service; + +import com.google.common.base.Preconditions; +import com.google.inject.Inject; +import org.apache.commons.lang.StringUtils; +import org.apache.usergrid.corepersistence.util.CpNamingUtils; +import org.apache.usergrid.persistence.map.MapManager; +import org.apache.usergrid.persistence.map.MapManagerFactory; +import org.apache.usergrid.persistence.map.impl.MapScopeImpl; +import org.apache.usergrid.persistence.model.entity.Id; + +import java.util.UUID; + +public class ApplicationRestorePasswordServiceImpl implements ApplicationRestorePasswordService { + private final MapManagerFactory mapManagerFactory; + final static String restorePasswordNamespace = "appRestorePassword"; + final static String passwordKey = "password"; + + @Inject + public ApplicationRestorePasswordServiceImpl(final MapManagerFactory mapManagerFactory) { + this.mapManagerFactory = mapManagerFactory; + } + + private MapManager getMapManager(final UUID applicationId) { + final Id appId = CpNamingUtils.generateApplicationId(applicationId); + return mapManagerFactory.createMapManager(new MapScopeImpl(appId, restorePasswordNamespace)); + } + + @Override + public String getApplicationRestorePassword(final UUID applicationId) { + Preconditions.checkNotNull(applicationId, "app id is null"); + + MapManager mapManager = getMapManager(applicationId); + return mapManager.getString(passwordKey); + + } + + @Override + public void setApplicationRestorePassword(final UUID applicationId, final String restorePassword) { + Preconditions.checkNotNull(applicationId, "app id is null"); + Preconditions.checkArgument(!StringUtils.isEmpty(restorePassword), "restorePassword is empty"); + + MapManager mapManager = getMapManager(applicationId); + mapManager.putString(passwordKey, restorePassword); + + } + + @Override + public void removeApplicationRestorePassword(final UUID applicationId) { + Preconditions.checkNotNull(applicationId, "app id is null"); + + MapManager mapManager = getMapManager(applicationId); + mapManager.delete(passwordKey); + } + +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/38c7313d/stack/rest/src/main/java/org/apache/usergrid/rest/ApiResponse.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/ApiResponse.java b/stack/rest/src/main/java/org/apache/usergrid/rest/ApiResponse.java index 727d187..684e8e1 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/ApiResponse.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/ApiResponse.java @@ -613,9 +613,16 @@ public class ApiResponse { public void setParams( Map<String, List<String>> params ) { + setParams(params, null); + } + + + // provide an ignore list to block custom params + public void setParams( Map<String, List<String>> params, List<String> ignoreList ) { Map<String, List<String>> q = new LinkedHashMap<>(); for ( String k : params.keySet() ) { if (IGNORE_QP.contains(k.toLowerCase())) continue; + if (ignoreList != null && ignoreList.contains(k.toLowerCase())) continue; List<String> v = params.get( k ); if ( v != null ) { q.put( k, new ArrayList<>( v ) ); http://git-wip-us.apache.org/repos/asf/usergrid/blob/38c7313d/stack/rest/src/main/java/org/apache/usergrid/rest/RootResource.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/RootResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/RootResource.java index b8abe54..6a42826 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/RootResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/RootResource.java @@ -134,9 +134,10 @@ public class RootResource extends AbstractContextResource implements MetricProce @JSONP @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) public ApiResponse getAllApplications2( @Context UriInfo ui, - @QueryParam("callback") @DefaultValue("callback") String callback ) + @QueryParam("deleted") @DefaultValue("false") Boolean deleted, + @QueryParam("callback") @DefaultValue("callback") String callback ) throws URISyntaxException { - return getAllApplications( ui, false, callback ); + return getAllApplications( ui, deleted, callback ); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/38c7313d/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/applications/ApplicationResource.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/applications/ApplicationResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/applications/ApplicationResource.java index 79973c3..0eff6b7 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/applications/ApplicationResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/applications/ApplicationResource.java @@ -23,6 +23,7 @@ import org.apache.amber.oauth2.common.exception.OAuthSystemException; import org.apache.amber.oauth2.common.message.OAuthResponse; import org.apache.commons.lang.NullArgumentException; import org.apache.commons.lang.StringUtils; +import org.apache.usergrid.corepersistence.service.ApplicationRestorePasswordService; import org.apache.usergrid.management.ApplicationInfo; import org.apache.usergrid.management.OrganizationInfo; import org.apache.usergrid.management.export.ExportService; @@ -44,6 +45,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; +import org.apache.usergrid.security.shiro.utils.SubjectUtils; import javax.ws.rs.*; import javax.ws.rs.core.Context; @@ -73,6 +75,7 @@ public class ApplicationResource extends AbstractContextResource { private static final Logger logger = LoggerFactory.getLogger(ApplicationResource.class); public static final String CONFIRM_APPLICATION_IDENTIFIER = "confirm_application_identifier"; + public static final String RESTORE_PASSWORD = "restore_password"; //@Autowired //protected ExportService exportService; @@ -465,8 +468,23 @@ public class ApplicationResource extends AbstractContextResource { throw new IllegalArgumentException("Application ID not specified in request"); } + ApplicationRestorePasswordService restorePasswordService = getApplicationRestorePasswordService(); + if (!SubjectUtils.isServiceAdmin()) { + // require password if it exists + String storedRestorePassword = restorePasswordService.getApplicationRestorePassword(applicationId); + if (StringUtils.isNotEmpty(storedRestorePassword)) { + // must have matching password as query parameter + String suppliedRestorePassword = ui.getQueryParameters().getFirst(RESTORE_PASSWORD); + if (!storedRestorePassword.equals(suppliedRestorePassword)) { + throw new IllegalArgumentException("Application cannot be restored without application password"); + } + } + } + management.restoreApplication( applicationId ); + // not deleting password -- will be changed upon successful soft delete + ApiResponse response = createApiResponse(); response.setAction( "restore" ); response.setApplication( emf.getEntityManager( applicationId ).getApplication() ); @@ -505,8 +523,23 @@ public class ApplicationResource extends AbstractContextResource { "Cannot delete application without supplying correct application name"); } + String restorePassword = null; + ApplicationRestorePasswordService restorePasswordService = getApplicationRestorePasswordService(); + if (SubjectUtils.isServiceAdmin()) { + restorePassword = ui.getQueryParameters().getFirst(RESTORE_PASSWORD); + if (StringUtils.isNotEmpty(restorePassword)) { + // save password, required for future undelete if not sysadmin + restorePasswordService.setApplicationRestorePassword(applicationId, restorePassword); + } + } + management.deleteApplication( applicationId ); + if (restorePassword == null) { + // clear restore password + restorePasswordService.removeApplicationRestorePassword(applicationId); + } + if (logger.isTraceEnabled()) { logger.trace("ApplicationResource.delete() deleted appId = {}", applicationId); } @@ -523,4 +556,8 @@ public class ApplicationResource extends AbstractContextResource { return response; } + private ApplicationRestorePasswordService getApplicationRestorePasswordService() { + return injector.getInstance(ApplicationRestorePasswordService.class); + } + }
