From e6856586c24f027aa824da0ef3b796d328632290 Mon Sep 17 00:00:00 2001 From: Sanjay Dalal Date: Tue, 8 Dec 2009 00:44:46 +0000 Subject: [PATCH] CSPACE-580 account is now able to update password only (for CSIP). update requires admin privileges. test: account test M account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java M account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java M account/service/src/main/java/org/collectionspace/services/account/AccountResource.java M account/client/src/test/java/org/collectionspace/services/client/test/AccountServiceTest.java --- .../client/test/AccountServiceTest.java | 97 ++++++++++++++++- .../services/account/AccountResource.java | 6 +- .../storage/AccountDocumentHandler.java | 3 +- .../account/storage/AccountStorageClient.java | 102 ++++++++++++++++-- 4 files changed, 193 insertions(+), 15 deletions(-) diff --git a/services/account/client/src/test/java/org/collectionspace/services/client/test/AccountServiceTest.java b/services/account/client/src/test/java/org/collectionspace/services/client/test/AccountServiceTest.java index 9d13184cf..bf5ac4ab8 100644 --- a/services/account/client/src/test/java/org/collectionspace/services/client/test/AccountServiceTest.java +++ b/services/account/client/src/test/java/org/collectionspace/services/client/test/AccountServiceTest.java @@ -276,16 +276,63 @@ public class AccountServiceTest extends AbstractServiceTest { Assert.assertEquals(updatedAccount.getEmail(), toUpdateAccount.getEmail(), "Data in updated object did not match submitted data."); - } @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class, dependsOnMethods = {"update"}) - public void deactivate(String testName) throws Exception { + public void updatePassword(String testName) throws Exception { // Perform setup. setupUpdate(testName); + ClientResponse res = + client.read(knownResourceId); + if (logger.isDebugEnabled()) { + logger.debug(testName + ": read status = " + res.getStatus()); + } + Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE); + + if (logger.isDebugEnabled()) { + logger.debug("got object to update with ID: " + knownResourceId); + } + AccountsCommon toUpdateAccount = + (AccountsCommon) res.getEntity(); + Assert.assertNotNull(toUpdateAccount); + + //change password + toUpdateAccount.setPassword(Base64.encodeBase64("imagination".getBytes())); + if (logger.isDebugEnabled()) { + logger.debug("updated object"); + logger.debug(objectAsXmlString(toUpdateAccount, + AccountsCommon.class)); + } + + // Submit the request to the service and store the response. + res = client.update(knownResourceId, toUpdateAccount); + int statusCode = res.getStatus(); + // Check the status code of the response: does it match the expected response(s)? + if (logger.isDebugEnabled()) { + logger.debug(testName + ": status = " + statusCode); + } + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); + + + AccountsCommon updatedAccount = (AccountsCommon) res.getEntity(); + Assert.assertNotNull(updatedAccount); + +// Assert.assertEquals(updatedAccount.getPassword(), +// toUpdateAccount.getPassword(), +// "Data in updated object did not match submitted data."); + } + + @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class, + dependsOnMethods = {"updatePassword"}) + public void deactivate(String testName) throws Exception { + + // Perform setup. + setupUpdate(testName); ClientResponse res = client.read(knownResourceId); @@ -373,6 +420,49 @@ public class AccountServiceTest extends AbstractServiceTest { Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); } + @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class, + dependsOnMethods = {"deactivate", "readNonExistent", "testSubmitRequest"}) + public void updateWrongUser(String testName) throws Exception { + + setupUpdate(); + // Submit the request to the service and store the response. + // + // Note: The ID used in this 'create' call may be arbitrary. + // The only relevant ID may be the one used in updateAccount(), below. + ClientResponse res = + client.read(knownResourceId); + if (logger.isDebugEnabled()) { + logger.debug(testName + ": read status = " + res.getStatus()); + } + Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE); + + if (logger.isDebugEnabled()) { + logger.debug("got object to update with ID: " + knownResourceId); + } + AccountsCommon toUpdateAccount = + (AccountsCommon) res.getEntity(); + Assert.assertNotNull(toUpdateAccount); + + toUpdateAccount.setUserId("barneyFake"); + if (logger.isDebugEnabled()) { + logger.debug("updated object with wrongUser"); + logger.debug(objectAsXmlString(toUpdateAccount, + AccountsCommon.class)); + } + EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode(); + res = client.update(knownResourceId, toUpdateAccount); + int statusCode = res.getStatus(); + + // Check the status code of the response: does it match + // the expected response(s)? + if (logger.isDebugEnabled()) { + logger.debug(testName + ": status = " + statusCode); + } + Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode), + invalidStatusCodeMessage(REQUEST_TYPE, statusCode)); + Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE); + } + // --------------------------------------------------------------- // CRUD tests : DELETE tests // --------------------------------------------------------------- @@ -461,8 +551,7 @@ public class AccountServiceTest extends AbstractServiceTest { account.setLastName(lastName); account.setScreenName(screenName); account.setUserId(screenName); - byte[] b64passwd = Base64.encodeBase64(passwd.getBytes()); - account.setPassword(b64passwd); + account.setPassword(Base64.encodeBase64(passwd.getBytes())); account.setEmail(email); account.setPhone("1234567890"); if (logger.isDebugEnabled()) { 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 b1d4a7a27..dca0561d1 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 @@ -42,6 +42,7 @@ import org.collectionspace.services.account.storage.AccountStorageClient; import org.collectionspace.services.common.AbstractCollectionSpaceResource; import org.collectionspace.services.common.context.RemoteServiceContextImpl; import org.collectionspace.services.common.context.ServiceContext; +import org.collectionspace.services.common.document.BadRequestException; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentHandler; @@ -211,11 +212,14 @@ public class AccountResource DocumentHandler handler = createDocumentHandler(ctx); getStorageClient(ctx).update(ctx, csid, handler); result = (AccountsCommon) ctx.getOutput(); + } catch (BadRequestException bre) { + Response response = Response.status( + Response.Status.BAD_REQUEST).entity("Update failed reason " + bre.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (UnauthorizedException ue) { Response response = Response.status( Response.Status.UNAUTHORIZED).entity("Update failed reason " + ue.getErrorReason()).type("text/plain").build(); throw new WebApplicationException(response); - } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("caugth exception in updateAccount", dnfe); diff --git a/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java b/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java index 2bc63ae64..bdc735a85 100644 --- a/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java +++ b/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java @@ -53,12 +53,12 @@ public class AccountDocumentHandler @Override public void handleUpdate(DocumentWrapper wrapDoc) throws Exception { - getServiceContext().setOutput(account); } @Override public void completeUpdate(DocumentWrapper wrapDoc) throws Exception { AccountsCommon upAcc = wrapDoc.getWrappedObject(); + getServiceContext().setOutput(account); sanitize(upAcc); } @@ -145,5 +145,6 @@ public class AccountDocumentHandler */ private void sanitize(AccountsCommon account) { account.setTenantid(""); + account.setPassword(null); } } diff --git a/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java b/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java index bda4a6234..f069b0f9e 100644 --- a/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java +++ b/services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java @@ -25,6 +25,7 @@ package org.collectionspace.services.account.storage; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +import javax.persistence.NoResultException; import javax.persistence.Query; import org.apache.commons.codec.binary.Base64; import org.collectionspace.services.account.AccountsCommon; @@ -32,6 +33,7 @@ import org.collectionspace.services.authentication.User; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.BadRequestException; 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.DocumentHandler.Action; import org.collectionspace.services.common.document.DocumentNotFoundException; @@ -104,6 +106,60 @@ public class AccountStorageClient extends JpaStorageClient { } } + @Override + public void update(ServiceContext ctx, String id, DocumentHandler handler) + throws BadRequestException, DocumentNotFoundException, + DocumentException { + String docType = ctx.getDocumentType(); + if (docType == null) { + throw new DocumentNotFoundException( + "Unable to find DocumentType for service " + ctx.getServiceName()); + } + if (handler == null) { + throw new IllegalArgumentException( + "AccountStorageClient.update: handler is missing"); + } + EntityManagerFactory emf = null; + EntityManager em = null; + try { + handler.prepare(Action.UPDATE); + AccountsCommon account = (AccountsCommon) handler.getCommonPart(); + DocumentWrapper wrapDoc = + new DocumentWrapperImpl(account); + setCsid(account, id); //set id just in case it was not populated by consumer + handler.handle(Action.UPDATE, wrapDoc); + emf = getEntityManagerFactory(); + em = emf.createEntityManager(); + em.getTransaction().begin(); + AccountsCommon accountFound = getAccount(em, id); + + checkAllowedUpdates(account, accountFound); + //if userid and password are given, add to default id provider + if (account.getUserId() != null && account.getPassword() != null) { + + User userFound = getUser(em, account); + User user = createUser(account, ctx.getTenantId()); + em.merge(user); + } + em.merge(account); + em.getTransaction().commit(); + handler.complete(Action.UPDATE, wrapDoc); + } catch (BadRequestException bre) { + throw bre; + } catch (DocumentException de) { + throw de; + } catch (Exception e) { + if (logger.isDebugEnabled()) { + logger.debug("Caught exception ", e); + } + throw new DocumentException(e); + } finally { + if (emf != null) { + releaseEntityManagerFactory(emf); + } + } + } + @Override public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException, @@ -124,15 +180,7 @@ public class AccountStorageClient extends JpaStorageClient { em = emf.createEntityManager(); //TODO investigate if deep delete is possible //query an delete is inefficient - AccountsCommon accountFound = em.find(AccountsCommon.class, id); - if (accountFound == null) { - if (em != null && em.getTransaction().isActive()) { - em.getTransaction().rollback(); - } - String msg = "could not find entity with id=" + id; - logger.error(msg); - throw new DocumentNotFoundException(msg); - } + AccountsCommon accountFound = getAccount(em, id); StringBuilder accDelStr = new StringBuilder("DELETE FROM "); accDelStr.append(getEntityName(ctx)); @@ -193,6 +241,29 @@ public class AccountStorageClient extends JpaStorageClient { } } + private AccountsCommon getAccount(EntityManager em, String id) throws DocumentNotFoundException { + AccountsCommon accountFound = em.find(AccountsCommon.class, id); + if (accountFound == null) { + if (em != null && em.getTransaction().isActive()) { + em.getTransaction().rollback(); + } + String msg = "could not find account with id=" + id; + logger.error(msg); + throw new DocumentNotFoundException(msg); + } + return accountFound; + } + + private boolean checkAllowedUpdates(AccountsCommon toAccount, AccountsCommon fromAccount) throws BadRequestException { + if (!fromAccount.getUserId().equals(toAccount.getUserId())) { + String msg = "User id " + toAccount.getUserId() + " not found!"; + logger.error(msg); + logger.debug(msg + " found userid=" + fromAccount.getUserId()); + throw new BadRequestException(msg); + } + return true; + } + private User createUser(AccountsCommon account, String tenantId) { User user = new User(); user.setTenantid(tenantId); @@ -204,4 +275,17 @@ public class AccountStorageClient extends JpaStorageClient { user.setPasswd(secEncPasswd); return user; } + + private User getUser(EntityManager em, AccountsCommon account) throws DocumentNotFoundException { + User userFound = em.find(User.class, account.getUserId()); + if (userFound == null) { + if (em != null && em.getTransaction().isActive()) { + em.getTransaction().rollback(); + } + String msg = "could not find user with id=" + account.getUserId(); + logger.error(msg); + throw new DocumentNotFoundException(msg); + } + return userFound; + } } -- 2.47.3