From: Ray Lee Date: Tue, 2 Jun 2020 19:00:13 +0000 (-0400) Subject: DRYD-861: Allow a user to retrieve own roles without having read perms on accounts... X-Git-Url: https://git.aero2k.de/?a=commitdiff_plain;h=535a592c8e2a1a6cc8547a3287cc1824a3b71c6b;p=tmp%2Fjakarta-migration.git DRYD-861: Allow a user to retrieve own roles without having read perms on accounts resource. --- diff --git a/services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java b/services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java index 424e8095a..cd06e8bd4 100644 --- a/services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java +++ b/services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java @@ -133,9 +133,9 @@ public class AccountResource extends SecurityResourceBase parentContext, UriInfo ui, String csid, AccountsCommon theUpdate) { return (AccountsCommon)update(parentContext, ui, csid, theUpdate, AccountsCommon.class); } - + /** * Resets an accounts password. @@ -243,8 +243,8 @@ public class AccountResource extends SecurityResourceBase ctx = createServiceContext((AccountsCommon) null, AccountsCommon.class, uriInfo); ctx.openConnection(); try { @@ -576,29 +576,25 @@ public class AccountResource extends SecurityResourceBase ctx = null; - + try { - AccountRoleSubResource subResource = - new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE); - //get relationships for an account - result = subResource.getAccountRole(ctx, accCsid, SubjectType.ROLE); + result = JpaStorageUtils.getAccountRoles(accCsid); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.GET_FAILED, accCsid); } - checkResult(result, accCsid, ServiceMessages.GET_FAILED); + return result; } @@ -606,7 +602,7 @@ public class AccountResource extends SecurityResourceBase ctx = createServiceContext((AccountsCommon) null, AccountsCommon.class, (UriInfo) null); ctx.openConnection(); @@ -646,17 +642,17 @@ public class AccountResource extends SecurityResourceBase ctx = createServiceContext((AccountsCommon) null, AccountsCommon.class, uriInfo); ctx.openConnection(); try { @@ -679,7 +675,7 @@ public class AccountResource extends SecurityResourceBase resourceClass = resourceMethodInvoker.getResourceClass(); try { CollectionSpaceResource resourceInstance = (CollectionSpaceResource)resourceClass.newInstance(); @@ -121,32 +121,34 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn return result; } - - /* - * Check to see if the resource required authorization to access - * - */ - private boolean requiresAuthorization(String resName) { - boolean result = true; - // - // ACCOUNT_PERMISSIONS: All active users are allowed to see the *their* (we enforce this) current list of permissions. If this is not - // the request, then we'll do a full AuthZ check. - // - // STRUCTURED_DATE_REQUEST: All user can request the parsing of a structured date string. - // - switch (resName) { - case AuthZ.STRUCTURED_DATE_REQUEST: - case AuthZ.ACCOUNT_PERMISSIONS: - case AuthZ.REPORTS_MIME_OUTPUTS: - result = false; - break; - default: - result = true; - } - - return result; - } - + + /* + * Check to see if the resource required authorization to access + * + */ + private boolean requiresAuthorization(String resName) { + boolean result = true; + // + // ACCOUNT_PERMISSIONS, ACCOUNT_ROLES: All active users are allowed to see the *their* + // (we enforce this) current list of permissions and roles. If this is not the request, then + // we'll do a full AuthZ check. + // + // STRUCTURED_DATE_REQUEST: All user can request the parsing of a structured date string. + // + switch (resName) { + case AuthZ.STRUCTURED_DATE_REQUEST: + case AuthZ.ACCOUNT_PERMISSIONS: + case AuthZ.ACCOUNT_ROLES: + case AuthZ.REPORTS_MIME_OUTPUTS: + result = false; + break; + default: + result = true; + } + + return result; + } + /* (non-Javadoc) * @see org.jboss.resteasy.spi.interception.PreProcessInterceptor#preProcess(org.jboss.resteasy.spi.HttpRequest, org.jboss.resteasy.core.ResourceMethod) */ @@ -155,21 +157,21 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn throws Failure, CSWebApplicationException { ServerResponse result = null; // A null value essentially means success for this method Method resourceMethod = resourceMethodInvoker.getMethod(); - + try { if (isAnonymousRequest(request, resourceMethodInvoker) == true) { // We don't need to check credentials for anonymous requests. Just login to Nuxeo and // exit nuxeoPreProcess(request, resourceMethodInvoker); // We login to Nuxeo only after we've checked authorization - + return result; } - + final String servicesResource = "/cspace-services/"; // HACK - this is configured in war, get this from tomcat instead final int servicesResourceLen = servicesResource.length(); String httpMethod = request.getHttpMethod(); String uriPath = request.getUri().getPath(); - + if (logger.isDebugEnabled()) { String fullRequest = request.getUri().getRequestUri().toString(); int servicesResourceIdx = fullRequest.indexOf(servicesResource); @@ -177,10 +179,10 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn : fullRequest.substring(servicesResourceIdx+servicesResourceLen); logger.debug("received " + httpMethod + " on " + relativeRequest); } - + String resName = SecurityUtils.getResourceName(request.getUri()); String resEntity = SecurityUtils.getResourceEntity(resName); - + // // If the resource entity is acting as a proxy then all sub-resources will map to the resource itself. // This essentially means sub-resources inherit all the authz permissions of the entity. @@ -202,7 +204,7 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn // Make sure the account of the user making the request is current and active // checkActive(); - + if (requiresAuthorization(resName) == true) { //see comment immediately above AuthZ authZ = AuthZ.get(); CSpaceResource res = new URIResourceImpl(AuthN.get().getCurrentTenantId(), resName, httpMethod); @@ -244,7 +246,7 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn // Login to Nuxeo // nuxeoPreProcess(request, resourceMethodInvoker); // We login to Nuxeo only after we've checked authorization - + // // We've passed all the checks. Now just log the results // @@ -260,25 +262,25 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn } throw t; } - + return result; } - + @Override public void postProcess(ServerResponse arg0) { // // Log out of the Nuxeo framework // nuxeoPostProcess(arg0); - } + } /** * checkActive check if account is active - * @throws CSWebApplicationException + * @throws CSWebApplicationException */ private void checkActive() throws CSWebApplicationException { String userId = AuthN.get().getUserId(); - + try { // // Need to ensure that user's tenant is not disabled @@ -290,18 +292,18 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn userId, tenantBindingType.getDisplayName()); Response response = Response.status( Response.Status.CONFLICT).entity(errMsg).type("text/plain").build(); - throw new CSWebApplicationException(response); + throw new CSWebApplicationException(response); } } catch (IllegalStateException ise) { String errMsg = "User's account is not associated to any active tenants, userId=" + userId; // Note the RFC on return types: - // If the request already included Authorization credentials, then the 401 response + // If the request already included Authorization credentials, then the 401 response // indicates that authorization has been refused for those credentials. Response response = Response.status( Response.Status.UNAUTHORIZED).entity(errMsg).type("text/plain").build(); throw new CSWebApplicationException(ise, response); } - + try { //can't use JAXB here as this runs from the common jar which cannot //depend upon the account service @@ -349,10 +351,10 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn Response.Status.INTERNAL_SERVER_ERROR).entity(msg).type("text/plain").build(); throw new CSWebApplicationException(e, response); } - + return null; } - + public void nuxeoPostProcess(ServerResponse arg0) { try { nuxeoLogout(); @@ -360,8 +362,8 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn String msg = "Unable to logout of the Nuxeo framework."; logger.error(msg, e); } - } - + } + private void logLoginContext(LoginContext loginContext) { if (!logger.isTraceEnabled()) return; @@ -374,10 +376,10 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn logger.trace("[" + principal.getName() + "]"); } } - + private void logLogoutContext(LoginContext loginContext) { if (!logger.isTraceEnabled()) return; - + if (loginContext != null) { logger.trace("CollectionSpace services now logging out of Nuxeo with LoginContext: " + loginContext); @@ -391,8 +393,8 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn logger.trace("Logged out."); } } - - + + /* * Login to Nuxeo and save the LoginContext instance in a thread local variable */ @@ -407,9 +409,9 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn Thread.currentThread(), threadLocalLoginContext)); } } - + LoginContext loginContext = threadLocalLoginContext.get(); - + if (loginContext == null) { loginContext = Framework.loginAs(user); frameworkLogins++; @@ -434,9 +436,9 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn frameworkLogins++; } } - + private synchronized void nuxeoLogout() throws LoginException { - LoginContext loginContext = threadLocalLoginContext != null ? threadLocalLoginContext.get() : null; + LoginContext loginContext = threadLocalLoginContext != null ? threadLocalLoginContext.get() : null; if (loginContext != null) { logLogoutContext(loginContext); loginContext.logout(); @@ -451,7 +453,7 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn logger.warn(ERROR_NUXEO_LOGOUT); // If we get here, it means our login/logout bookkeeping has failed. } } - + if (frameworkLogins == 0) { if (threadLocalLoginContext != null) { logger.trace(String.format("Thread ID %s: Clearing ThreadLocal instance %s - %s ", @@ -459,5 +461,5 @@ public class SecurityInterceptor implements PreProcessInterceptor, PostProcessIn } threadLocalLoginContext = null; //Clear the ThreadLocal to void Tomcat warnings associated with thread pools. } - } + } } diff --git a/services/common/src/main/java/org/collectionspace/services/common/security/SecurityUtils.java b/services/common/src/main/java/org/collectionspace/services/common/security/SecurityUtils.java index 0f20ebcf2..062f25f72 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/security/SecurityUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/security/SecurityUtils.java @@ -81,7 +81,7 @@ class CSpacePasswordEncoder extends BasePasswordEncoder { /** * - * @author + * @author */ public class SecurityUtils { @@ -90,12 +90,12 @@ public class SecurityUtils { public static final String URI_PATH_SEPARATOR = "/"; public static final int MIN_PASSWORD_LENGTH = 8; public static final int MAX_PASSWORD_LENGTH = 24; - + public static final String BASE64_ENCODING = "BASE64"; public static final String BASE16_ENCODING = "HEX"; public static final String RFC2617_ENCODING = "RFC2617"; private static char MD5_HEX[] = "0123456789abcdef".toCharArray(); - + /** * createPasswordHash creates password has using configured digest algorithm * and encoding @@ -123,7 +123,7 @@ public class SecurityUtils { logger.error(msg); throw new IllegalArgumentException(msg); } - if (password.length() < MIN_PASSWORD_LENGTH + if (password.length() < MIN_PASSWORD_LENGTH || password.length() > MAX_PASSWORD_LENGTH) { String msg = "Bad password: '"+password+"': length should be >= " + MIN_PASSWORD_LENGTH + " and <= " + MAX_PASSWORD_LENGTH; @@ -134,11 +134,11 @@ public class SecurityUtils { public static String getWorkflowResourceName(HttpRequest request) { String result = null; - + UriInfo uriInfo = request.getUri(); String workflowSubResName = SecurityUtils.getResourceName(uriInfo); String resEntity = SecurityUtils.getResourceEntity(workflowSubResName); - + MultivaluedMap pathParams = uriInfo.getPathParameters(); String workflowTransition = pathParams.getFirst(WorkflowClient.TRANSITION_PARAM_JAXRS); if (workflowTransition != null) { @@ -147,17 +147,17 @@ public class SecurityUtils { // e.g., intakes/workflow or intakes/*/workflow result = resEntity; } - + return result; } - + public static String getIndexResourceName(HttpRequest request) { String result = null; - + UriInfo uriInfo = request.getUri(); String indexSubResName = SecurityUtils.getResourceName(uriInfo); String resEntity = SecurityUtils.getResourceEntity(indexSubResName); - + MultivaluedMap pathParams = uriInfo.getPathParameters(); String indexId = pathParams.getFirst(IndexClient.INDEX_ID_PARAM); if (indexId != null && pathParams.containsKey("csid")) { @@ -165,12 +165,12 @@ public class SecurityUtils { result = resEntity + "/*/" + IndexClient.SERVICE_NAME + "/" + indexId; } else if (indexId != null) { // e.g., intakes/index/fulltext - result = resEntity + "/" + IndexClient.SERVICE_NAME + "/" + indexId; + result = resEntity + "/" + IndexClient.SERVICE_NAME + "/" + indexId; } else { // e.g., intakes result = resEntity; } - + // // Overriding the result from above. // @@ -178,10 +178,10 @@ public class SecurityUtils { // we're just going to return the index resource name. // result = IndexClient.SERVICE_NAME; - + return result; - } - + } + /** * Gets the resource name. * @@ -192,7 +192,7 @@ public class SecurityUtils { String uriPath = uriInfo.getPath(); MultivaluedMap pathParams = uriInfo.getPathParameters(); - + for (String pathParamName : pathParams.keySet()) { //assumption : path params for csid for any entity has substring csid in name String pathParamValue = pathParams.get(pathParamName).get(0); @@ -216,9 +216,9 @@ public class SecurityUtils { if ((pathParamName.toLowerCase().indexOf("indexid") > -1)) { //replace indexid with wildcard uriPath = uriPath.replace(pathParamValue, "*"); - } + } } - + // FIXME: REM // Since the hjid (HyperJaxb3 generated IDs) are not unique strings in URIs that also have a CSID, // we need to replace hjid last. We can fix this by having HyperJaxb3 generate UUID. @@ -229,13 +229,13 @@ public class SecurityUtils { String hjidValue = hjidValueList.get(0); //should be just one value, so get the first. uriPath = uriPath.replace(hjidValue, "*"); } - + uriPath = uriPath.replace("//", "/"); // replace duplicate '/' characters uriPath = uriPath.startsWith("/") ? uriPath.substring(1) : uriPath; // if present, strip the leading '/' character - + return uriPath; } - + /** * Gets the resource name. * @@ -244,16 +244,16 @@ public class SecurityUtils { */ public static String getResourceEntity(UriInfo uriInfo) { String result = null; - + result = getResourceEntity(uriInfo.getPath()); // List pathSegmentList = uriInfo.getPathSegments(); // if (pathSegmentList.isEmpty() == false) { // result = pathSegmentList.get(0).getPath(); // } - + return result; } - + /** * Gets the resource entity by returning the first segment of the resource path * @@ -264,12 +264,12 @@ public class SecurityUtils { public static String getResourceEntity(String relativePath) { String result = ""; - + StringTokenizer strTok = new StringTokenizer(relativePath, URI_PATH_SEPARATOR); String pathSegment = null; while (strTok.hasMoreTokens() == true) { pathSegment = strTok.nextToken(); - if (pathSegment.equals("*") || + if (pathSegment.equals("*") || pathSegment.equals(IndexClient.SERVICE_PATH_COMPONENT) || pathSegment.equals(CollectionSpaceClient.SERVICE_DESCRIPTION_PATH)) { // Strip off subresource paths since they inherit their parent's permissions // // leave the loop if we hit a wildcard character or the "index" subresource @@ -285,15 +285,15 @@ public class SecurityUtils { // Special case for the "index" services since "index" is also a subresource for some of the other services. // if (Tools.isEmpty(result) && pathSegment.equals(IndexClient.SERVICE_PATH_COMPONENT)) { - result = IndexClient.SERVICE_PATH_COMPONENT; + result = IndexClient.SERVICE_PATH_COMPONENT; } - + return result; } - + public static List getReadableServiceBindingsForCurrentUser( List serviceBindings) { - ArrayList readableList = + ArrayList readableList = new ArrayList(serviceBindings.size()); AuthZ authZ = AuthZ.get(); for(ServiceBindingType binding:serviceBindings) { @@ -305,7 +305,7 @@ public class SecurityUtils { } return readableList; } - + /** * Checks if is entity is action as a proxy for all sub-resources. * @@ -313,19 +313,20 @@ public class SecurityUtils { */ public static final boolean isResourceProxied(String resName) { boolean result = true; - + switch (resName) { case AuthZ.REPORTS_INVOKE: case AuthZ.BATCH_INVOKE: - case AuthZ.ACCOUNT_PERMISSIONS: + case AuthZ.ACCOUNT_PERMISSIONS: + case AuthZ.ACCOUNT_ROLES: result = false; break; } - + return result; } - + /** * isCSpaceAdmin check if authenticated user is a CSpace administrator * @param tenantId @@ -333,24 +334,24 @@ public class SecurityUtils { */ public static boolean isCSpaceAdmin() { boolean result = false; - + String tenantId = null; try { tenantId = AuthN.get().getCurrentTenantId(); } catch (Throwable e) { tenantId = AuthN.ADMIN_TENANT_ID; } - + if (tenantId != null) { if (AuthN.ADMIN_TENANT_ID.equals(tenantId) == true || AuthN.ANONYMOUS_TENANT_ID.equals(tenantId)) { result = true; } } - + return result; } - + public static String createPasswordHash(String hashAlgorithm, String hashEncoding, String hashCharset, String username, String password, String salt) { @@ -362,7 +363,7 @@ public class SecurityUtils { { CSpacePasswordEncoder passwordEncoder = new CSpacePasswordEncoder(); String saltedPassword = passwordEncoder.mergePasswordAndSalt(password, salt); // - + String passwordHash = null; byte passBytes[]; try @@ -463,5 +464,5 @@ public class SecurityUtils { return Base64Utils.fromb64(str); } - + } diff --git a/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageUtils.java b/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageUtils.java index 109ca4dbc..0b70abee9 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageUtils.java @@ -39,12 +39,14 @@ import javax.persistence.Query; import org.collectionspace.authentication.AuthN; import org.collectionspace.services.authorization.AccountPermission; -import org.collectionspace.services.authorization.AccountValue; +import org.collectionspace.services.authorization.AccountRole; import org.collectionspace.services.authorization.AccountRoleRel; +import org.collectionspace.services.authorization.AccountValue; import org.collectionspace.services.authorization.AuthZ; import org.collectionspace.services.authorization.CSpaceResource; import org.collectionspace.services.authorization.PermissionRoleRel; import org.collectionspace.services.authorization.PermissionValue; +import org.collectionspace.services.authorization.RoleValue; import org.collectionspace.services.authorization.URIResourceImpl; import org.collectionspace.services.common.api.Tools; import org.collectionspace.services.common.authorization_mgt.AuthorizationRoleRel; @@ -60,32 +62,32 @@ import org.slf4j.LoggerFactory; /** * Utilities for JpaStorage - * @author + * @author */ @SuppressWarnings({"rawtypes", "unchecked"}) public class JpaStorageUtils { final private static Logger logger = LoggerFactory.getLogger(JpaStorageUtils.class); - + /** The Constant CS_PERSISTENCE_UNIT. */ public final static String CS_PERSISTENCE_UNIT = "org.collectionspace.services"; public static String CS_AUTHZ_PERSISTENCE_UNIT = "org.collectionspace.services.authorization"; public final static String CS_CURRENT_USER = "0"; - + // This is the column name for ID field of all the JPA objects public static final String CSID_LABEL = "csid"; - + private static Map entityManagerFactoryCache = new HashMap(); private static boolean useTenantId(String tenantId) { boolean result = true; - + boolean csAdmin = SecurityUtils.isCSpaceAdmin(); if (csAdmin == true) { logger.trace("Running as the CSAdmin user."); //Thread.dumpStack(); } - + if (tenantId == null) { result = false; logger.trace("Ignoring tenant ID during ."); @@ -94,7 +96,7 @@ public class JpaStorageUtils { return result; } - + @Deprecated public static Object getEntity(String id, Class entityClazz) { EntityManagerFactory emf = null; @@ -114,7 +116,7 @@ public class JpaStorageUtils { } return entityFound; } - + public static Object getEntity(long id, Class entityClazz) throws DocumentNotFoundException { @@ -136,7 +138,7 @@ public class JpaStorageUtils { /** * getEntity with given id and class using given entity manager - * + * * @param em * @param id * @param entityClazz @@ -152,7 +154,7 @@ public class JpaStorageUtils { //FIXME: it would be nice to verify tenantid as well return em.find(entityClazz, id); } - + public static Object getEntity(JPATransactionContext jpaTransactionContext, String id, Class entityClazz) throws DocumentNotFoundException { if (entityClazz == null) { String msg = "Not constructed with JpaStorageClientImpl(entityClazz) ctor"; @@ -161,8 +163,8 @@ public class JpaStorageUtils { } //FIXME: it would be nice to verify tenantid as well return jpaTransactionContext.find(entityClazz, id); - } - + } + @Deprecated private static String getUserId(String csid) throws DocumentNotFoundException { @@ -173,7 +175,7 @@ public class JpaStorageUtils { if (csid.equals(CS_CURRENT_USER) == true) { return AuthN.get().getUserId(); } - + //FIXME: Why can't the common jar depend on the account service? Can we move the account //jaxb classes to the common "jaxb" module? try { @@ -182,7 +184,7 @@ public class JpaStorageUtils { String whereClause = "where csid = :csid"; HashMap params = new HashMap(); params.put("csid", csid); - + Object account = JpaStorageUtils.getEntity( "org.collectionspace.services.account.AccountsCommon", whereClause, params); if (account == null) { @@ -195,12 +197,12 @@ public class JpaStorageUtils { result = (String)JaxbUtils.getValue(account, "getUserId"); } catch (Exception e) { String msg = "User's account is in invalid state, csid=" + csid; - throw new DocumentNotFoundException(msg); + throw new DocumentNotFoundException(msg); } - + return result; } - + private static AccountValue getAccountValue(String csid) throws DocumentNotFoundException { @@ -234,11 +236,11 @@ public class JpaStorageUtils { return av; } catch (Exception e) { String msg = "User's account is in invalid state, csid=" + csid; - throw new DocumentNotFoundException(msg); + throw new DocumentNotFoundException(msg); } } - //FIXME: REM - This method should probably be moved to the AccountPermissionDocumemntHandler + //FIXME: REM - This method should probably be moved to the AccountPermissionDocumentHandler /* * This is a prototype for the /accounts/{csid}/permissions GET service call. */ @@ -246,8 +248,8 @@ public class JpaStorageUtils { throws UnauthorizedException, DocumentNotFoundException { return getAccountPermissions(csid, null, null); } - - //FIXME: REM - This method should probably be moved to the AccountPermissionDocumemntHandler + + //FIXME: REM - This method should probably be moved to the AccountPermissionDocumentHandler /* * This is a prototype for the /accounts/{csid}/permissions GET service call. */ @@ -260,7 +262,7 @@ public class JpaStorageUtils { // AccountValue account = getAccountValue(csid); String userId = account.getUserId(); - String currentUserId = AuthN.get().getUserId(); + String currentUserId = AuthN.get().getUserId(); if (currentUserId.equalsIgnoreCase(userId) == false) { CSpaceResource res = new URIResourceImpl(AuthN.get().getCurrentTenantId(), "accounts", "GET"); if (AuthZ.get().isAccessAllowed(res) == false) { @@ -272,7 +274,7 @@ public class JpaStorageUtils { throw new UnauthorizedException(msg); } } - + AccountPermission result = new AccountPermission(); EntityManagerFactory emf = null; EntityManager em = null; @@ -284,9 +286,9 @@ public class JpaStorageUtils { emf = getEntityManagerFactory(); em = emf.createEntityManager(); - + StringBuilder permQueryStrBldr = new StringBuilder( - "SELECT DISTINCT pr FROM " + AccountRoleRel.class.getName() + " ar, " + "SELECT DISTINCT pr FROM " + AccountRoleRel.class.getName() + " ar, " + PermissionRoleRel.class.getName() + " pr" + " WHERE ar.roleId = pr.roleId and ar.userId=" + "'" + userId + "'"); // @@ -297,7 +299,7 @@ public class JpaStorageUtils { " or pr.permissionResource = " + "'" + permissionResource + "'" + ")"); } String queryStr = permQueryStrBldr.toString(); //for debugging - Query q = em.createQuery(queryStr); + Query q = em.createQuery(queryStr); resultList = q.getResultList().iterator(); if (resultList.hasNext()) { @@ -330,41 +332,120 @@ public class JpaStorageUtils { } return result; } - + + //FIXME: REM - This method should probably be moved to the AccountPermissionDocumentHandler + public static AccountRole getAccountRoles(String csid) + throws UnauthorizedException, DocumentNotFoundException { + return getAccountRoles(csid, null, null); + } + + //FIXME: REM - This method should probably be moved to the AccountPermissionDocumentHandler + public static AccountRole getAccountRoles(String csid, String currentResource, String permissionResource) + throws UnauthorizedException, DocumentNotFoundException { + // + // Make sure the user asking for this list has the correct + // permission -that is, the csid's userId match the currently logged in userId or + // that they have read access to the "accounts" resource. + // + AccountValue account = getAccountValue(csid); + String userId = account.getUserId(); + String currentUserId = AuthN.get().getUserId(); + if (currentUserId.equalsIgnoreCase(userId) == false) { + CSpaceResource res = new URIResourceImpl(AuthN.get().getCurrentTenantId(), "accounts", "GET"); + if (AuthZ.get().isAccessAllowed(res) == false) { + String msg = "Access to the permissions for the account with csid = " + csid + " is NOT allowed for " + + " user=" + currentUserId; + if (logger.isDebugEnabled() == true) { + logger.debug(msg); + } + throw new UnauthorizedException(msg); + } + } + + AccountRole result = new AccountRole(); + EntityManagerFactory emf = null; + EntityManager em = null; + Iterator resultList = null; + try { + List accountValues = new ArrayList(); + accountValues.add(account); + result.setAccount(accountValues); + + emf = getEntityManagerFactory(); + em = emf.createEntityManager(); + + String queryStr = + "SELECT DISTINCT ar FROM " + AccountRoleRel.class.getName() + " ar " + + "WHERE ar.userId=" + "'" + userId + "'"; + + Query q = em.createQuery(queryStr); + resultList = q.getResultList().iterator(); + + if (resultList.hasNext()) { + List roleValues = new ArrayList(); + while (resultList.hasNext()) { + AccountRoleRel accountRolRel = (AccountRoleRel)resultList.next(); + roleValues.add(AuthorizationRoleRel.buildRoleValue(accountRolRel)); + } + result.setRole(roleValues); + } + } catch (NoResultException nre) { + if (em != null && em.getTransaction().isActive()) { + em.getTransaction().rollback(); + } + if (logger.isDebugEnabled()) { + logger.debug("could not find entity with id=" + userId, nre); + } + //returns null + } catch (Exception e) { + if (em != null && em.getTransaction().isActive()) { + em.getTransaction().rollback(); + } + if (logger.isDebugEnabled()) { + logger.debug("could not find entity(2) with id=" + userId, e); + } + } finally { + if (em != null) { + releaseEntityManagerFactory(emf); + } + } + return result; + } + public static Object getEnityByKey( JPATransactionContext jpaTransactionContext, - String entityName, - String key, + String entityName, + String key, String value, String tenantId) throws TransactionException { return getEnityByKey(jpaTransactionContext, (DocumentFilter)null, entityName, key, value, tenantId); } - + public static Object getEnityByKey( JPATransactionContext jpaTransactionContext, DocumentFilter docFilter, String entityName, String key, String value, String tenantId) throws TransactionException { Object result = null; - + try { boolean useTenantId = useTenantId(tenantId); StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM "); queryStrBldr.append(entityName); queryStrBldr.append(" a"); - + if (docFilter != null) { String joinFetch = docFilter.getJoinFetchClause(); if (Tools.notBlank(joinFetch)) { queryStrBldr.append(" " + joinFetch); } } - + queryStrBldr.append(" WHERE a." + key + " = :" + key); if (useTenantId == true) { queryStrBldr.append(" AND a.tenantId = :tenantId"); } - String queryStr = queryStrBldr.toString(); //for debugging + String queryStr = queryStrBldr.toString(); //for debugging Query q = jpaTransactionContext.createQuery(queryStr); q.setParameter(key, value); if (useTenantId == true) { @@ -382,12 +463,12 @@ public class JpaStorageUtils { } //returns null } - + return result; } /** - * + * * @param em * @param entityName * @param key1 @@ -395,18 +476,18 @@ public class JpaStorageUtils { * @param key2 * @param value2 * @return - * @throws TransactionException + * @throws TransactionException */ public static Object getEntityByDualKeys( JPATransactionContext jpaTransactionContext, - String entityName, + String entityName, String key1, String value1, String key2, String value2) throws TransactionException { return getEntityByDualKeys(jpaTransactionContext, entityName, key1, value1, key2, value2, null); } - + /** - * + * * @param em * @param entityName * @param key1 @@ -415,16 +496,16 @@ public class JpaStorageUtils { * @param value2 * @param tenantId * @return - * @throws TransactionException + * @throws TransactionException */ public static Object getEntityByDualKeys( JPATransactionContext jpaTransactionContext, - String entityName, + String entityName, String key1, String value1, String key2, String value2, String tenantId) throws TransactionException { Object result = null; - + boolean useTenantId = useTenantId(tenantId); StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM "); queryStrBldr.append(entityName); @@ -441,12 +522,12 @@ public class JpaStorageUtils { if (useTenantId == true) { q.setParameter("tenantId", tenantId); } - + result = q.getSingleResult(); return result; } - + public static List getEntityListByDualKeys(JPATransactionContext jpaTransactionContext, String entityName, String key1, String value1, String key2, String value2, String tenantId) throws TransactionException { List result = null; @@ -472,15 +553,15 @@ public class JpaStorageUtils { return result; } - + /** - * + * * @param ctx * @param entityName * @param id * @param tenantId * @return - * @throws TransactionException + * @throws TransactionException */ public static Object getEntity( JPATransactionContext jpaTransactionContext, @@ -492,7 +573,7 @@ public class JpaStorageUtils { } /** - * getEntity + * getEntity * @param entityName fully qualified entity name * @param id * @param tenantId @@ -518,7 +599,7 @@ public class JpaStorageUtils { queryStrBldr.append(entityName); queryStrBldr.append(" a"); queryStrBldr.append(" WHERE csid = :csid"); - + boolean useTenantId = useTenantId(tenantId); if (useTenantId == true) { queryStrBldr.append(" AND tenantId = :tenantId"); @@ -559,7 +640,7 @@ public class JpaStorageUtils { public static Object getEntity(JPATransactionContext jpaTransactionContext, String entityName, String whereClause, HashMap paramBindings) { Object result = null; - + StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM "); queryStrBldr.append(entityName); queryStrBldr.append(" a"); @@ -570,20 +651,20 @@ public class JpaStorageUtils { for (String paramName : paramBindings.keySet()) { q.setParameter(paramName, paramBindings.get(paramName)); } - + result = q.getSingleResult(); - + if (result == null) { logger.debug("Call to getEntity() returned empty set."); } - + return result; } - + public static Object getEntity(EntityManager em, String entityName, String whereClause, HashMap paramBindings) { Object result = null; - + StringBuilder queryStrBldr = new StringBuilder("SELECT a FROM "); queryStrBldr.append(entityName); queryStrBldr.append(" a"); @@ -594,16 +675,16 @@ public class JpaStorageUtils { for (String paramName : paramBindings.keySet()) { q.setParameter(paramName, paramBindings.get(paramName)); } - + result = q.getSingleResult(); - + if (result == null) { logger.debug("Call to getEntity() returned empty set."); } - + return result; } - + /** * getEntity using given where clause with given param bindings * @param entityName @@ -652,7 +733,7 @@ public class JpaStorageUtils { public static EntityManagerFactory getEntityManagerFactory() { EntityManagerFactory result = null; PersistenceException persistenceException = null; - + try { result = getEntityManagerFactory(CS_PERSISTENCE_UNIT); } catch (PersistenceException e) { @@ -671,11 +752,11 @@ public class JpaStorageUtils { persistenceException = e; } } - + if (result == null) { throw persistenceException; } - + return result; } @@ -691,14 +772,14 @@ public class JpaStorageUtils { EntityManagerFactory result = null; result = getCachedEntityManagerFactory(persistenceUnit); - + // // Try using a backup persistence unit if the specified one is not available and log a warning // if (result == null && !persistenceUnit.equalsIgnoreCase(CS_PERSISTENCE_UNIT)) { result = getCachedEntityManagerFactory(CS_PERSISTENCE_UNIT); } - + // // One more try. // @@ -742,7 +823,7 @@ public class JpaStorageUtils { // are cached and re-used, they should not be closed after each use. // Instead, releaseEntityManagerFactories() should be called when the // services layer is stopped. - + // if (emf != null) { // emf.close(); // } @@ -752,8 +833,7 @@ public class JpaStorageUtils { for (EntityManagerFactory emf : entityManagerFactoryCache.values()) { emf.close(); } - + entityManagerFactoryCache.clear(); } } -