]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
DRYD-947: Refactored connection and transaction handling for password-reset workflow...
authorRichard Millet <remillet@yahoo.com>
Fri, 26 Feb 2021 19:28:19 +0000 (11:28 -0800)
committerRichard Millet <remillet@yahoo.com>
Fri, 26 Feb 2021 19:28:19 +0000 (11:28 -0800)
services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java
services/common/src/main/java/org/collectionspace/services/common/SecurityResourceBase.java
services/common/src/main/java/org/collectionspace/services/common/context/RemoteServiceContextImpl.java
services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java

index 970212295556503a695b98465f27778456358528..46a6c7f9a81bbbee3c85aa5c0cea80791be77115 100644 (file)
@@ -206,11 +206,13 @@ public class AccountResource extends SecurityResourceBase<AccountsCommon, Accoun
                        if (roleValueList.isEmpty() == false) {
                                result = new ArrayList<String>();
                                for (RoleValue roleValue: roleValueList) {
-                                       String displayName = roleValue.getDisplayName();
-                                       if (displayName == null) {
-                                               displayName = RoleClient.inferDisplayName(roleValue.getRoleName(), tenantId);
+                                       if (roleValue != null) {
+                                               String displayName = roleValue.getDisplayName();
+                                               if (displayName == null) {
+                                                       displayName = RoleClient.inferDisplayName(roleValue.getRoleName(), tenantId);
+                                               }
+                                               result.add(displayName);
                                        }
-                                       result.add(displayName);
                                }
                        }
                }
@@ -224,15 +226,14 @@ public class AccountResource extends SecurityResourceBase<AccountsCommon, Accoun
     public AccountsCommon updateAccount(@Context UriInfo ui, @PathParam("csid") String csid, AccountsCommon theUpdate) {
         return (AccountsCommon)update(ui, csid, theUpdate, AccountsCommon.class);
     }
-
+    
     /*
-     * Use this when you have an existing and active ServiceContext.
+     * Use this when you have an existing and active ServiceContext. //FIXME: Use this only for password reset
      */
-    public AccountsCommon updateAccount(ServiceContext<AccountsCommon, AccountsCommon> parentContext, UriInfo ui, String csid, AccountsCommon theUpdate) {
-        return (AccountsCommon)update(parentContext, ui, csid, theUpdate, AccountsCommon.class);
+    private AccountsCommon updateAccountPassword(ServiceContext<AccountsCommon, AccountsCommon> parentContext, UriInfo ui, String csid, AccountsCommon theUpdate) {
+        return (AccountsCommon)update(parentContext, ui, csid, theUpdate, AccountsCommon.class, false);
     }
 
-
     /**
      * Resets an accounts password.
      *
@@ -328,7 +329,7 @@ public class AccountResource extends SecurityResourceBase<AccountsCommon, Accoun
                                                AccountsCommon accountUpdate = new AccountsCommon();
                                                accountUpdate.setUserId(targetAccount.getUserId());
                                                accountUpdate.setPassword(password.getBytes());
-                                               updateAccount(ctx, ui, targetAccount.getCsid(), accountUpdate);
+                                               updateAccountPassword(ctx, ui, targetAccount.getCsid(), accountUpdate);
                                                TokenStorageClient.update(transactionCtx, tokenId, false); // disable the token so it can't be used again.
                                                transactionCtx.commitTransaction();
                                                //
@@ -343,6 +344,7 @@ public class AccountResource extends SecurityResourceBase<AccountsCommon, Accoun
                                }
                                } catch (Throwable t) {
                                        transactionCtx.markForRollback();
+                                       transactionCtx.close(); // https://jira.ets.berkeley.edu/jira/browse/CC-241                                     
                                        String errMsg = String.format("Could not reset password using token ID='%s'. Error: '%s'",
                                                        t.getMessage(), token.getId());
                                response = Response.status(Response.Status.BAD_REQUEST).entity(errMsg).type("text/plain").build();
@@ -370,31 +372,43 @@ public class AccountResource extends SecurityResourceBase<AccountsCommon, Accoun
 
         MultivaluedMap<String,String> queryParams = ui.getQueryParameters();
         String email = queryParams.getFirst(AccountClient.EMAIL_QUERY_PARAM);
-        if (email == null) {
+        if (email == null || email.isEmpty()) {
                response = Response.status(Response.Status.BAD_REQUEST).entity("You must specify an 'email' query paramater.").type("text/plain").build();
                return response;
         }
 
         String tenantId = queryParams.getFirst(AuthN.TENANT_ID_QUERY_PARAM);
-        if (tenantId == null) {
+        if (tenantId == null || tenantId.isEmpty()) {
                response = Response.status(Response.Status.BAD_REQUEST).entity("You must specify an 'tid' (tenant ID) query paramater.").type("text/plain").build();
                return response;
         }
-
+        //
+        // Search for an account with the provided email and tenant ID
+        //
+               boolean found = false;
+               AccountListItem accountListItem = null;
        AccountsCommonList accountList = getAccountList(ui);
-       if (accountList == null || accountList.getTotalItems() == 0) {
-               response = Response.status(Response.Status.NOT_FOUND).entity("Could not locate an account associated with the email: " +
-                               email).type("text/plain").build();
-       } else if (accountList.getTotalItems() > 1) {
-               response = Response.status(Response.Status.BAD_REQUEST).entity("Located more than one account associated with the email: " +
-                               email).type("text/plain").build();
-       } else {
-               AccountListItem accountListItem = accountList.getAccountListItem().get(0);
-               try {
+       if (accountList != null || accountList.getTotalItems() > 0) {
+                       List<AccountListItem> itemsList = accountList.getAccountListItem();
+                       for (AccountListItem item : itemsList) {
+                               if (item != null && item.getTenantid() != null && item.getTenantid().equalsIgnoreCase(tenantId)) {
+                                       accountListItem = item;
+                                       found = true;
+                                       break;
+                               }
+                       }
+       }
+
+       if (found == true) {
+                       try {
                                response = requestPasswordReset(ui, tenantId, accountListItem);
                        } catch (Exception e) {
-               response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).type("text/plain").build();
+                       response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).type("text/plain").build();
                        }
+       } else {
+               String msg = String.format("Could not locate an account associated with the email '%s' and tenant ID '%s'",
+                               email , tenantId);
+               response = Response.status(Response.Status.NOT_FOUND).entity(msg).type("text/plain").build();
        }
 
         return response;
index 9d1f870b8cee1454b63f6976838955ae9c6bf5fa..2a17628ba4868a0fa241982256278259b70bab16 100644 (file)
@@ -232,7 +232,21 @@ public class AccountDocumentHandler
             AccountListItem accListItem = new AccountListItem();
             accListItem.setScreenName(account.getScreenName());
             accListItem.setUserid(account.getUserId());
-            accListItem.setTenantid(account.getTenants().get(0).getTenantId()); // pick the default/first tenant
+            //
+            // Since accounts can be associated with more than 1 tenant, we only want to include
+            // the tenant information for the current service context.
+            //
+               String tenantInCtx = this.getServiceContext().getTenantId();
+            List<AccountTenant> associatedTenantList = account.getTenants();
+            for (AccountTenant associatedTenant : associatedTenantList) {
+                if (associatedTenant != null && associatedTenant.getTenantId() != null) {
+                       if (associatedTenant.getTenantId().equalsIgnoreCase(tenantInCtx)) {
+                               accListItem.setTenantid(associatedTenant.getTenantId());
+                               break;
+                       }
+                }
+            }
+
             accListItem.setTenants(account.getTenants());
             accListItem.setEmail(account.getEmail());
             accListItem.setStatus(account.getStatus());
index 1a0df03bf5a838bc96ed32a647b2160509327691..b42977406e12158e4d761c1facbbeb71bafefa48 100644 (file)
@@ -184,14 +184,10 @@ public class AccountStorageClient extends JpaStorageClientImpl {
                         accountReceived.getPassword());
             }
             DocumentWrapper<AccountsCommon> wrapDoc =
-                    new DocumentWrapperImpl<AccountsCommon>(accountFound);
+                       new DocumentWrapperImpl<AccountsCommon>(accountFound);
             handler.handle(Action.UPDATE, wrapDoc);
             handler.complete(Action.UPDATE, wrapDoc); 
             jpaConnectionContext.commitTransaction();
-            //
-            // Don't sanitize until we've committed changes to the DB
-            //
-            handler.sanitize(wrapDoc);
         } catch (BadRequestException bre) {
                jpaConnectionContext.markForRollback();
             throw bre;
index 1d59dd2d6df1ba0c3dacf4a6f6fa3b10db4dbcbc..81b2a7b4d47213a2e5d014946aa446f17da1f2c7 100644 (file)
@@ -4,6 +4,8 @@ import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.DocumentException;
 import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentHandler;
+import org.collectionspace.services.common.document.DocumentWrapper;
+import org.collectionspace.services.common.document.DocumentWrapperImpl;
 import org.collectionspace.services.common.storage.TransactionContext;
 import org.collectionspace.services.common.storage.jpa.JPATransactionContext;
 import org.slf4j.Logger;
@@ -141,6 +143,12 @@ public abstract class SecurityResourceBase<IT, OT> extends AbstractCollectionSpa
             throw bigReThrow(e, ServiceMessages.LIST_FAILED);
         }
     }
+    
+    protected OT sanitize(DocumentHandler handler, OT outputObject) {
+        DocumentWrapper<OT> wrapDoc = new DocumentWrapperImpl<OT>(outputObject);
+        handler.sanitize(wrapDoc);
+        return outputObject;
+    }    
 
     public Object update(String csid, IT theUpdate, Class<?> objectClass) {
         return update((UriInfo)null, csid, theUpdate, objectClass);
@@ -155,13 +163,19 @@ public abstract class SecurityResourceBase<IT, OT> extends AbstractCollectionSpa
             ServiceContext<IT, OT> ctx = createServiceContext(theUpdate, objectClass, ui);
             DocumentHandler handler = createDocumentHandler(ctx);
             getStorageClient(ctx).update(ctx, csid, handler);
-            return ctx.getOutput();
+            return sanitize(handler, ctx.getOutput());
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.PUT_FAILED, csid);
         }
     }
     
     public Object update(ServiceContext<?, ?> parentCtx, UriInfo ui, String csid, IT theUpdate, Class objectClass) {
+       return update(parentCtx, ui, csid, theUpdate, objectClass, true);
+    }
+
+    public Object update(ServiceContext<?, ?> parentCtx, UriInfo ui, String csid, IT theUpdate, Class objectClass, boolean sanitize) {
+       Object result = null;
+       
         if (logger.isDebugEnabled()) {
             logger.debug("updateRole with csid=" + csid);
         }
@@ -171,10 +185,16 @@ public abstract class SecurityResourceBase<IT, OT> extends AbstractCollectionSpa
             ServiceContext<IT, OT> ctx = createServiceContext(parentCtx, theUpdate, objectClass, ui);
             DocumentHandler handler = createDocumentHandler(ctx);
             getStorageClient(ctx).update(ctx, csid, handler);
-            return ctx.getOutput();
+            if (sanitize == true) {
+               result = sanitize(handler, ctx.getOutput());
+            } else {
+               result = ctx.getOutput();
+            }
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.PUT_FAILED, csid);
         }
+        
+        return result;
     }
 
     protected ServiceContext<IT, OT> createServiceContext(
index 17ba6aea3c26245042c85cd85acfd4992e1224f4..fd0cd6dadfbf7ab18a014125dddd3be9aa84165c 100644 (file)
@@ -290,8 +290,11 @@ public class RemoteServiceContextImpl<IT, OT>
                        TransactionContext transactionCtx = getCurrentTransactionContext();
                        if (transactionCtx != null) {
                                if (--transactionConnectionRefCount == 0) {
-                                       transactionCtx.close();
-                               this.setProperty(StorageClient.SC_TRANSACTION_CONTEXT_KEY, null);
+                                       try {
+                                               transactionCtx.close();
+                                       } finally {
+                                       this.setProperty(StorageClient.SC_TRANSACTION_CONTEXT_KEY, null);
+                                       }
                                }
                        } else {
                                throw new TransactionException("Attempted to release a non-existent storage connection.  Transaction context missing from service context.");
index 86665d0ac40dac6729175b84bde1ed900aaee9cb..b963929a3be0368a2e76afbdf33549cf3c823b66 100644 (file)
@@ -256,11 +256,13 @@ public class JpaStorageClientImpl implements StorageClient {
             handler.complete(Action.GET_ALL, wrapDoc);
             jpaConnectionContext.commitTransaction();
         } catch (DocumentException de) {
+               jpaConnectionContext.markForRollback();
             throw de;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
                 logger.debug("Caught exception ", e);
             }
+            jpaConnectionContext.markForRollback();
             throw new DocumentException(e);
         } finally {
             ctx.closeConnection();