From e13d8d7c0fe4b3350dcf9c1178df59bdc4bba189 Mon Sep 17 00:00:00 2001 From: remillet Date: Tue, 7 Nov 2017 22:22:26 -0800 Subject: [PATCH] DRYD-177: Now saving the state of a tenant's authority/vocab initialization. If already initialized, the Service layer will skip authority/vocab init at startup. --- .../jaxrs/CSpaceResteasyBootstrap.java | 84 +++++++++++++------ .../services/client/TenantFactory.java | 17 ++-- .../src/main/resources/accounts_common.xsd | 9 ++ .../main/resources/db/postgresql/account.sql | 2 +- .../storage/TenantDocumentHandler.java | 3 +- .../storage/TenantStorageConstants.java | 1 + .../collectionspace/authentication/AuthN.java | 6 +- .../spring/SpringAuthNContext.java | 16 +++- .../services/common/SecurityResourceBase.java | 2 +- .../AuthorizationCommon.java | 2 +- 10 files changed, 105 insertions(+), 37 deletions(-) diff --git a/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java b/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java index d0ad3dd4d..51d5f11a3 100644 --- a/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java +++ b/services/JaxRsServiceProvider/src/main/java/org/collectionspace/services/jaxrs/CSpaceResteasyBootstrap.java @@ -7,6 +7,8 @@ import org.jboss.resteasy.core.Dispatcher; import org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap; import org.collectionspace.authentication.CSpaceTenant; +import org.collectionspace.services.account.Tenant; +import org.collectionspace.services.account.TenantResource; import org.collectionspace.services.authorization.AuthZ; import org.collectionspace.services.client.AuthorityClient; import org.collectionspace.services.common.CSWebApplicationException; @@ -31,6 +33,7 @@ import java.util.logging.Level; public class CSpaceResteasyBootstrap extends ResteasyBootstrap { java.util.logging.Logger logger = java.util.logging.Logger.getAnonymousLogger(); + static final String RESET_AUTHORITIES_PROPERTY = "org.collectionspace.services.authorities.reset"; @Override public void contextInitialized(ServletContextEvent event) { @@ -45,10 +48,8 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { Dispatcher disp = deployment.getDispatcher(); disp.getDefaultContextObjects().put(ResourceMap.class, app.getResourceMap()); - String initAuthsString = System.getProperty("org.collectionspace.services.authorities.init", Boolean.TRUE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file - if (Boolean.valueOf(initAuthsString) == true) { - initializeAuthorities(app.getResourceMap()); - } + String resetAuthsString = System.getProperty(RESET_AUTHORITIES_PROPERTY, Boolean.TRUE.toString()); // Property can be set in the tomcat/bin/setenv.sh (or setenv.bat) file + initializeAuthorities(app.getResourceMap(), Boolean.valueOf(resetAuthsString)); logger.log(Level.INFO, String.format("%tc [INFO] CollectionSpace Services' JAX-RS application started.", new Date())); } catch (Exception e) { @@ -57,6 +58,7 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { } } + @Override public void contextDestroyed(ServletContextEvent event) { logger.log(Level.INFO, "[INFO] Shutting down the CollectionSpace Services' JAX-RS application."); @@ -69,25 +71,32 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { * @param resourceMap * @throws Exception */ - public void initializeAuthorities(ResourceMap resourceMap) throws Exception { + public void initializeAuthorities(ResourceMap resourceMap, boolean reset) throws Exception { TenantBindingConfigReaderImpl tenantBindingConfigReader = ServiceMain.getInstance().getTenantBindingConfigReader(); Hashtable tenantBindingsTable = tenantBindingConfigReader.getTenantBindings(false); for (TenantBindingType tenantBindings : tenantBindingsTable.values()) { CSpaceTenant tenant = new CSpaceTenant(tenantBindings.getId(), tenantBindings.getName()); - for (ServiceBindingType serviceBinding : tenantBindings.getServiceBindings()) { - AuthorityInstanceList element = serviceBinding.getAuthorityInstanceList(); - if (element != null && element.getAuthorityInstance() != null) { - List authorityInstanceList = element.getAuthorityInstance(); - for (AuthorityInstanceType authorityInstance : authorityInstanceList) { - try { - initializeAuthorityInstance(resourceMap, authorityInstance, serviceBinding, tenant); - } catch (Exception e) { - logger.log(Level.SEVERE, "Could not initialize authorities and authority terms: " + e.getMessage()); - throw e; - } - } - } - } + if (shouldInitializeAuthorities(tenant, reset) == true) { + for (ServiceBindingType serviceBinding : tenantBindings.getServiceBindings()) { + AuthorityInstanceList element = serviceBinding.getAuthorityInstanceList(); + if (element != null && element.getAuthorityInstance() != null) { + List authorityInstanceList = element.getAuthorityInstance(); + for (AuthorityInstanceType authorityInstance : authorityInstanceList) { + try { + initializeAuthorityInstance(resourceMap, authorityInstance, serviceBinding, tenant, reset); + } catch (Exception e) { + logger.log(Level.SEVERE, "Could not initialize authorities and authority terms: " + e.getMessage()); + throw e; + } + } + } + } + // + // If we made it this far, we've either created the tenant's authorities and terms or we've reset them. Either way, + // we should mark the isAuthoritiesInitialized field of the tenant to 'true'. + // + setAuthoritiesInitialized(tenant, true); + } } } @@ -98,16 +107,43 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { Object classInstance = co.newInstance(null); return (AuthorityClient) classInstance; } + + private boolean shouldInitializeAuthorities(CSpaceTenant cspaceTenant, boolean reset) { + AuthZ.get().login(); // login as super admin + TenantResource tenantResource = new TenantResource(); + Tenant tenantState = tenantResource.getTenant(cspaceTenant.getId()); + + // + // If the tenant's authorities have been initialized and + // we're not being asked to reset them, we'll return 'false' + // making any changes + // + return tenantState.isAuthoritiesInitialized() == false || reset == true; + } + + private void setAuthoritiesInitialized(CSpaceTenant cspaceTenant, boolean initState) { + AuthZ.get().login(); // login as super admin + TenantResource tenantResource = new TenantResource(); + Tenant tenantState = tenantResource.getTenant(cspaceTenant.getId()); + + tenantState.setAuthoritiesInitialized(initState); + tenantResource.updateTenant(cspaceTenant.getId(), tenantState); + } + /* * Check to see if an an authority instance and its corresponding terms exist. If not, try to create them. */ - private void initializeAuthorityInstance(ResourceMap resourceMap, AuthorityInstanceType authorityInstance, ServiceBindingType serviceBinding, CSpaceTenant tenant) throws Exception { + private void initializeAuthorityInstance(ResourceMap resourceMap, + AuthorityInstanceType authorityInstance, + ServiceBindingType serviceBinding, + CSpaceTenant cspaceTenant, + boolean reset) throws Exception { int status = -1; Response response = null; String serviceName = serviceBinding.getName(); - - AuthZ.get().login(tenant); + + AuthZ.get().login(cspaceTenant); String clientClassName = serviceBinding.getClientHandler(); AuthorityClient client = getAuthorityClient(clientClassName); String authoritySpecifier = RefName.shortIdToPath(authorityInstance.getTitleRef()); // e.g., urn:cspace:name(ulan) @@ -147,9 +183,9 @@ public class CSpaceResteasyBootstrap extends ResteasyBootstrap { } // - // Finally, try to create or verify the authority terms. + // Next, try to create or verify the authority terms. // - initializeAuthorityInstanceTerms(authorityResource, client, authoritySpecifier, resourceMap, authorityInstance, serviceName, tenant); + initializeAuthorityInstanceTerms(authorityResource, client, authoritySpecifier, resourceMap, authorityInstance, serviceName, cspaceTenant); } private void initializeAuthorityInstanceTerms( diff --git a/services/account/client/src/main/java/org/collectionspace/services/client/TenantFactory.java b/services/account/client/src/main/java/org/collectionspace/services/client/TenantFactory.java index 78d01ef0f..54eb3d3b1 100644 --- a/services/account/client/src/main/java/org/collectionspace/services/client/TenantFactory.java +++ b/services/account/client/src/main/java/org/collectionspace/services/client/TenantFactory.java @@ -30,34 +30,37 @@ import org.slf4j.LoggerFactory; /** * - * @author + * @author */ public class TenantFactory { static private final Logger logger = LoggerFactory.getLogger(TenantFactory.class); /** * create tenant instance + * * @param screenName * @param userName * @param passwd * @param email - * @param tenantId add non-null tenant id else let service take tenant id of - * the authenticated user + * @param tenantId + * add non-null tenant id else let service take tenant id of the + * authenticated user * @param useScreenName * @param invalidTenant * @param useUser * @param usePassword * @return */ - public static Tenant createTenantInstance(String id, - String name, boolean disabled) { + public static Tenant createTenantInstance(String id, String name, boolean disabled, + boolean authoritiesInitialized) { Tenant tenant = new Tenant(); tenant.setName(name); tenant.setId(id); + tenant.setAuthoritiesInitialized(authoritiesInitialized); tenant.setDisabled(disabled); - return tenant; -} + return tenant; + } } diff --git a/services/account/jaxb/src/main/resources/accounts_common.xsd b/services/account/jaxb/src/main/resources/accounts_common.xsd index 63371d416..af8e80ce0 100644 --- a/services/account/jaxb/src/main/resources/accounts_common.xsd +++ b/services/account/jaxb/src/main/resources/accounts_common.xsd @@ -314,6 +314,15 @@ + + + + + + + + + diff --git a/services/account/pstore/src/main/resources/db/postgresql/account.sql b/services/account/pstore/src/main/resources/db/postgresql/account.sql index bcfa115c5..7f1564e81 100644 --- a/services/account/pstore/src/main/resources/db/postgresql/account.sql +++ b/services/account/pstore/src/main/resources/db/postgresql/account.sql @@ -5,6 +5,6 @@ DROP TABLE IF EXISTS tenants CASCADE; DROP SEQUENCE IF EXISTS hibernate_sequence; create table accounts_common (csid varchar(128) not null, created_at timestamp not null, email varchar(255) not null, mobile varchar(255), person_ref_name varchar(255), phone varchar(255), screen_name varchar(128) not null, status varchar(15) not null, updated_at timestamp, userid varchar(128) not null, metadata_protection varchar(255), roles_protection varchar(255), primary key (csid)); create table accounts_tenants (HJID int8 not null, tenant_id varchar(128) not null, TENANTS_ACCOUNTS_COMMON_CSID varchar(128), primary key (HJID)); -create table tenants (id varchar(128) not null, created_at timestamp not null, name varchar(255) not null, disabled boolean not null, updated_at timestamp, primary key (id)); +create table tenants (id varchar(128) not null, created_at timestamp not null, name varchar(255) not null, authorities_initialized boolean not null, disabled boolean not null, updated_at timestamp, primary key (id)); alter table accounts_tenants add constraint FKFDA649B05A9CEEB5 foreign key (TENANTS_ACCOUNTS_COMMON_CSID) references accounts_common; create sequence hibernate_sequence; diff --git a/services/account/service/src/main/java/org/collectionspace/services/account/storage/TenantDocumentHandler.java b/services/account/service/src/main/java/org/collectionspace/services/account/storage/TenantDocumentHandler.java index f4d1446c8..15318c761 100644 --- a/services/account/service/src/main/java/org/collectionspace/services/account/storage/TenantDocumentHandler.java +++ b/services/account/service/src/main/java/org/collectionspace/services/account/storage/TenantDocumentHandler.java @@ -77,8 +77,9 @@ public class TenantDocumentHandler private Tenant merge(Tenant from, Tenant to) { Date now = new Date(); to.setUpdatedAtItem(now); - // The only thing we allow changing at this point is the disabled flag + // The only thing we allow changing at this point are the 'disabled' and 'authoritiesInitialized' flags to.setDisabled(from.isDisabled()); + to.setAuthoritiesInitialized(from.isAuthoritiesInitialized()); if (logger.isDebugEnabled()) { logger.debug("merged account=" diff --git a/services/account/service/src/main/java/org/collectionspace/services/account/storage/TenantStorageConstants.java b/services/account/service/src/main/java/org/collectionspace/services/account/storage/TenantStorageConstants.java index d780179ce..190946dc0 100644 --- a/services/account/service/src/main/java/org/collectionspace/services/account/storage/TenantStorageConstants.java +++ b/services/account/service/src/main/java/org/collectionspace/services/account/storage/TenantStorageConstants.java @@ -64,4 +64,5 @@ public class TenantStorageConstants { final public static String ID_FIELD = "id"; final public static String NAME_FIELD = "name"; final public static String DISABLED_FIELD = "disabled"; + final public static String AUTHORITIES_INITIALIZED_FIELD = "authoritiesInitialized"; } diff --git a/services/authentication/service/src/main/java/org/collectionspace/authentication/AuthN.java b/services/authentication/service/src/main/java/org/collectionspace/authentication/AuthN.java index b1a6db2e2..5d8f71ca1 100644 --- a/services/authentication/service/src/main/java/org/collectionspace/authentication/AuthN.java +++ b/services/authentication/service/src/main/java/org/collectionspace/authentication/AuthN.java @@ -74,13 +74,17 @@ public class AuthN { final public static String ROLE_ALL_TENANTS_MANAGER = "ALL_TENANTS_MANAGER"; final public static String ROLE_ALL_TENANTS_MANAGER_ID = "0"; final public static String ALL_TENANTS_MANAGER_TENANT_ID = "0"; + public static final String ADMIN_TENANT_ID = "0"; + public static final String ADMIN_TENANT_NAME = "tenant_admin"; + public static final String ANONYMOUS_TENANT_ID = "-1"; - public static final String ANONYMOUS_USER = "anonymous"; public static final String ANONYMOUS_TENANT_NAME = ANONYMOUS_USER; + public static final String SPRING_ADMIN_USER = "SPRING_ADMIN"; public static final String SPRING_ADMIN_PASSWORD = "SPRING_ADMIN"; + public static final String TENANT_ID_QUERY_PARAM = "tid"; public static final String TENANT_ID_PATH_PARAM = "tenantId"; diff --git a/services/authentication/service/src/main/java/org/collectionspace/authentication/spring/SpringAuthNContext.java b/services/authentication/service/src/main/java/org/collectionspace/authentication/spring/SpringAuthNContext.java index 2d3ef77f6..1529343ac 100644 --- a/services/authentication/service/src/main/java/org/collectionspace/authentication/spring/SpringAuthNContext.java +++ b/services/authentication/service/src/main/java/org/collectionspace/authentication/spring/SpringAuthNContext.java @@ -114,6 +114,20 @@ public class SpringAuthNContext implements AuthNContext { */ @Override public CSpaceTenant getCurrentTenant() { - return getUser().getPrimaryTenant(); + CSpaceTenant result = null; + + CSpaceUser cspaceUser = getUser(); + if (cspaceUser != null) { + result = getUser().getPrimaryTenant(); + } else { + String username = getUserId(); + if (username.equals(AuthN.ANONYMOUS_USER)) { + result = new CSpaceTenant(AuthN.ANONYMOUS_TENANT_ID, AuthN.ANONYMOUS_TENANT_NAME); + } else if (username.equals(AuthN.SPRING_ADMIN_USER)) { + result = new CSpaceTenant(AuthN.ADMIN_TENANT_ID, AuthN.ADMIN_TENANT_NAME); + } + } + + return result; } } diff --git a/services/common/src/main/java/org/collectionspace/services/common/SecurityResourceBase.java b/services/common/src/main/java/org/collectionspace/services/common/SecurityResourceBase.java index 8573b9947..226a6091a 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/SecurityResourceBase.java +++ b/services/common/src/main/java/org/collectionspace/services/common/SecurityResourceBase.java @@ -51,7 +51,7 @@ public abstract class SecurityResourceBase extends AbstractCollectionSpaceResour try { ServiceContext ctx = createServiceContext((Object) null, objectClass); DocumentHandler handler = createDocumentHandler(ctx); - MultivaluedMap queryParams = ui.getQueryParameters(); + MultivaluedMap queryParams = (ui != null ? ui.getQueryParameters() : null); DocumentFilter myFilter = handler.createDocumentFilter(); myFilter.setPagination(queryParams); myFilter.setQueryParams(queryParams); diff --git a/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java b/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java index 17f00e974..638125f74 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java +++ b/services/common/src/main/java/org/collectionspace/services/common/authorization_mgt/AuthorizationCommon.java @@ -409,7 +409,7 @@ public class AuthorizationCommon { ArrayList existingTenants) throws SQLException, Exception { // Need to define and look for a createDisabled attribute in tenant config final String insertTenantSQL = - "INSERT INTO tenants (id,name,disabled,created_at) VALUES (?,?,FALSE,now())"; + "INSERT INTO tenants (id,name,authorities_initialized,disabled,created_at) VALUES (?,?,FALSE,FALSE,now())"; PreparedStatement pstmt = null; try { pstmt = conn.prepareStatement(insertTenantSQL); // create a statement -- 2.47.3