Repository: usergrid Updated Branches: refs/heads/master 5bca0940d -> ce31acd72
USERGRID-933: refactor org config and add 4 more config items confirm/activate process still has issues with determining org for request, may need to add organization info to token Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/16bcae6e Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/16bcae6e Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/16bcae6e Branch: refs/heads/master Commit: 16bcae6e16d4efea3c8d7b070a44db2c50ff3721 Parents: db26ba7 Author: Mike Dunker <[email protected]> Authored: Wed Dec 30 13:50:31 2015 -0800 Committer: Mike Dunker <[email protected]> Committed: Wed Dec 30 13:50:31 2015 -0800 ---------------------------------------------------------------------- .../main/resources/usergrid-default.properties | 4 + .../corepersistence/CpEntityManagerFactory.java | 2 +- .../corepersistence/util/CpNamingUtils.java | 23 +- .../org/apache/usergrid/utils/MapUtils.java | 6 + .../organizations/OrganizationResource.java | 72 ++++-- .../organizations/users/UsersResource.java | 4 +- .../rest/management/users/UserResource.java | 10 +- .../rest/management/users/UsersResource.java | 6 +- .../usergrid/management/ManagementService.java | 22 +- .../usergrid/management/OrganizationConfig.java | 201 ++++++++++----- .../management/OrganizationConfigProps.java | 45 ++++ .../cassandra/ManagementServiceImpl.java | 242 ++++++++++++------- .../cassandra/OrganizationConfigPropsImpl.java | 109 +++++++++ .../migration/AppInfoMigrationPluginTest.java | 2 +- .../apache/usergrid/management/EmailFlowIT.java | 9 +- .../management/OrganizationConfigIT.java | 109 +++++++++ .../usergrid/management/OrganizationIT.java | 4 +- .../cassandra/ManagementServiceIT.java | 2 +- .../management/importer/ImportServiceIT.java | 2 +- .../security/providers/FacebookProviderIT.java | 2 +- .../providers/PingIdentityProviderIT.java | 2 +- 21 files changed, 675 insertions(+), 203 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/config/src/main/resources/usergrid-default.properties ---------------------------------------------------------------------- diff --git a/stack/config/src/main/resources/usergrid-default.properties b/stack/config/src/main/resources/usergrid-default.properties index 7b80a23..1f8b7c9 100644 --- a/stack/config/src/main/resources/usergrid-default.properties +++ b/stack/config/src/main/resources/usergrid-default.properties @@ -594,6 +594,10 @@ usergrid.version.build=${version} # usergrid.auth.cache.time-to-live=3600 +# Default connection types to return for an entity (fewer connection types increases performance) +# none, in (only connections inbound to the entity), out (only connections outbound from the entity), +# all (= in + out)' +usergrid.rest.default-connection-param=all http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java index a38324a..0613f62 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java @@ -166,7 +166,7 @@ public class CpEntityManagerFactory implements EntityManagerFactory, Application if ( em.getApplication() == null ) { logger.info("Creating management application"); Map mgmtAppProps = new HashMap<String, Object>(); - mgmtAppProps.put(PROPERTY_NAME, "systemapp"); + mgmtAppProps.put(PROPERTY_NAME, CassandraService.MANAGEMENT_APPLICATION); em.create( getManagementAppId(), TYPE_APPLICATION, mgmtAppProps); em.getApplication(); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/core/src/main/java/org/apache/usergrid/corepersistence/util/CpNamingUtils.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/util/CpNamingUtils.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/util/CpNamingUtils.java index 55bc49a..3ebab39 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/util/CpNamingUtils.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/util/CpNamingUtils.java @@ -24,6 +24,7 @@ import java.util.UUID; import org.apache.usergrid.persistence.core.scope.ApplicationScope; import org.apache.usergrid.persistence.core.scope.ApplicationScopeImpl; import org.apache.usergrid.persistence.entities.Application; +import org.apache.usergrid.persistence.entities.Group; import org.apache.usergrid.persistence.graph.Edge; import org.apache.usergrid.persistence.graph.SearchByEdge; import org.apache.usergrid.persistence.graph.SearchByEdgeType; @@ -270,12 +271,32 @@ public class CpNamingUtils { /** + * Generate an entity Id from the given UUID + * + * @param entityId the entity's UUID + */ + public static Id generateEntityId( UUID entityId, String entityType ) { + return new SimpleId( entityId, entityType ); + } + + + /** * Generate an applicationId from the given UUID * * @param applicationId the applicationId */ public static Id generateApplicationId( UUID applicationId ) { - return new SimpleId( applicationId, Application.ENTITY_TYPE ); + return generateEntityId( applicationId, Application.ENTITY_TYPE ); + } + + + /** + * Generate an organizationId from the given UUID + * + * @param organizationId the organizationId + */ + public static Id generateOrganizationId( UUID organizationId ) { + return generateEntityId( organizationId, Group.ENTITY_TYPE ); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/core/src/main/java/org/apache/usergrid/utils/MapUtils.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/utils/MapUtils.java b/stack/core/src/main/java/org/apache/usergrid/utils/MapUtils.java index 12da2e0..37df8ed 100644 --- a/stack/core/src/main/java/org/apache/usergrid/utils/MapUtils.java +++ b/stack/core/src/main/java/org/apache/usergrid/utils/MapUtils.java @@ -269,6 +269,12 @@ public class MapUtils extends org.apache.commons.collections.MapUtils { } + public static <S, T> Map<String, Object> toStringObjectMap(Map<S, T> map) { + Map<String, Object> newMap = new HashMap<>(); + map.forEach((k,v) -> newMap.put(k.toString(), v)); + return newMap; + } + public static <S, T> HashMapBuilder<S, T> hashMap( S key, T value ) { return new HashMapBuilder<S, T>().map( key, value ); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationResource.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationResource.java index 12fbc63..a70f766 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationResource.java @@ -51,9 +51,7 @@ import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; import static javax.servlet.http.HttpServletResponse.*; import static javax.ws.rs.core.MediaType.APPLICATION_JSON; @@ -364,28 +362,51 @@ public class OrganizationResource extends AbstractContextResource { } + protected Set<String> getSetFromCommaSeparatedString(String input) { + Set<String> ret = new HashSet<>(); + StringTokenizer tokenizer = new StringTokenizer(input, ","); + + while (tokenizer.hasMoreTokens()) { + ret.add(tokenizer.nextToken()); + } + + return ret; + } + + + protected Map<String, Object> getConfigData(OrganizationConfig orgConfig, String itemsParam, + boolean includeDefaults, boolean includeOverrides) { + boolean itemsParamEmpty = itemsParam == null || itemsParam.isEmpty() || itemsParam.equals("*"); + return orgConfig.getOrgConfigCustomMap(itemsParamEmpty ? null : getSetFromCommaSeparatedString(itemsParam), + includeDefaults, includeOverrides); + } + + @JSONP @RequireSystemAccess @GET @Path("config") public ApiResponse getConfig( @Context UriInfo ui, - @QueryParam("callback") @DefaultValue("callback") String callback ) + @QueryParam("items") @DefaultValue("") String itemsParam, + @QueryParam("separate_defaults") @DefaultValue("false") boolean separateDefaults, + @QueryParam("callback") @DefaultValue("callback") String callback ) throws Exception { logger.info( "Get configuration for organization: " + organization.getUuid() ); - // TODO: check for super user, @RequireSystemAccess didn't work - ApiResponse response = createApiResponse(); response.setAction( "get organization configuration" ); - - // TODO: check for super user + //response.setParams(ui.getQueryParameters()); OrganizationConfig orgConfig = management.getOrganizationConfigByUuid( organization.getUuid() ); - response.setProperty( "configuration", management.getOrganizationConfigData( orgConfig ) ); - // response.setOrganizationConfig( orgConfig ); + if (separateDefaults) { + response.setProperty("orgConfiguration", getConfigData(orgConfig, itemsParam, false, true)); + response.setProperty("defaults", getConfigData(orgConfig, itemsParam, true, false)); + } else { + response.setProperty("configuration", getConfigData(orgConfig, itemsParam, true, true)); + } return response; } @@ -396,27 +417,42 @@ public class OrganizationResource extends AbstractContextResource { @JSONP @PUT @Path("config") - public ApiResponse putConfig( @Context UriInfo ui, Map<String, Object> json, - @QueryParam("callback") @DefaultValue("callback") String callback ) + public ApiResponse putConfig( @Context UriInfo ui, + Map<String, Object> json, + @QueryParam("separate_defaults") @DefaultValue("false") boolean separateDefaults, + @QueryParam("only_changed") @DefaultValue("false") boolean onlyChanged, + @QueryParam("callback") @DefaultValue("callback") String callback ) throws Exception { logger.debug("Put configuration for organization: " + organization.getUuid()); ApiResponse response = createApiResponse(); response.setAction("put organization configuration"); - - // TODO: check for super user - - // response.setParams(ui.getQueryParameters()); + //response.setParams(ui.getQueryParameters()); OrganizationConfig orgConfig = management.getOrganizationConfigByUuid( organization.getUuid() ); - orgConfig.addProperties(json); + + // validates JSON and throws IllegalArgumentException if invalid + // exception will be handled up the chain + orgConfig.addProperties(json, true); + management.updateOrganizationConfig(orgConfig); // refresh orgConfig -- to pick up removed entries and defaults orgConfig = management.getOrganizationConfigByUuid( organization.getUuid() ); - response.setProperty( "configuration", management.getOrganizationConfigData( orgConfig ) ); + + String itemsToReturn = ""; + if (onlyChanged) { + itemsToReturn = String.join(",", json.keySet()); + } + + if (separateDefaults) { + response.setProperty("orgConfiguration", getConfigData(orgConfig, itemsToReturn, false, true)); + response.setProperty("defaults", getConfigData(orgConfig, itemsToReturn, true, false)); + } else { + response.setProperty( "configuration", getConfigData(orgConfig, itemsToReturn, true, true)); + } return response; } http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/users/UsersResource.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/users/UsersResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/users/UsersResource.java index d0dfbdb..c308bdd 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/users/UsersResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/users/UsersResource.java @@ -129,11 +129,11 @@ public class UsersResource extends AbstractContextResource { } if ( user == null ) { - user = management.createAdminUser( username, name, email, password, false, false ); + user = management.createAdminUser( organization.getUuid(), username, name, email, password, false, false ); // A null may be returned if the user fails validation check if ( user != null ) { - management.startAdminUserPasswordResetFlow( user ); + management.startAdminUserPasswordResetFlow( organization.getUuid(), user ); } } http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java index 037121b..320c18e 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java @@ -280,7 +280,7 @@ public class UserResource extends AbstractContextResource { } if ( !useReCaptcha() ) { - management.startAdminUserPasswordResetFlow( user ); + management.startAdminUserPasswordResetFlow( null, user ); return handleViewable( "resetpw_email_success", this ); } @@ -291,7 +291,7 @@ public class UserResource extends AbstractContextResource { reCaptcha.checkAnswer( httpServletRequest.getRemoteAddr(), challenge, uresponse ); if ( reCaptchaResponse.isValid() ) { - management.startAdminUserPasswordResetFlow( user ); + management.startAdminUserPasswordResetFlow( null, user ); return handleViewable( "resetpw_email_success", this ); } else { @@ -337,7 +337,7 @@ public class UserResource extends AbstractContextResource { } try { - management.handleActivationTokenForAdminUser( user.getUuid(), token ); + management.handleActivationTokenForAdminUser( null, user.getUuid(), token ); return handleViewable( "activate", this ); } catch ( TokenException e ) { @@ -366,7 +366,7 @@ public class UserResource extends AbstractContextResource { } try { - ActivationState state = management.handleConfirmationTokenForAdminUser( user.getUuid(), token ); + ActivationState state = management.handleConfirmationTokenForAdminUser( null, user.getUuid(), token ); if ( state == ActivationState.CONFIRMED_AWAITING_ACTIVATION ) { return handleViewable( "confirm", this ); } @@ -404,7 +404,7 @@ public class UserResource extends AbstractContextResource { ApiResponse response = createApiResponse(); - management.startAdminUserActivationFlow( user ); + management.startAdminUserActivationFlow( null, user ); response.setAction( "reactivate user" ); return response; http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java index 6136139..33b6990 100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java @@ -89,7 +89,7 @@ public class UsersResource extends AbstractContextResource { private UserResource getUserResource(UserInfo user, String type, String value) throws ManagementException { if (user == null) { - throw new ManagementException("Could not find organization for " + type + " : " + value); + throw new ManagementException("Could not find user for " + type + " : " + value); } return getSubResource(UserResource.class).init( user ); } @@ -125,7 +125,7 @@ public class UsersResource extends AbstractContextResource { ApiResponse response = createApiResponse(); response.setAction( "create user" ); - UserInfo user = management.createAdminUser( username, name, email, password, false, false ); + UserInfo user = management.createAdminUser( null, username, name, email, password, false, false ); Map<String, Object> result = new LinkedHashMap<String, Object>(); if ( user != null ) { result.put( "user", user ); @@ -199,7 +199,7 @@ public class UsersResource extends AbstractContextResource { if (reCaptchaPassed) { user = management.findAdminUser(email); if (user != null) { - management.startAdminUserPasswordResetFlow(user); + management.startAdminUserPasswordResetFlow(null, user); return handleViewable("resetpw_email_success", this); } else { errorMsg = "We don't recognize that email, try again..."; http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java b/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java index cf2924b..950f7e0 100644 --- a/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java +++ b/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java @@ -50,23 +50,23 @@ public interface ManagementService { public AccessInfo authorizeClient( String clientId, String clientSecret, long ttl ) throws Exception; - public ActivationState handleConfirmationTokenForAdminUser( UUID userId, String token ) throws Exception; + public ActivationState handleConfirmationTokenForAdminUser( UUID organizationId, UUID userId, String token ) throws Exception; - public ActivationState handleActivationTokenForAdminUser( UUID userId, String token ) throws Exception; + public ActivationState handleActivationTokenForAdminUser( UUID organizationId, UUID userId, String token ) throws Exception; public ActivationState handleActivationTokenForOrganization( UUID organizationId, String token ) throws Exception; public boolean checkPasswordResetTokenForAdminUser( UUID userId, String token ) throws Exception; - public UserInfo createAdminUser( String username, String name, String email, String password, boolean activated, - boolean disabled ) throws Exception; + public UserInfo createAdminUser( UUID organizationId, String username, String name, String email, String password, + boolean activated, boolean disabled ) throws Exception; - public UserInfo createAdminUser( String username, String name, String email, String password, boolean activated, - boolean disabled, Map<String, Object> userProperties ) throws Exception; + public UserInfo createAdminUser( UUID organizationId, String username, String name, String email, String password, + boolean activated, boolean disabled, Map<String, Object> userProperties ) throws Exception; - public UserInfo createAdminFrom( User user, String password ) throws Exception; + public UserInfo createAdminFrom( UUID organizationId, User user, String password ) throws Exception; - public UserInfo createAdminFromPrexistingPassword( User user, CredentialsInfo ci ) throws Exception; + public UserInfo createAdminFromPrexistingPassword( UUID organizationId, User user, CredentialsInfo ci ) throws Exception; public ApplicationInfo createApplication( UUID organizationId, String applicationName ) throws Exception; public ApplicationInfo createApplication( UUID organizationId, String applicationName, @@ -233,11 +233,11 @@ public interface ManagementService { public void removeOrganizationApplication( UUID organizationId, UUID applicationId ) throws Exception; - public void startAdminUserActivationFlow( UserInfo user ) throws Exception; + public void startAdminUserActivationFlow( UUID organizationId, UserInfo user ) throws Exception; public void sendAdminUserEmail( UserInfo user, String subject, String html ) throws Exception; - public void startAdminUserPasswordResetFlow( UserInfo user ) throws Exception; + public void startAdminUserPasswordResetFlow( UUID organizationId, UserInfo user ) throws Exception; public void startOrganizationActivationFlow( OrganizationInfo organization ) throws Exception; @@ -357,8 +357,6 @@ public interface ManagementService { public OrganizationConfig getOrganizationConfigByUuid( UUID id ) throws Exception; - public Map<String, Object> getOrganizationConfigData( OrganizationConfig organizationConfig ) throws Exception; - public OrganizationConfig getOrganizationConfigForApplication( UUID applicationId ) throws Exception; public void updateOrganizationConfig( OrganizationConfig organizationConfig ) throws Exception; http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/main/java/org/apache/usergrid/management/OrganizationConfig.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/OrganizationConfig.java b/stack/services/src/main/java/org/apache/usergrid/management/OrganizationConfig.java index 0fe775b..9c063c6 100644 --- a/stack/services/src/main/java/org/apache/usergrid/management/OrganizationConfig.java +++ b/stack/services/src/main/java/org/apache/usergrid/management/OrganizationConfig.java @@ -17,96 +17,185 @@ package org.apache.usergrid.management; -import java.util.Map; -import java.util.UUID; +import com.sun.org.apache.xpath.internal.operations.Bool; +import org.apache.usergrid.utils.MapUtils; -import static org.apache.usergrid.persistence.Schema.PROPERTY_PATH; -import static org.apache.usergrid.persistence.Schema.PROPERTY_UUID; +import java.util.*; +import static org.apache.commons.lang.StringUtils.defaultIfEmpty; +import static org.apache.commons.lang.StringUtils.isBlank; -public class OrganizationConfig { - - public static final String DEFAULT_CONNECTION_PARAM_PROPERTY = "defaultConnectionParam"; - private static final String DEFAULT_CONNECTION_PARAM_DEFAULT_VALUE = "all"; - - private static final String [] propertyNames = { - DEFAULT_CONNECTION_PARAM_PROPERTY - }; - private static final String [] defaultValues = { - DEFAULT_CONNECTION_PARAM_DEFAULT_VALUE - }; +public class OrganizationConfig { + private Map<String, String> defaultProperties; private UUID id; private String name; - private Map<String, Object> properties; + private Map<String, String> orgProperties; - public OrganizationConfig() { + // shouldn't use the default constructor + private OrganizationConfig() { } - - public OrganizationConfig(UUID id, String name) { + public OrganizationConfig(OrganizationConfigProps configFileProperties, UUID id, String name) { + defaultProperties = configFileProperties.getPropertyMap(); this.id = id; this.name = name; + this.orgProperties = new HashMap<>(); } + public OrganizationConfig(OrganizationConfigProps configFileProperties) { + this(configFileProperties, null, null); + } + + private void orgPropertyValidate(Map<String, Object> entityProperties) throws IllegalArgumentException { + Set<String> entityPropertyKeys = new HashSet<>(entityProperties.keySet()); + entityPropertyKeys.removeAll(defaultProperties.keySet()); + // if anything remains in the key set, it is not a valid property + if (entityPropertyKeys.size() > 0) { + throw new IllegalArgumentException("Invalid organization config keys: " + String.join(", ", entityPropertyKeys)); + } - public OrganizationConfig(Map<String, Object> properties) { - id = ( UUID ) properties.get( PROPERTY_UUID ); - name = ( String ) properties.get( PROPERTY_PATH ); + entityProperties.forEach((k,v) -> { + if (!v.getClass().equals(String.class)) { + throw new IllegalArgumentException("Organization config values must be strings."); + } + }); } + private void addOrgProperties(Map<String, Object> newOrgProperties) { + newOrgProperties.forEach((k,v) -> { + // only take valid properties, validation (if required) happened earlier + if (defaultProperties.containsKey(k)) { + // ignore non-strings, validation happened earlier + if (v.getClass().equals(String.class)) { + this.orgProperties.put(k, v.toString()); + } + } + }); + } + + public OrganizationConfig(OrganizationConfigProps configFileProperties, UUID id, String name, + Map<Object, Object> newOrgProperties, boolean validateOrgProperties) + throws IllegalArgumentException { + this(configFileProperties, id, name); + + Map<String, Object> orgPropertiesMap = MapUtils.toStringObjectMap(newOrgProperties); - public OrganizationConfig(UUID id, String name, Map<String, Object> properties) { - this( id, name ); - this.properties = properties; + // entityPropertyValidate will throw IllegalArgumentException + if (validateOrgProperties) { + orgPropertyValidate(orgPropertiesMap); + } - // add default values to properties map - addDefaultsToProperties(); + addOrgProperties(orgPropertiesMap); } - private void addDefaultsToProperties() { - for (int i=0; i < propertyNames.length; i++) { - if (!properties.containsKey(propertyNames[i])) { - properties.put(propertyNames[i], defaultValues[i]); - } + // adds supplied properties to existing properties + public void addProperties(Map<String, Object> newOrgProperties, boolean validateOrgProperties) + throws IllegalArgumentException { + + // entityPropertyValidate will throw IllegalArgumentException if invalid + if (validateOrgProperties) { + orgPropertyValidate(newOrgProperties); } + + // don't clear properties map -- these overwrite/add to existing + addOrgProperties(newOrgProperties); } + public Map<String, Object> getOrgConfigCustomMap(Set<String> items, boolean includeDefaults, boolean includeOverrides) { + Map<String, Object> map = new HashMap<>(); + + if (includeDefaults) { + map.putAll(defaultProperties); + } + + if (includeOverrides) { + map.putAll(orgProperties); + } + + if (items != null) { + // filter out properties not specified + map.keySet().retainAll(items); + } + + return map; + } + + public Map<String, Object> getOrgConfigMap() { + return getOrgConfigCustomMap(null, true, true); + } + + public Map<String, Object> getOrgConfigOverridesMap() { + return getOrgConfigCustomMap(null, false, true); + } + + public Map<String, Object> getOrgConfigDefaultsMap() { + return getOrgConfigCustomMap(null, false, true); + } + + // only include specified items + public Map<String, Object> getFilteredOrgConfigMap(Set<String> items) { + return getOrgConfigCustomMap(items, true, true); + } + + public Map<String, Object> getFilteredOrgConfigOverridesMap(Set<String> items) { + return getOrgConfigCustomMap(items, false, true); + } + + public Map<String, Object> getFilteredOrgConfigDefaultsMap(Set<String> items) { + return getOrgConfigCustomMap(items, false, true); + } + + public String getProperty(String key) { + String retValue = null; + if (orgProperties != null) { + retValue = orgProperties.get(key); + } + return retValue != null ? retValue : defaultProperties.get(key); + } + + public String getProperty(String name, String defaultValue) { + String retValue = getProperty(name); + return retValue != null ? retValue : defaultValue; + } + + public boolean isProperty(String name, boolean defaultValue) { + String val = getProperty(name); + return isBlank(val) ? defaultValue : Boolean.parseBoolean(val); + } + + public int intProperty(String name, int defaultValue) { + String val = getProperty(name); + return isBlank(val) ? defaultValue : Integer.parseInt(val); + } + + public long longProperty(String name, long defaultValue) { + String val = getProperty(name); + return isBlank(val) ? defaultValue : Long.parseLong(val); + } public UUID getUuid() { return id; } - public void setUuid( UUID id ) { this.id = id; } - public String getName() { return name; } - public void setName( String name ) { this.name = name; } - public String getDefaultConnectionParam() { - String defaultParam = DEFAULT_CONNECTION_PARAM_DEFAULT_VALUE; - if ( properties != null ) { - Object paramValue = properties.get( DEFAULT_CONNECTION_PARAM_PROPERTY ); - if ( paramValue instanceof String ) { - defaultParam = ( String ) paramValue; - } - } - return defaultParam; + return getProperty(OrganizationConfigProps.PROPERTIES_DEFAULT_CONNECTION_PARAM); } - @Override public int hashCode() { final int prime = 31; @@ -116,7 +205,6 @@ public class OrganizationConfig { return result; } - @Override public boolean equals( Object obj ) { if ( this == obj ) { @@ -145,26 +233,7 @@ public class OrganizationConfig { else if ( !name.equals( other.name ) ) { return false; } - return true; - } - - - public Map<String, Object> getProperties() { - return properties; - } - - - public void setProperties( Map<String, Object> properties ) { - this.properties = properties; - - // add default values to properties map - addDefaultsToProperties(); + return getOrgConfigMap().equals(other.getOrgConfigMap()); } - public void addProperties( Map<String, Object> properties ) { - this.properties.putAll(properties); - - // add default values to properties map - addDefaultsToProperties(); - } } http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/main/java/org/apache/usergrid/management/OrganizationConfigProps.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/OrganizationConfigProps.java b/stack/services/src/main/java/org/apache/usergrid/management/OrganizationConfigProps.java new file mode 100644 index 0000000..577e1d6 --- /dev/null +++ b/stack/services/src/main/java/org/apache/usergrid/management/OrganizationConfigProps.java @@ -0,0 +1,45 @@ +/* + * 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.management; + +import java.util.Map; +import java.util.Set; + +public interface OrganizationConfigProps { + String PROPERTIES_DEFAULT_CONNECTION_PARAM = "usergrid.rest.default-connection-param"; + String PROPERTIES_ADMIN_SYSADMIN_EMAIL = AccountCreationProps.PROPERTIES_ADMIN_SYSADMIN_EMAIL; + String PROPERTIES_ADMIN_ACTIVATION_URL = AccountCreationProps.PROPERTIES_ADMIN_ACTIVATION_URL; + String PROPERTIES_ADMIN_CONFIRMATION_URL = AccountCreationProps.PROPERTIES_ADMIN_CONFIRMATION_URL; + String PROPERTIES_ADMIN_RESETPW_URL = AccountCreationProps.PROPERTIES_ADMIN_RESETPW_URL; + + Set<String> getPropertyNames(); + + Map<String, String> getPropertyMap(); + + String getProperty(String name); + + String getProperty(String name, String defaultValue); + + boolean isProperty(String name, boolean defaultValue); + + int intProperty(String name, int defaultValue); + + long longProperty(String name, long defaultValue); + + void setProperty(String name, String value); + +} http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java index 5ffe830..61beeb7 100644 --- a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java +++ b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java @@ -142,6 +142,8 @@ public class ManagementServiceImpl implements ManagementService { protected AccountCreationPropsImpl properties; + protected OrganizationConfigPropsImpl orgConfigProperties; + protected LockManager lockManager; protected TokenService tokens; @@ -174,11 +176,10 @@ public class ManagementServiceImpl implements ManagementService { @Autowired public void setProperties( Properties properties ) { this.properties = new AccountCreationPropsImpl( properties ); - - + this.orgConfigProperties = new OrganizationConfigPropsImpl( properties ); } - String orgSysAdminEmail,defaultSysAdminEmail,adminSysAdminEmail; + String orgSysAdminEmail,defaultSysAdminEmail; private String getDefaultSysAdminEmail(){ defaultSysAdminEmail = defaultSysAdminEmail != null ? defaultSysAdminEmail @@ -194,13 +195,43 @@ public class ManagementServiceImpl implements ManagementService { return orgSysAdminEmail; } - private String getAdminSystemEmail(){ - if( adminSysAdminEmail != null ){ - return adminSysAdminEmail; + String defaultAdminSysAdminEmail = null; + private String getDefaultAdminSystemEmail(){ + if( defaultAdminSysAdminEmail == null ){ + defaultAdminSysAdminEmail = properties.getProperty(PROPERTIES_ADMIN_SYSADMIN_EMAIL, getDefaultSysAdminEmail()); + } + + return defaultAdminSysAdminEmail; + } + + private String getAdminSystemEmailForApplication(UUID applicationId) { + String adminSystemEmail = null; + try { + OrganizationConfig orgConfig = getOrganizationConfigForApplication(applicationId); + if (orgConfig != null) { + adminSystemEmail = orgConfig.getProperty(PROPERTIES_ADMIN_SYSADMIN_EMAIL); + } + } + catch (Exception e) { + // swallow + } + + return adminSystemEmail != null ? adminSystemEmail : getDefaultAdminSystemEmail(); + } + + private String getAdminSystemEmailForOrganization(UUID organizationId) { + String adminSystemEmail = null; + try { + OrganizationConfig orgConfig = getOrganizationConfigByUuid(organizationId); + if (orgConfig != null) { + adminSystemEmail = orgConfig.getProperty(PROPERTIES_ADMIN_SYSADMIN_EMAIL); + } } - adminSysAdminEmail = properties.getProperty( PROPERTIES_ADMIN_SYSADMIN_EMAIL ); - adminSysAdminEmail = adminSysAdminEmail!=null ? adminSysAdminEmail : getDefaultSysAdminEmail(); - return adminSysAdminEmail; + catch (Exception e) { + // swallow + } + + return adminSystemEmail != null ? adminSystemEmail : getDefaultAdminSystemEmail(); } @@ -303,7 +334,7 @@ public class ManagementServiceImpl implements ManagementService { if ( !anyNull( superuser_username, superuser_email, superuser_password ) ) { UserInfo user = this.getAdminUserByUsername( superuser_username ); if ( user == null ) { - createAdminUser( superuser_username, "Super User", superuser_email, superuser_password, + createAdminUser( null, superuser_username, "Super User", superuser_email, superuser_password, superuser_enabled, !superuser_enabled ); } else { @@ -324,7 +355,7 @@ public class ManagementServiceImpl implements ManagementService { UserInfo user = this.getAdminUserByUsername( username ); if ( user == null ) { try { - createAdminUser( username, "Super User", email, password, true, false ); + createAdminUser( null, username, "Super User", email, password, true, false ); }catch(Exception e){ } @@ -466,10 +497,10 @@ public class ManagementServiceImpl implements ManagementService { return null; } if ( areActivationChecksDisabled() ) { - user = createAdminUserInternal( username, name, email, password, true, false, userProperties ); + user = createAdminUserInternal( null, username, name, email, password, true, false, userProperties ); } else { - user = createAdminUserInternal( username, name, email, password, activated, disabled, userProperties ); + user = createAdminUserInternal( null, username, name, email, password, activated, disabled, userProperties ); } logger.debug("User created"); @@ -793,7 +824,7 @@ public class ManagementServiceImpl implements ManagementService { } - private UserInfo doCreateAdmin( User user, CredentialsInfo userPassword, CredentialsInfo mongoPassword ) + private UserInfo doCreateAdmin( UUID organizationId, User user, CredentialsInfo userPassword, CredentialsInfo mongoPassword ) throws Exception { writeUserToken( smf.getManagementAppId(), user, encryptionService @@ -812,7 +843,7 @@ public class ManagementServiceImpl implements ManagementService { // special case for sysadmin and test account only if ( !user.getEmail().equals( properties.getProperty( PROPERTIES_SYSADMIN_LOGIN_EMAIL ) ) && !user.getEmail().equals( properties .getProperty( PROPERTIES_TEST_ACCOUNT_ADMIN_USER_EMAIL ) ) ) { - this.startAdminUserActivationFlow( userInfo ); + this.startAdminUserActivationFlow( organizationId, userInfo ); } return userInfo; @@ -820,9 +851,9 @@ public class ManagementServiceImpl implements ManagementService { @Override - public UserInfo createAdminFromPrexistingPassword( User user, CredentialsInfo ci ) throws Exception { + public UserInfo createAdminFromPrexistingPassword( UUID organizationId, User user, CredentialsInfo ci ) throws Exception { - return doCreateAdmin( user, ci, + return doCreateAdmin( organizationId, user, ci, // we can't actually set the mongo password. We never have the plain text in // this path encryptionService.plainTextCredentials( mongoPassword( user.getUsername(), "" ), user.getUuid(), @@ -831,8 +862,8 @@ public class ManagementServiceImpl implements ManagementService { @Override - public UserInfo createAdminFrom( User user, String password ) throws Exception { - return doCreateAdmin(user, + public UserInfo createAdminFrom( UUID organizationId, User user, String password ) throws Exception { + return doCreateAdmin(organizationId, user, encryptionService.defaultEncryptedCredentials(password, user.getUuid(), smf.getManagementAppId()), encryptionService.plainTextCredentials(mongoPassword(user.getUsername(), password), user.getUuid(), smf.getManagementAppId())); @@ -840,20 +871,20 @@ public class ManagementServiceImpl implements ManagementService { @Override - public UserInfo createAdminUser( String username, String name, String email, String password, boolean activated, + public UserInfo createAdminUser( UUID organizationId, String username, String name, String email, String password, boolean activated, boolean disabled ) throws Exception { - return createAdminUser(username, name, email, password, activated, disabled, null); + return createAdminUser(organizationId, username, name, email, password, activated, disabled, null); } @Override - public UserInfo createAdminUser( String username, String name, String email, String password, boolean activated, + public UserInfo createAdminUser( UUID organizationId, String username, String name, String email, String password, boolean activated, boolean disabled, Map<String, Object> userProperties ) throws Exception { if ( !validateAdminInfo(username, name, email, password) ) { return null; } - return createAdminUserInternal( username, name, email, password, activated, disabled, userProperties ); + return createAdminUserInternal( organizationId, username, name, email, password, activated, disabled, userProperties ); } @@ -881,7 +912,7 @@ public class ManagementServiceImpl implements ManagementService { } - private UserInfo createAdminUserInternal( String username, String name, String email, String password, + private UserInfo createAdminUserInternal( UUID organizationId, String username, String name, String email, String password, boolean activated, boolean disabled, Map<String, Object> userProperties ) throws Exception { logger.info( "createAdminUserInternal: {}", username ); @@ -910,7 +941,7 @@ public class ManagementServiceImpl implements ManagementService { } user = em.create( user ); - return createAdminFrom( user, password ); + return createAdminFrom( organizationId, user, password ); } @@ -2225,15 +2256,19 @@ public class ManagementServiceImpl implements ManagementService { @Override - public void startAdminUserPasswordResetFlow( UserInfo user ) throws Exception { + public void startAdminUserPasswordResetFlow( UUID organizationId, UserInfo user ) throws Exception { String token = getPasswordResetTokenForAdminUser( user.getUuid(), 0 ); + String resetPropertyUrl = organizationId != null ? + getOrganizationConfigPropertyByUuid(organizationId, PROPERTIES_ADMIN_RESETPW_URL) : + getOrganizationConfigPropertyForUserInfo(user, PROPERTIES_ADMIN_RESETPW_URL); + String reset_url = - String.format( properties.getProperty( PROPERTIES_ADMIN_RESETPW_URL ), user.getUuid().toString() ) + String.format( resetPropertyUrl, user.getUuid().toString() ) + "?token=" + token; Map<String, String> pageContext = hashMap( "reset_url", reset_url ) - .map( "reset_url_base", properties.getProperty( PROPERTIES_ADMIN_RESETPW_URL ) ) + .map( "reset_url_base", resetPropertyUrl ) .map( "user_uuid", user.getUuid().toString() ).map( "raw_token", token ); @@ -2265,7 +2300,7 @@ public class ManagementServiceImpl implements ManagementService { } if ( newOrganizationsNeedSysAdminApproval() ) { logger.info( "sending SysAdminApproval confirmation email: {}", organization.getName() ); - //TODO: add org email approval + //TODO: org shouldn't approve org activation, right? sendHtmlMail( properties, getOrgSystemEmail(), properties.getProperty( PROPERTIES_MAILER_EMAIL ), "Request For Organization Account Activation " + organization.getName(), appendEmailFooter( @@ -2329,7 +2364,7 @@ public class ManagementServiceImpl implements ManagementService { organization_owners = ( organization_owners == null ) ? user.getHTMLDisplayEmailAddress() : organization_owners + ", " + user.getHTMLDisplayEmailAddress(); } - //TODO: org email + //TODO: email for org admin or sysadmin? sendHtmlMail( properties, getOrgSystemEmail(), properties.getProperty( PROPERTIES_MAILER_EMAIL ), "Organization Account Activated " + organization.getName(), appendEmailFooter( emailMsg( @@ -2351,18 +2386,18 @@ public class ManagementServiceImpl implements ManagementService { @Override - public void startAdminUserActivationFlow( UserInfo user ) throws Exception { + public void startAdminUserActivationFlow( UUID organizationId, UserInfo user ) throws Exception { if ( user.isActivated() ) { - sendAdminUserConfirmationEmail( user ); + sendAdminUserConfirmationEmail( organizationId, user ); sendAdminUserActivatedEmail( user ); - sendSysAdminNewAdminActivatedNotificationEmail( user ); + sendSysAdminNewAdminActivatedNotificationEmail( organizationId, user ); } else { if ( newAdminUsersRequireConfirmation() ) { - sendAdminUserConfirmationEmail( user ); + sendAdminUserConfirmationEmail( organizationId, user ); } else if ( newAdminUsersNeedSysAdminApproval() ) { - sendSysAdminRequestAdminActivationEmail( user ); + sendSysAdminRequestAdminActivationEmail( organizationId, user ); } else { // sdg: There seems to be a hole in the logic. The user has been @@ -2375,20 +2410,20 @@ public class ManagementServiceImpl implements ManagementService { @Override - public ActivationState handleConfirmationTokenForAdminUser( UUID userId, String token ) throws Exception { + public ActivationState handleConfirmationTokenForAdminUser( UUID organizationId, UUID userId, String token ) throws Exception { AuthPrincipalInfo principal = getPrincipalFromAccessToken( token, TOKEN_TYPE_CONFIRM, ADMIN_USER ); if ( ( principal != null ) && userId.equals( principal.getUuid() ) ) { UserInfo user = getAdminUserByUuid( principal.getUuid() ); confirmAdminUser( user.getUuid() ); if ( newAdminUsersNeedSysAdminApproval() ) { sendAdminUserConfirmedAwaitingActivationEmail( user ); - sendSysAdminRequestAdminActivationEmail(user); + sendSysAdminRequestAdminActivationEmail(organizationId, user); return ActivationState.CONFIRMED_AWAITING_ACTIVATION; } else { activateAdminUser( principal.getUuid() ); sendAdminUserActivatedEmail( user ); - sendSysAdminNewAdminActivatedNotificationEmail( user ); + sendSysAdminNewAdminActivatedNotificationEmail( organizationId, user ); return ActivationState.ACTIVATED; } } @@ -2397,48 +2432,55 @@ public class ManagementServiceImpl implements ManagementService { @Override - public ActivationState handleActivationTokenForAdminUser( UUID userId, String token ) throws Exception { + public ActivationState handleActivationTokenForAdminUser( UUID organizationId, UUID userId, String token ) throws Exception { AuthPrincipalInfo principal = getPrincipalFromAccessToken( token, TOKEN_TYPE_ACTIVATION, ADMIN_USER ); if ( ( principal != null ) && userId.equals( principal.getUuid() ) ) { activateAdminUser( principal.getUuid() ); UserInfo user = getAdminUserByUuid( principal.getUuid() ); sendAdminUserActivatedEmail( user ); - sendSysAdminNewAdminActivatedNotificationEmail(user); + sendSysAdminNewAdminActivatedNotificationEmail(organizationId, user); return ActivationState.ACTIVATED; } return ActivationState.UNKNOWN; } - public void sendAdminUserConfirmationEmail( UserInfo user ) throws Exception { + public void sendAdminUserConfirmationEmail( UUID organizationId, UserInfo user ) throws Exception { String token = getConfirmationTokenForAdminUser(user.getUuid(), 0); + String adminActivationUrlTemplate = organizationId != null ? + getOrganizationConfigPropertyByUuid(organizationId, PROPERTIES_ADMIN_CONFIRMATION_URL) : + getOrganizationConfigPropertyForUserInfo(user, PROPERTIES_ADMIN_CONFIRMATION_URL); String confirmation_url = - String.format( properties.getProperty( PROPERTIES_ADMIN_CONFIRMATION_URL ), user.getUuid().toString() ) + String.format( adminActivationUrlTemplate, user.getUuid().toString() ) + "?token=" + token; sendAdminUserEmail( user, "User Account Confirmation: " + user.getEmail(), - emailMsg( hashMap( "user_email", user.getEmail() ).map( "confirmation_url", confirmation_url ), + emailMsg( hashMap( "confirm_email", user.getEmail() ).map( "confirmation_url", confirmation_url ), PROPERTIES_EMAIL_ADMIN_CONFIRMATION ) ); } - public void sendSysAdminRequestAdminActivationEmail( UserInfo user ) throws Exception { + public void sendSysAdminRequestAdminActivationEmail( UUID organizationId, UserInfo user ) throws Exception { String token = getActivationTokenForAdminUser(user.getUuid(), 0); //TODO: admin specific email + String activationUrlTemplate = organizationId != null ? + getOrganizationConfigPropertyByUuid(organizationId, PROPERTIES_ADMIN_ACTIVATION_URL) : + getOrganizationConfigPropertyForUserInfo(user, PROPERTIES_ADMIN_ACTIVATION_URL); String activation_url = - String.format( properties.getProperty( PROPERTIES_ADMIN_ACTIVATION_URL ), user.getUuid().toString() ) - + "?token=" + token; - sendHtmlMail(properties, getAdminSystemEmail(), - properties.getProperty(PROPERTIES_MAILER_EMAIL), + String.format( activationUrlTemplate, user.getUuid().toString() ) + "?token=" + token; + String adminSystemEmail = organizationId != null ? getAdminSystemEmailForOrganization(organizationId) : + getAdminSystemEmailForApplication(user.getApplicationId()); + sendHtmlMail(properties, adminSystemEmail, properties.getProperty(PROPERTIES_MAILER_EMAIL), "Request For Admin User Account Activation " + user.getEmail(), appendEmailFooter( emailMsg(hashMap("user_email", user.getEmail()).map("activation_url", activation_url), PROPERTIES_EMAIL_SYSADMIN_ADMIN_ACTIVATION))); } - public void sendSysAdminNewAdminActivatedNotificationEmail( UserInfo user ) throws Exception { + public void sendSysAdminNewAdminActivatedNotificationEmail( UUID organizationId, UserInfo user ) throws Exception { if ( properties.notifySysAdminOfNewAdminUsers() ) { - sendHtmlMail( properties, getAdminSystemEmail(), - properties.getProperty( PROPERTIES_MAILER_EMAIL ), + String adminSystemEmail = organizationId != null ? getAdminSystemEmailForOrganization(organizationId) : + getAdminSystemEmailForApplication(user.getApplicationId()); + sendHtmlMail( properties, adminSystemEmail, properties.getProperty( PROPERTIES_MAILER_EMAIL ), "Admin User Account Activated " + user.getEmail(), appendEmailFooter( emailMsg( hashMap( "user_email", user.getEmail() ), PROPERTIES_EMAIL_SYSADMIN_ADMIN_ACTIVATED ) ) ); } @@ -2608,10 +2650,10 @@ public class ManagementServiceImpl implements ManagementService { @Override public void startAppUserPasswordResetFlow( UUID applicationId, User user ) throws Exception { String token = getPasswordResetTokenForAppUser(applicationId, user.getUuid()); - String reset_url = - buildUserAppUrl( applicationId, properties.getProperty( PROPERTIES_USER_RESETPW_URL ), user, token ); + String resetPropertyUrl = getOrganizationConfigPropertyForApplication(applicationId, PROPERTIES_USER_RESETPW_URL); + String reset_url = buildUserAppUrl( applicationId, resetPropertyUrl, user, token ); Map<String, String> pageContext = hashMap( "reset_url", reset_url ) - .map( "reset_url_base", properties.getProperty( PROPERTIES_ADMIN_RESETPW_URL ) ) + .map( "reset_url_base", resetPropertyUrl ) .map( "user_uuid", user.getUuid().toString() ).map( "raw_token", token ) .map( "application_id", applicationId.toString() ); /* @@ -3145,20 +3187,21 @@ public class ManagementServiceImpl implements ManagementService { return Boolean.parseBoolean(obj); } + private OrganizationConfig getOrganizationConfigDefaultsOnly() throws Exception { + return new OrganizationConfig(orgConfigProperties); + } + @Override public OrganizationConfig getOrganizationConfigByName( String organizationName ) throws Exception { - if ( organizationName == null ) { - return null; + if ( organizationName == null || organizationName.equals("management")) { + return getOrganizationConfigDefaultsOnly(); } EntityManager em = emf.getEntityManager(smf.getManagementAppId()); EntityRef ref = em.getAlias( Group.ENTITY_TYPE, organizationName ); - if ( ref == null ) { - return null; - } - return getOrganizationConfigByUuid( ref.getUuid() ); + return ref != null ? getOrganizationConfigByUuid(ref.getUuid()) : getOrganizationConfigDefaultsOnly(); } @@ -3168,56 +3211,85 @@ public class ManagementServiceImpl implements ManagementService { EntityManager em = emf.getEntityManager( smf.getManagementAppId() ); Entity entity = em.get( new SimpleEntityRef( Group.ENTITY_TYPE, id ) ); if ( entity == null ) { - return null; + return getOrganizationConfigDefaultsOnly(); } - Map properties = em.getDictionaryAsMap( entity, ORGANIZATION_CONFIG_DICTIONARY ); - OrganizationConfig orgConfig = new OrganizationConfig( entity.getProperties() ); - orgConfig.setProperties( properties ); - return orgConfig; + Map<Object, Object> entityProperties = em.getDictionaryAsMap(entity, ORGANIZATION_CONFIG_DICTIONARY); + return new OrganizationConfig( orgConfigProperties, + (UUID)entity.getProperty(PROPERTY_UUID), + (String)entity.getProperty(PROPERTY_PATH), + entityProperties, false); } - @Override - public Map<String, Object> getOrganizationConfigData( OrganizationConfig organizationConfig ) throws Exception { + private OrganizationConfig getOrganizationConfigForUserInfo(UserInfo user) throws Exception { + UUID userApp = user.getApplicationId(); + + if (userApp == CpNamingUtils.MANAGEMENT_APPLICATION_ID) { + Map<UUID, String> organizations = getOrganizationsForAdminUser(user.getUuid()); + if (organizations != null) { + Iterator<UUID> iter = organizations.keySet().iterator(); + if (iter.hasNext()) { + return getOrganizationConfigByUuid(iter.next()); + } + } + } else { + // if user is not an admin, use associated application + return getOrganizationConfigForApplication(userApp); + } + + // return default + return getOrganizationConfigDefaultsOnly(); + } + + + private String getOrganizationConfigPropertyForUserInfo(UserInfo user, String key) throws Exception { + return getOrganizationConfigForUserInfo(user).getProperty(key); + } + + + private String getOrganizationConfigPropertyForApplication(UUID applicationId, String key) throws Exception { + return getOrganizationConfigForApplication(applicationId).getProperty(key); + } - Map<String, Object> jsonOrganizationConfig = new HashMap<>(); - jsonOrganizationConfig.putAll( JsonUtils.toJsonMap( organizationConfig.getProperties() ) ); - return jsonOrganizationConfig; + private String getOrganizationConfigPropertyByUuid(UUID organizationId, String key) throws Exception { + return getOrganizationConfigByUuid(organizationId).getProperty(key); } @Override public OrganizationConfig getOrganizationConfigForApplication( UUID applicationInfoId ) throws Exception { - if ( applicationInfoId == null ) { - return null; - } + if ( applicationInfoId != null && applicationInfoId != CpNamingUtils.MANAGEMENT_APPLICATION_ID) { - final EntityManager em = emf.getEntityManager( smf.getManagementAppId() ); + final EntityManager em = emf.getEntityManager( smf.getManagementAppId() ); - Results r = em.getSourceEntities( - new SimpleEntityRef(CpNamingUtils.APPLICATION_INFO, applicationInfoId), - ORG_APP_RELATIONSHIP, Group.ENTITY_TYPE, Level.ALL_PROPERTIES); + Results r = em.getSourceEntities( + new SimpleEntityRef(CpNamingUtils.APPLICATION_INFO, applicationInfoId), + ORG_APP_RELATIONSHIP, Group.ENTITY_TYPE, Level.ALL_PROPERTIES); - Entity entity = r.getEntity(); + Entity entity = r.getEntity(); + + if ( entity != null ) { + Map<Object, Object> entityProperties = em.getDictionaryAsMap(entity, ORGANIZATION_CONFIG_DICTIONARY); + return new OrganizationConfig(orgConfigProperties, entity.getUuid(), entity.getName(), entityProperties, false); + } - if ( entity != null ) { - Map properties = em.getDictionaryAsMap(entity, ORGANIZATION_CONFIG_DICTIONARY); - return new OrganizationConfig(entity.getUuid(), entity.getName(), properties); } - return null; + // return the defaults + return new OrganizationConfig(orgConfigProperties); } @Override public void updateOrganizationConfig( OrganizationConfig organizationConfig ) throws Exception { - Map<String, Object> properties = organizationConfig.getProperties(); - if ( properties != null ) { + // get only the overrides + Map<String, Object> orgConfigProperties = organizationConfig.getOrgConfigOverridesMap(); + if ( orgConfigProperties != null ) { EntityRef organizationEntity = new SimpleEntityRef( Group.ENTITY_TYPE, organizationConfig.getUuid() ); EntityManager em = emf.getEntityManager( smf.getManagementAppId() ); - for ( Map.Entry<String, Object> entry : properties.entrySet() ) { + for ( Map.Entry<String, Object> entry : orgConfigProperties.entrySet() ) { if ( "".equals( entry.getValue() ) ) { em.removeFromDictionary( organizationEntity, ORGANIZATION_CONFIG_DICTIONARY, entry.getKey() ); } else { http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/main/java/org/apache/usergrid/management/cassandra/OrganizationConfigPropsImpl.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/OrganizationConfigPropsImpl.java b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/OrganizationConfigPropsImpl.java new file mode 100644 index 0000000..7063507 --- /dev/null +++ b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/OrganizationConfigPropsImpl.java @@ -0,0 +1,109 @@ +/* + * 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.management.cassandra; + + +import org.apache.usergrid.management.OrganizationConfigProps; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +import static org.apache.commons.lang.StringUtils.isBlank; + + +public class OrganizationConfigPropsImpl implements OrganizationConfigProps { + private static final Logger logger = LoggerFactory.getLogger( OrganizationConfigPropsImpl.class ); + + private static final String DEFAULT_CONNECTION_PARAM_DEFAULTVALUE = "all"; + private static final String ADMIN_SYSADMIN_EMAIL_DEFAULTVALUE = null; // null will fall back to system level admin + private static final String ADMIN_ACTIVATION_URL_DEFAULTVALUE = ""; // should be configured in properties file + private static final String ADMIN_CONFIRMATION_URL_DEFAULTVALUE = ""; // should be configured in properties file + private static final String ADMIN_RESETPW_URL_DEFAULTVALUE = ""; // should be configured in properties file + + private static final Map<String, String> noConfigDefaults = new HashMap<>(); + static { + noConfigDefaults.put(PROPERTIES_DEFAULT_CONNECTION_PARAM, DEFAULT_CONNECTION_PARAM_DEFAULTVALUE); + noConfigDefaults.put(PROPERTIES_ADMIN_SYSADMIN_EMAIL, ADMIN_SYSADMIN_EMAIL_DEFAULTVALUE); + noConfigDefaults.put(PROPERTIES_ADMIN_ACTIVATION_URL, ADMIN_ACTIVATION_URL_DEFAULTVALUE); + noConfigDefaults.put(PROPERTIES_ADMIN_CONFIRMATION_URL, ADMIN_CONFIRMATION_URL_DEFAULTVALUE); + noConfigDefaults.put(PROPERTIES_ADMIN_RESETPW_URL, ADMIN_RESETPW_URL_DEFAULTVALUE); + } + + //protected final Properties properties; + protected final Map<String, String> map; + + public OrganizationConfigPropsImpl(Properties properties) { + map = new HashMap<>(); + noConfigDefaults.forEach((k,v) -> map.put(k, properties.getProperty(k, v))); + } + + public Set<String> getPropertyNames() { + return new HashSet<>(noConfigDefaults.keySet()); + } + + public Map<String, String> getPropertyMap() { + return new HashMap<>(map); + } + + public String getProperty(String name) { + String propertyValue = map.get(name); + if (isBlank(propertyValue)) { + logger.warn("Missing value for " + name); + propertyValue = null; + } + return propertyValue; + } + + + public String getProperty(String name, String defaultValue) { + return map.getOrDefault(name, defaultValue); + } + + + public boolean isProperty(String name, boolean defaultValue) { + String val = getProperty(name); + if (isBlank(val)) { + return defaultValue; + } else { + return Boolean.parseBoolean(val); + } + } + + public int intProperty(String name, int defaultValue) { + String val = getProperty(name); + if (isBlank(val)) { + return defaultValue; + } else { + return Integer.parseInt(val); + } + } + + public long longProperty(String name, long defaultValue) { + String val = getProperty(name); + if (isBlank(val)) { + return defaultValue; + } else { + return Long.parseLong(val); + } + } + + public void setProperty(String name, String value) { + map.put(name,value); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java b/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java index ef97188..cad9cca 100644 --- a/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java +++ b/stack/services/src/test/java/org/apache/usergrid/corepersistence/migration/AppInfoMigrationPluginTest.java @@ -120,7 +120,7 @@ public class AppInfoMigrationPluginTest { List<Entity> deletedApps = new ArrayList<>(); setup.getEmf().initializeApplicationV2( - CassandraService.DEFAULT_ORGANIZATION, AppInfoMigrationPlugin.SYSTEM_APP_ID, "systemapp", null); + CassandraService.DEFAULT_ORGANIZATION, AppInfoMigrationPlugin.SYSTEM_APP_ID, CassandraService.MANAGEMENT_APPLICATION, null); EntityManager systemAppEm = setup.getEmf().getEntityManager( AppInfoMigrationPlugin.SYSTEM_APP_ID ); http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/test/java/org/apache/usergrid/management/EmailFlowIT.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/management/EmailFlowIT.java b/stack/services/src/test/java/org/apache/usergrid/management/EmailFlowIT.java index 3d14c2f..2ba7b19 100644 --- a/stack/services/src/test/java/org/apache/usergrid/management/EmailFlowIT.java +++ b/stack/services/src/test/java/org/apache/usergrid/management/EmailFlowIT.java @@ -104,7 +104,8 @@ public class EmailFlowIT { LOG.info( token ); assertEquals( ActivationState.ACTIVATED, - setup.getMgmtSvc().handleConfirmationTokenForAdminUser( org_owner.owner.getUuid(), token ) ); + setup.getMgmtSvc().handleConfirmationTokenForAdminUser( org_owner.getOrganization().getUuid(), + org_owner.owner.getUuid(), token ) ); Message activation = inbox.get( 1 ); assertEquals( "User Account Activated", activation.getSubject() ); @@ -144,7 +145,8 @@ public class EmailFlowIT { LOG.info( token ); ActivationState state = - setup.getMgmtSvc().handleConfirmationTokenForAdminUser( org_owner.owner.getUuid(), token ); + setup.getMgmtSvc().handleConfirmationTokenForAdminUser( org_owner.getOrganization().getUuid(), + org_owner.owner.getUuid(), token ); assertEquals( ActivationState.CONFIRMED_AWAITING_ACTIVATION, state ); confirmation = user_inbox.get( 1 ); @@ -164,7 +166,8 @@ public class EmailFlowIT { token = getTokenFromMessage( activation ); LOG.info( token ); - state = setup.getMgmtSvc().handleActivationTokenForAdminUser( org_owner.owner.getUuid(), token ); + state = setup.getMgmtSvc().handleActivationTokenForAdminUser( org_owner.getOrganization().getUuid(), + org_owner.owner.getUuid(), token ); assertEquals( ActivationState.ACTIVATED, state ); Message activated = user_inbox.get( 2 ); http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/test/java/org/apache/usergrid/management/OrganizationConfigIT.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/management/OrganizationConfigIT.java b/stack/services/src/test/java/org/apache/usergrid/management/OrganizationConfigIT.java new file mode 100644 index 0000000..36243b6 --- /dev/null +++ b/stack/services/src/test/java/org/apache/usergrid/management/OrganizationConfigIT.java @@ -0,0 +1,109 @@ +/* + * 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.management; + + +import org.apache.usergrid.NewOrgAppAdminRule; +import org.apache.usergrid.ServiceITSetup; +import org.apache.usergrid.ServiceITSetupImpl; +import org.apache.usergrid.cassandra.ClearShiroSubject; +import org.apache.usergrid.corepersistence.util.CpNamingUtils; +import org.apache.usergrid.management.cassandra.ManagementServiceImpl; +import org.apache.usergrid.management.cassandra.OrganizationConfigPropsImpl; +import org.apache.usergrid.management.exceptions.RecentlyUsedPasswordException; +import org.apache.usergrid.persistence.index.utils.MapUtils; +import org.apache.usergrid.security.AuthPrincipalInfo; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; + +import java.util.*; + +import static org.apache.usergrid.TestHelper.*; +import static org.junit.Assert.*; + + +public class OrganizationConfigIT { + + @Rule + public ClearShiroSubject clearShiroSubject = new ClearShiroSubject(); + + @ClassRule + public static ServiceITSetup setup = new ServiceITSetupImpl(); + + @Rule + public NewOrgAppAdminRule newOrgAppAdminRule = new NewOrgAppAdminRule( setup ); + + @Test + public void testCreateOrganizationConfig() throws Exception { + + final String orgName = uniqueOrg(); + + UserInfo user = setup.getMgmtSvc().createAdminUser(null, uniqueUsername(), "Org Config Admin", uniqueEmail(), "test", true, false ); + assertNotNull( user ); + + OrganizationInfo org = setup.getMgmtSvc().createOrganization( orgName, user, true ); + assertNotNull( org ); + + setup.getEmf().getEntityManager( setup.getSmf().getManagementAppId() ); + + OrganizationConfig orgConfig = setup.getMgmtSvc().getOrganizationConfigByUuid(org.getUuid()); + assertNotNull(orgConfig); + + // until something added to it, returned orgConfig should match the values in the default + + // empty org config with default properties from config file + OrganizationConfigProps configProps = new OrganizationConfigPropsImpl(setup.getMgmtSvc().getProperties()); + Map<Object, Object> emptyConfigProps = new HashMap<>(); + + OrganizationConfig orgConfigDefault = new OrganizationConfig( configProps, org.getUuid(), org.getName(), emptyConfigProps, false ); + assertTrue(orgConfig.equals(orgConfigDefault)); + + // insert a config value for the org + Map<String, Object> propMap = new HashMap<>(); + String testKey = OrganizationConfigProps.PROPERTIES_ADMIN_RESETPW_URL; + String testValue = "***TEST VALUE***"; + propMap.put(testKey, testValue); + orgConfig.addProperties(propMap, false); + setup.getMgmtSvc().updateOrganizationConfig(orgConfig); + + setup.getEmf().getEntityManager( setup.getSmf().getManagementAppId() ); + + // get org config again + OrganizationConfig orgConfigUpdated = setup.getMgmtSvc().getOrganizationConfigByUuid(org.getUuid()); + assertNotNull(orgConfigUpdated); + String updatedValue = orgConfigUpdated.getProperty(testKey); + assertTrue(updatedValue.equals(testValue)); + + // delete the config entry by setting it to "" + propMap.put(testKey, ""); + orgConfigUpdated.addProperties(propMap, false); + setup.getMgmtSvc().updateOrganizationConfig(orgConfigUpdated); + + setup.getEmf().getEntityManager( setup.getSmf().getManagementAppId() ); + + // get org config again, should match defaults + OrganizationConfig orgConfigReset = setup.getMgmtSvc().getOrganizationConfigByUuid(org.getUuid()); + assertNotNull(orgConfigReset); + assertTrue(orgConfigReset.equals(orgConfigDefault)); + } + + @Test + public void testOrganizationConfigInvalidKeys() throws Exception { + // TODO: add test + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java b/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java index b48fd77..9d20dcb 100644 --- a/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java +++ b/stack/services/src/test/java/org/apache/usergrid/management/OrganizationIT.java @@ -116,7 +116,7 @@ public class OrganizationIT { assertEquals( organization.getOwner().getUuid(), principal.getUuid() ); UserInfo new_user = setup.getMgmtSvc() - .createAdminUser(uniqueUsername(), "Test User", uniqueEmail(), + .createAdminUser( organization2.getUuid(), uniqueUsername(), "Test User", uniqueEmail(), "testpassword", true, true ); assertNotNull( new_user ); @@ -132,7 +132,7 @@ public class OrganizationIT { UserInfo user = setup.getMgmtSvc() - .createAdminUser( uniqueUsername(), "Ed Anuff", uniqueEmail(), passwords[0], true, false ); + .createAdminUser(null, uniqueUsername(), "Ed Anuff", uniqueEmail(), passwords[0], true, false ); assertNotNull( user ); OrganizationInfo organization = setup.getMgmtSvc().createOrganization( uniqueOrg(), user, true ); http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java b/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java index ad2ce66..83b8465 100644 --- a/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java +++ b/stack/services/src/test/java/org/apache/usergrid/management/cassandra/ManagementServiceIT.java @@ -474,7 +474,7 @@ public class ManagementServiceIT { String password = "test"; UserInfo adminUser = setup.getMgmtSvc() - .createAdminUser( username, "Todd Nine",uniqueEmail(), password, + .createAdminUser( null, username, "Todd Nine",uniqueEmail(), password, false, false ); EntityManager em = setup.getEmf().getEntityManager( setup.getSmf().getManagementAppId() ); http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/test/java/org/apache/usergrid/management/importer/ImportServiceIT.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/management/importer/ImportServiceIT.java b/stack/services/src/test/java/org/apache/usergrid/management/importer/ImportServiceIT.java index 7dc075c..b5c02fc 100644 --- a/stack/services/src/test/java/org/apache/usergrid/management/importer/ImportServiceIT.java +++ b/stack/services/src/test/java/org/apache/usergrid/management/importer/ImportServiceIT.java @@ -101,7 +101,7 @@ public class ImportServiceIT { } //creates sample test application - adminUser = setup.getMgmtSvc().createAdminUser( + adminUser = setup.getMgmtSvc().createAdminUser( null, username, username, username+"@test.com", username, false, false ); organization = setup.getMgmtSvc().createOrganization( username, adminUser, true ); applicationId = setup.getMgmtSvc().createApplication( organization.getUuid(), username+"app" ).getId(); http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/test/java/org/apache/usergrid/security/providers/FacebookProviderIT.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/security/providers/FacebookProviderIT.java b/stack/services/src/test/java/org/apache/usergrid/security/providers/FacebookProviderIT.java index cde0255..f6e307b 100644 --- a/stack/services/src/test/java/org/apache/usergrid/security/providers/FacebookProviderIT.java +++ b/stack/services/src/test/java/org/apache/usergrid/security/providers/FacebookProviderIT.java @@ -65,7 +65,7 @@ public class FacebookProviderIT { public static void setup() throws Exception { providerFactory = SpringResource.getInstance().getBean( SignInProviderFactory.class ); UserInfo adminUser = setup.getMgmtSvc() - .createAdminUser( uniqueUsername(), "Facebook User", "user"+newUUIDString()+"@facebook.com", "test", false, + .createAdminUser( null, uniqueUsername(), "Facebook User", "user"+newUUIDString()+"@facebook.com", "test", false, false ); OrganizationInfo organization = setup.getMgmtSvc().createOrganization( uniqueOrg(), adminUser, true ); applicationId = setup.getMgmtSvc().createApplication( organization.getUuid(), "fb-application" ).getId(); http://git-wip-us.apache.org/repos/asf/usergrid/blob/16bcae6e/stack/services/src/test/java/org/apache/usergrid/security/providers/PingIdentityProviderIT.java ---------------------------------------------------------------------- diff --git a/stack/services/src/test/java/org/apache/usergrid/security/providers/PingIdentityProviderIT.java b/stack/services/src/test/java/org/apache/usergrid/security/providers/PingIdentityProviderIT.java index df63d1f..4ddd7a2 100644 --- a/stack/services/src/test/java/org/apache/usergrid/security/providers/PingIdentityProviderIT.java +++ b/stack/services/src/test/java/org/apache/usergrid/security/providers/PingIdentityProviderIT.java @@ -61,7 +61,7 @@ public class PingIdentityProviderIT { @BeforeClass public static void setup() throws Exception { adminUser = setup.getMgmtSvc() - .createAdminUser( "pinguser", "Ping User", "[email protected]", "test", false, false ); + .createAdminUser( null, "pinguser", "Ping User", "[email protected]", "test", false, false ); organization = setup.getMgmtSvc().createOrganization( "ping-organization", adminUser, true ); applicationId = setup.getMgmtSvc().createApplication( organization.getUuid(), "ping-application" ).getId(); }
