From 673137edf7635c19786713b200a44f1fca545d06 Mon Sep 17 00:00:00 2001 From: Sanjay Dalal Date: Tue, 1 Dec 2009 21:45:08 +0000 Subject: [PATCH] CSPACE-642 a user on login is associated with a tenant Account service now associates a user with tenant on account creation time if default identity provider is used. This association is retrieved (CSpacePrincipal) at the time of login. Tenant binding is retrieved using the tenant id established after login. Moved db schema for default id provider to authentication/client. Introduced ServiceException to capture error code and error reason. UnauthorizedException with 401 (derived from ServiceException) is thrown if tenant could not be found on login. Rest of the common exceptions are derived from ServiceException. Service resources changed to handle UnauthorizedException. test: authentication client with security enabled on server (web.xml), all service tests without security --- pom.xml | 8 + .../services/account/AccountResource.java | 33 +++- .../account/storage/AccountStorageClient.java | 6 +- .../acquisition/AcquisitionResource.java | 23 ++- services/authentication/build.xml | 4 +- services/authentication/client/build.xml | 178 ++++++++++++++++++ services/authentication/client/pom.xml | 78 +++++++- .../resources/db/mysql/authentication.sql | 6 + .../main/resources/db/mysql/test_authn.sql | 14 ++ .../test/resources/META-INF/persistence.xml | 19 ++ .../src/test/resources/hibernate.cfg.xml | 24 +++ .../authentication_identity_provider.xsd | 49 ++++- services/authentication/service/build.xml | 23 --- services/authentication/service/pom.xml | 9 + .../authentication/CSpaceDBLoginModule.java | 125 ++++++------ .../authentication/CSpacePrincipal.java | 80 ++++++++ .../resources/config/jboss-login-config.xml | 31 +-- .../resources/db/mysql/authentication.sql | 18 -- .../main/resources/db/mysql/test_authn.sql | 14 -- .../CollectionObjectResource.java | 21 +++ services/common/pom.xml | 7 +- .../services/common/ServiceException.java | 136 +++++++++++++ .../context/AbstractServiceContext.java | 60 +++++- .../context/MultipartServiceContextImpl.java | 5 +- .../context/RemoteServiceContextImpl.java | 3 +- .../common/document/BadRequestException.java | 13 +- .../common/document/DocumentException.java | 41 ++-- .../document/DocumentNotFoundException.java | 9 +- .../security/ServiceForbiddenException.java | 92 +++++++++ .../security/UnauthorizedException.java | 91 +++++++++ .../services/intake/IntakeResource.java | 23 ++- services/pom.xml | 2 +- .../relation/NewRelationResource.java | 23 ++- .../vocabulary/VocabularyResource.java | 61 +++++- 34 files changed, 1120 insertions(+), 209 deletions(-) create mode 100644 services/authentication/client/build.xml create mode 100644 services/authentication/client/src/main/resources/db/mysql/authentication.sql create mode 100644 services/authentication/client/src/main/resources/db/mysql/test_authn.sql create mode 100644 services/authentication/client/src/test/resources/META-INF/persistence.xml create mode 100644 services/authentication/client/src/test/resources/hibernate.cfg.xml create mode 100644 services/authentication/service/src/main/java/org/collectionspace/authentication/CSpacePrincipal.java delete mode 100644 services/authentication/service/src/main/resources/db/mysql/authentication.sql delete mode 100644 services/authentication/service/src/main/resources/db/mysql/test_authn.sql create mode 100644 services/common/src/main/java/org/collectionspace/services/common/ServiceException.java create mode 100644 services/common/src/main/java/org/collectionspace/services/common/security/ServiceForbiddenException.java create mode 100644 services/common/src/main/java/org/collectionspace/services/common/security/UnauthorizedException.java diff --git a/pom.xml b/pom.xml index a4f601270..31a485ee0 100644 --- a/pom.xml +++ b/pom.xml @@ -123,6 +123,14 @@ false + + + jboss + http://repository.jboss.com/maven2 + + false + + mojo mojo repo 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 e44155e69..b1d4a7a27 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 @@ -40,12 +40,12 @@ import javax.ws.rs.core.UriInfo; import org.collectionspace.services.account.storage.AccountHandlerFactory; import org.collectionspace.services.account.storage.AccountStorageClient; import org.collectionspace.services.common.AbstractCollectionSpaceResource; -import org.collectionspace.services.common.context.MultipartServiceContext; import org.collectionspace.services.common.context.RemoteServiceContextImpl; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentHandler; +import org.collectionspace.services.common.security.UnauthorizedException; import org.collectionspace.services.common.storage.StorageClient; import org.jboss.resteasy.util.HttpResponseCodes; import org.slf4j.Logger; @@ -66,7 +66,7 @@ public class AccountResource return serviceName; } - private ServiceContext createServiceContext(T obj) { + private ServiceContext createServiceContext(T obj) throws Exception { ServiceContext ctx = new RemoteServiceContextImpl(getServiceName()); ctx.setInput(obj); ctx.setDocumentType(AccountsCommon.class.getPackage().getName()); //persistence unit @@ -99,6 +99,10 @@ public class AccountResource path.path("" + csid); Response response = Response.created(path.build()).build(); return response; + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in createAccount", e); @@ -128,7 +132,11 @@ public class AccountResource ServiceContext ctx = createServiceContext((AccountsCommon) null); DocumentHandler handler = createDocumentHandler(ctx); getStorageClient(ctx).get(ctx, csid, handler); - result = (AccountsCommon)ctx.getOutput(); + result = (AccountsCommon) ctx.getOutput(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("getAccount", dnfe); @@ -165,7 +173,12 @@ public class AccountResource DocumentFilter myFilter = new DocumentFilter(); handler.setDocumentFilter(myFilter); getStorageClient(ctx).getFiltered(ctx, handler); - accountList = (AccountsCommonList)handler.getCommonPartList(); + accountList = (AccountsCommonList) handler.getCommonPartList(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); + } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in getAccountList", e); @@ -197,7 +210,12 @@ public class AccountResource ServiceContext ctx = createServiceContext(theUpdate); DocumentHandler handler = createDocumentHandler(ctx); getStorageClient(ctx).update(ctx, csid, handler); - result = (AccountsCommon)ctx.getOutput(); + result = (AccountsCommon) ctx.getOutput(); + } 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); @@ -232,6 +250,11 @@ public class AccountResource ServiceContext ctx = createServiceContext((AccountsCommon) null); getStorageClient(ctx).delete(ctx, csid); return Response.status(HttpResponseCodes.SC_OK).build(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); + } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("caught exception in deleteAccount", dnfe); 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 8131f10ff..bda4a6234 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 @@ -28,7 +28,6 @@ import javax.persistence.EntityManagerFactory; import javax.persistence.Query; import org.apache.commons.codec.binary.Base64; import org.collectionspace.services.account.AccountsCommon; -import org.collectionspace.services.account.AccountsCommon; import org.collectionspace.services.authentication.User; import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.BadRequestException; @@ -82,7 +81,7 @@ public class AccountStorageClient extends JpaStorageClient { em.getTransaction().begin(); //if userid and password are given, add to default id provider if (account.getUserId() != null && account.getPassword() != null) { - User user = createUser(account); + User user = createUser(account, ctx.getTenantId()); em.persist(user); } account.setTenantid(ctx.getTenantId()); @@ -194,8 +193,9 @@ public class AccountStorageClient extends JpaStorageClient { } } - private User createUser(AccountsCommon account) { + private User createUser(AccountsCommon account, String tenantId) { User user = new User(); + user.setTenantid(tenantId); user.setUsername(account.getUserId()); byte[] bpass = Base64.decodeBase64(account.getPassword()); SecurityUtils.validatePassword(new String(bpass)); diff --git a/services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java b/services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java index 26ef178a1..aa722c1b6 100644 --- a/services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java +++ b/services/acquisition/service/src/main/java/org/collectionspace/services/acquisition/AcquisitionResource.java @@ -44,6 +44,7 @@ import org.collectionspace.services.common.context.MultipartServiceContextFactor import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentHandler; +import org.collectionspace.services.common.security.UnauthorizedException; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; import org.jboss.resteasy.util.HttpResponseCodes; @@ -70,7 +71,7 @@ public class AcquisitionResource ctx.getRepositoryClientType().toString()); docHandler.setServiceContext(ctx); if (ctx.getInput() != null) { - Object obj = ((MultipartServiceContext)ctx).getInputPart(ctx.getCommonPartLabel(), AcquisitionsCommon.class); + Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), AcquisitionsCommon.class); if (obj != null) { docHandler.setCommonPart((AcquisitionsCommon) obj); } @@ -93,6 +94,10 @@ public class AcquisitionResource path.path("" + csid); Response response = Response.created(path.build()).build(); return response; + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in createAcquisition", e); @@ -123,6 +128,10 @@ public class AcquisitionResource DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).get(ctx, csid, handler); result = (MultipartOutput) ctx.getOutput(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("getAcquisition", dnfe); @@ -158,6 +167,10 @@ public class AcquisitionResource DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).getAll(ctx, handler); acquisitionObjectList = (AcquisitionsCommonList) handler.getCommonPartList(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in getAcquisitionList", e); @@ -193,6 +206,10 @@ public class AcquisitionResource DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).update(ctx, csid, handler); result = (MultipartOutput) ctx.getOutput(); + } 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 updateAcquisition", dnfe); @@ -227,6 +244,10 @@ public class AcquisitionResource ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName()); getRepositoryClient(ctx).delete(ctx, csid); return Response.status(HttpResponseCodes.SC_OK).build(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("caught exception in deleteAcquisition", dnfe); diff --git a/services/authentication/build.xml b/services/authentication/build.xml index 5a88b75ae..6d4ccff2b 100644 --- a/services/authentication/build.xml +++ b/services/authentication/build.xml @@ -108,16 +108,18 @@ - + + + diff --git a/services/authentication/client/build.xml b/services/authentication/client/build.xml new file mode 100644 index 000000000..6736c399f --- /dev/null +++ b/services/authentication/client/build.xml @@ -0,0 +1,178 @@ + + + + collectionspace authentication service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/services/authentication/client/pom.xml b/services/authentication/client/pom.xml index b3ff5a885..d3fd746cd 100644 --- a/services/authentication/client/pom.xml +++ b/services/authentication/client/pom.xml @@ -14,7 +14,10 @@ org.collectionspace.services.authentication.client 1.0 services.authentication.client - + + authentication.sql + ${basedir}/src/main/resources/db/mysql + @@ -27,6 +30,11 @@ slf4j-log4j12 test + + org.collectionspace.services + org.collectionspace.services.authentication.jaxb + 1.0 + org.collectionspace.services org.collectionspace.services.client @@ -70,6 +78,10 @@ commons-httpclient 3.1 + + mysql + mysql-connector-java + @@ -97,5 +109,69 @@ + + + + ddl + + + + org.codehaus.mojo + hibernate3-maven-plugin + 2.2 + + + process-test-resources + + hbm2ddl + + + + + + + hbm2ddl + + + + ${sql.file} + jpaconfiguration + true + true + true + true + false + org.collectionspace.services.authentication + + + + + mysql + mysql-connector-java + 5.0.5 + + + + + maven-antrun-plugin + + + process-test-resources + + + + + + + run + + + + + + + + + diff --git a/services/authentication/client/src/main/resources/db/mysql/authentication.sql b/services/authentication/client/src/main/resources/db/mysql/authentication.sql new file mode 100644 index 000000000..863a09caa --- /dev/null +++ b/services/authentication/client/src/main/resources/db/mysql/authentication.sql @@ -0,0 +1,6 @@ +drop table if exists roles; +drop table if exists users; +drop table if exists users_roles; +create table roles (rolename varchar(255) not null, rolegroup varchar(255) not null, tenantid varchar(255) not null, primary key (rolename)); +create table users (username varchar(255) not null, passwd varchar(128) not null, tenantid varchar(255) not null, primary key (username)); +create table users_roles (HJID bigint not null auto_increment, rolename varchar(255) not null, tenantid varchar(255) not null, username varchar(255) not null, primary key (HJID)); diff --git a/services/authentication/client/src/main/resources/db/mysql/test_authn.sql b/services/authentication/client/src/main/resources/db/mysql/test_authn.sql new file mode 100644 index 000000000..dde95566a --- /dev/null +++ b/services/authentication/client/src/main/resources/db/mysql/test_authn.sql @@ -0,0 +1,14 @@ +-- +-- Copyright 2009 University of California at Berkeley +-- Licensed under the Educational Community License (ECL), Version 2.0. +-- You may not use this file except in compliance with this License. +-- +use cspace; + +INSERT INTO `users` (`username`,`passwd`, `tenantid`) VALUES ('test','n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=', '1'); + +insert into roles (rolename, rolegroup, `tenantid`) values ('collections_manager', 'collections', '1'); +insert into roles (rolename, rolegroup, `tenantid`) values ('collections_registrar', 'collections', '1'); + +insert into users_roles(username, rolename, `tenantid`) values ('test', 'collections_manager', '1'); +insert into users_roles(username, rolename, `tenantid`) values('admin', 'collections_registrar', '1'); \ No newline at end of file diff --git a/services/authentication/client/src/test/resources/META-INF/persistence.xml b/services/authentication/client/src/test/resources/META-INF/persistence.xml new file mode 100644 index 000000000..97d00a01d --- /dev/null +++ b/services/authentication/client/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,19 @@ + + + + org.collectionspace.services.authentication.User + org.collectionspace.services.authentication.Role + org.collectionspace.services.authentication.UserRole + + + + + + + diff --git a/services/authentication/client/src/test/resources/hibernate.cfg.xml b/services/authentication/client/src/test/resources/hibernate.cfg.xml new file mode 100644 index 000000000..9c2b94e2c --- /dev/null +++ b/services/authentication/client/src/test/resources/hibernate.cfg.xml @@ -0,0 +1,24 @@ + + + + + + + jdbc:mysql://localhost:3306/cspace + com.mysql.jdbc.Driver + test + test + org.hibernate.dialect.MySQLDialect + org.hibernate.transaction.JDBCTransactionFactory + thread + true + + diff --git a/services/authentication/jaxb/src/main/resources/authentication_identity_provider.xsd b/services/authentication/jaxb/src/main/resources/authentication_identity_provider.xsd index a49a1e755..e50ed0fa7 100644 --- a/services/authentication/jaxb/src/main/resources/authentication_identity_provider.xsd +++ b/services/authentication/jaxb/src/main/resources/authentication_identity_provider.xsd @@ -37,11 +37,24 @@ + + + + + + + + + + + + + - + @@ -69,11 +82,24 @@ + + + + + + + + + + + + + - + @@ -82,7 +108,7 @@ - + @@ -101,11 +127,24 @@ + + + + + + + + + + + + + - + @@ -114,7 +153,7 @@ - + diff --git a/services/authentication/service/build.xml b/services/authentication/service/build.xml index 5bbd99dd8..a10f3150a 100644 --- a/services/authentication/service/build.xml +++ b/services/authentication/service/build.xml @@ -108,29 +108,6 @@ - - - - - - - - - - - - diff --git a/services/authentication/service/pom.xml b/services/authentication/service/pom.xml index 79b335f65..d0574ba17 100644 --- a/services/authentication/service/pom.xml +++ b/services/authentication/service/pom.xml @@ -35,6 +35,8 @@ test + + javax.security @@ -42,6 +44,13 @@ 1.0.01 provided + + + + org.jboss.logging + jboss-logging-log4j + 2.1.0.GA + jboss jbosssx diff --git a/services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceDBLoginModule.java b/services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceDBLoginModule.java index 1d2a7d3dd..6ef9ba827 100644 --- a/services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceDBLoginModule.java +++ b/services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceDBLoginModule.java @@ -32,26 +32,28 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; +import java.util.Map; import javax.naming.InitialContext; import javax.naming.NamingException; +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginException; import javax.sql.DataSource; import org.jboss.security.SimpleGroup; import org.jboss.security.SimplePrincipal; import org.jboss.security.auth.spi.DatabaseServerLoginModule; -//import org.slf4j.Logger; -//import org.slf4j.LoggerFactory; +/** + * CollectionSpace default identity provider supporting multi-tenancy + * @author + */ public class CSpaceDBLoginModule extends DatabaseServerLoginModule { + protected String tenantQuery = "select tenantid from users where username=?"; //disabled due to classloading problem // private Logger logger = LoggerFactory.getLogger(CSpaceDBLoginModule.class); - private boolean log = true; //logger.isDebugEnabled(); - - private void log(String str) { - System.out.println(str); - } + private String tenantId; protected String getUsersPassword() throws LoginException { @@ -60,38 +62,33 @@ public class CSpaceDBLoginModule extends DatabaseServerLoginModule { Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; - InitialContext ctx = null; try { - - ctx = new InitialContext(); - DataSource ds = (DataSource) ctx.lookup(dsJndiName); - if (ds == null) { - throw new IllegalArgumentException("datasource not found: " + dsJndiName); - } - conn = ds.getConnection(); + conn = getConnection(); // Get the password - if (log) { - log("Executing query: " + principalsQuery + ", with username: " + username); + if (log.isDebugEnabled()) { + log.debug("Executing query: " + principalsQuery + ", with username: " + username); } ps = conn.prepareStatement(principalsQuery); ps.setString(1, username); rs = ps.executeQuery(); if (rs.next() == false) { - if (log) { - log("Query returned no matches from db"); + if (log.isDebugEnabled()) { + log.debug(principalsQuery + " returned no matches from db"); } throw new FailedLoginException("No matching username found"); } password = rs.getString(1); password = convertRawPassword(password); - if (log) { - log("Obtained user password"); + if (log.isDebugEnabled()) { + log.debug("Obtained user password"); } - } catch (NamingException ex) { - LoginException le = new LoginException("Error looking up DataSource from: " + dsJndiName); - le.initCause(ex); - throw le; + tenantId = rs.getString(2); + if (log.isDebugEnabled()) { + log.debug("Obtained tenantId"); + } + CSpacePrincipal principal = (CSpacePrincipal)getIdentity(); + principal.setTenantId(tenantId); } catch (SQLException ex) { LoginException le = new LoginException("Query failed"); le.initCause(ex); @@ -119,12 +116,6 @@ public class CSpaceDBLoginModule extends DatabaseServerLoginModule { } catch (SQLException ex) { } } - if (ctx != null) { - try { - ctx.close(); - } catch (Exception e) { - } - } } return password; } @@ -136,8 +127,8 @@ public class CSpaceDBLoginModule extends DatabaseServerLoginModule { */ protected Group[] getRoleSets() throws LoginException { String username = getUsername(); - if (log) { - log("getRoleSets using rolesQuery: " + rolesQuery + ", username: " + username); + if (log.isDebugEnabled()) { + log.debug("getRoleSets using rolesQuery: " + rolesQuery + ", username: " + username); } Connection conn = null; @@ -146,24 +137,23 @@ public class CSpaceDBLoginModule extends DatabaseServerLoginModule { ResultSet rs = null; try { - InitialContext ctx = new InitialContext(); - DataSource ds = (DataSource) ctx.lookup(dsJndiName); - conn = ds.getConnection(); + conn = getConnection(); // Get the user role names - if (log) { - log("Executing query: " + rolesQuery + ", with username: " + username); + if (log.isDebugEnabled()) { + log.debug("Executing query: " + rolesQuery + ", with username: " + username); } ps = conn.prepareStatement(rolesQuery); try { ps.setString(1, username); + ps.setString(2, tenantId); } catch (ArrayIndexOutOfBoundsException ignore) { // The query may not have any parameters so just try it } rs = ps.executeQuery(); if (rs.next() == false) { - if (log) { - log("No roles found"); + if (log.isDebugEnabled()) { + log.debug("No roles found"); } // if(aslm.getUnauthenticatedIdentity() == null){ // throw new FailedLoginException("No matching username found in Roles"); @@ -192,20 +182,16 @@ public class CSpaceDBLoginModule extends DatabaseServerLoginModule { try { // Principal p = aslm.createIdentity(name); Principal p = createIdentity(name); - if (log) { - log("Assign user to role " + name); + if (log.isDebugEnabled()) { + log.debug("Assign user to role " + name); } group.addMember(p); } catch (Exception e) { - log("Failed to create principal: " + name + " " + e.toString()); + log.error("Failed to create principal: " + name + " " + e.toString()); } } while (rs.next()); - } catch (NamingException ex) { - LoginException le = new LoginException("Error looking up DataSource from: " + dsJndiName); - le.initCause(ex); - throw le; } catch (SQLException ex) { LoginException le = new LoginException("Query failed"); le.initCause(ex); @@ -237,29 +223,30 @@ public class CSpaceDBLoginModule extends DatabaseServerLoginModule { return roleSets; } - /** Utility method to create a Principal for the given username. This - * creates an instance of the principalClassName type if this option was - * specified using the class constructor matching: ctor(String). If - * principalClassName was not specified, a SimplePrincipal is created. - * - * @param username the name of the principal - * @return the principal instance - * @throws java.lang.Exception thrown if the custom principal type cannot be created. - */ - protected Principal createIdentity(String username) - throws Exception { - Principal p = null; - if (principalClassName == null) { - p = new SimplePrincipal(username); - } else { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - Class clazz = loader.loadClass(principalClassName); - Class[] ctorSig = {String.class}; - Constructor ctor = clazz.getConstructor(ctorSig); - Object[] ctorArgs = {username}; - p = (Principal) ctor.newInstance(ctorArgs); + + private Connection getConnection() throws LoginException, SQLException { + InitialContext ctx = null; + Connection conn = null; + try { + ctx = new InitialContext(); + DataSource ds = (DataSource) ctx.lookup(dsJndiName); + if (ds == null) { + throw new IllegalArgumentException("datasource not found: " + dsJndiName); + } + conn = ds.getConnection(); + return conn; + } catch (NamingException ex) { + LoginException le = new LoginException("Error looking up DataSource from: " + dsJndiName); + le.initCause(ex); + throw le; + } finally { + if (ctx != null) { + try { + ctx.close(); + } catch (Exception e) { + } + } } - return p; } } diff --git a/services/authentication/service/src/main/java/org/collectionspace/authentication/CSpacePrincipal.java b/services/authentication/service/src/main/java/org/collectionspace/authentication/CSpacePrincipal.java new file mode 100644 index 000000000..d99219493 --- /dev/null +++ b/services/authentication/service/src/main/java/org/collectionspace/authentication/CSpacePrincipal.java @@ -0,0 +1,80 @@ +/** + * This document is a part of the source code and related artifacts + * for CollectionSpace, an open source collections management system + * for museums and related institutions: + + * http://www.collectionspace.org + * http://wiki.collectionspace.org + + * Copyright 2009 University of California at Berkeley + + * Licensed under the Educational Community License (ECL), Version 2.0. + * You may not use this file except in compliance with this License. + + * You may obtain a copy of the ECL 2.0 License at + + * https://source.collectionspace.org/collection-space/LICENSE.txt + + * 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.collectionspace.authentication; + +import java.security.Principal; + +/** + * CSpacePrincipal provides additional tenant-specific context to application + * @author + */ +public class CSpacePrincipal + implements Principal, java.io.Serializable { + + private String name; + private String tenantId; + + public CSpacePrincipal(String name) { + this.name = name; + } + + public int hashCode() { + return name.hashCode(); + } + + public boolean equals(Object obj) { + Principal p = (Principal) obj; + return name.equals(p.getName()); + } + + public String toString() { + return name; + } + + /** + * Returns the name of this principal. + * + * @return the name of this principal. + */ + public String getName() { + return name; + } + + /** + * Returns the id of the tenant this principal is associated with + * @return + */ + public String getTenantId() { + return tenantId; + } + + /** + * Set the id for the tenant to which princiapal is associated with + * The access to this method must be package private + * @param tenantId + */ + void setTenantId(String tenantId) { + this.tenantId = tenantId; + } +} diff --git a/services/authentication/service/src/main/resources/config/jboss-login-config.xml b/services/authentication/service/src/main/resources/config/jboss-login-config.xml index 4efd48078..9d4221a70 100644 --- a/services/authentication/service/src/main/resources/config/jboss-login-config.xml +++ b/services/authentication/service/src/main/resources/config/jboss-login-config.xml @@ -16,19 +16,20 @@ copy the following snippet into $JBOSS_HOME/server/cspace/conf/login-config.xml copy before the "other" application-policy --> - - - + + - CspaceDS - SHA-256 - false - - select passwd from users where username=? - - - select rolename, 'Roles' from users_roles where username=? - - - - + CspaceDS + SHA-256 + false + org.collectionspace.authentication.CSpacePrincipal + + select passwd, tenantid from users where username=? + + + select rolename, 'Roles' from users_roles where username=? and tenantid=? + + + + diff --git a/services/authentication/service/src/main/resources/db/mysql/authentication.sql b/services/authentication/service/src/main/resources/db/mysql/authentication.sql deleted file mode 100644 index aa853867a..000000000 --- a/services/authentication/service/src/main/resources/db/mysql/authentication.sql +++ /dev/null @@ -1,18 +0,0 @@ --- --- Copyright 2009 University of California at Berkeley --- Licensed under the Educational Community License (ECL), Version 2.0. --- You may not use this file except in compliance with this License. --- -use cspace; - -DROP TABLE IF EXISTS users; -CREATE TABLE users(username VARCHAR(512) PRIMARY KEY, passwd VARCHAR(128) NOT NULL ); -CREATE INDEX username_users on users(username); - -DROP TABLE IF EXISTS roles; -CREATE TABLE roles(rolename VARCHAR(128) PRIMARY KEY, rolegroup VARCHAR(128)); -CREATE INDEX rolename_roles on roles(rolename); - -DROP TABLE IF EXISTS users_roles; -CREATE TABLE users_roles(username VARCHAR(512) NOT NULL, rolename VARCHAR(128) NOT NULL); -CREATE INDEX username_users_roles on users_roles(username); \ No newline at end of file diff --git a/services/authentication/service/src/main/resources/db/mysql/test_authn.sql b/services/authentication/service/src/main/resources/db/mysql/test_authn.sql deleted file mode 100644 index ccdf60982..000000000 --- a/services/authentication/service/src/main/resources/db/mysql/test_authn.sql +++ /dev/null @@ -1,14 +0,0 @@ --- --- Copyright 2009 University of California at Berkeley --- Licensed under the Educational Community License (ECL), Version 2.0. --- You may not use this file except in compliance with this License. --- -use cspace; - -INSERT INTO `users` (`username`,`passwd`) VALUES ('test','n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg='); - -insert into roles (rolename, rolegroup) values ('collections_manager', 'collections'); -insert into roles (rolename, rolegroup) values ('collections_registrar', 'collections'); - -insert into users_roles(username, rolename) values ('test', 'collections_manager'); -insert into users_roles(username, rolename) values('admin', 'collections_registrar'); \ No newline at end of file diff --git a/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java b/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java index efc67f77d..b1fd2c796 100644 --- a/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java +++ b/services/collectionobject/service/src/main/java/org/collectionspace/services/collectionobject/CollectionObjectResource.java @@ -45,6 +45,7 @@ import org.collectionspace.services.common.context.MultipartServiceContextFactor import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentHandler; +import org.collectionspace.services.common.security.UnauthorizedException; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; import org.jboss.resteasy.util.HttpResponseCodes; @@ -89,6 +90,10 @@ public class CollectionObjectResource path.path("" + csid); Response response = Response.created(path.build()).build(); return response; + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in createCollectionObject", e); @@ -119,6 +124,10 @@ public class CollectionObjectResource DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).get(ctx, csid, handler); result = (MultipartOutput) ctx.getOutput(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("getCollectionObject", dnfe); @@ -154,6 +163,10 @@ public class CollectionObjectResource DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).getAll(ctx, handler); collectionObjectList = (CollectionobjectsCommonList) handler.getCommonPartList(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in getCollectionObjectList", e); @@ -186,6 +199,10 @@ public class CollectionObjectResource DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).update(ctx, csid, handler); result = (MultipartOutput) ctx.getOutput(); + } 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 updateCollectionObject", dnfe); @@ -220,6 +237,10 @@ public class CollectionObjectResource ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName()); getRepositoryClient(ctx).delete(ctx, csid); return Response.status(HttpResponseCodes.SC_OK).build(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("caught exception in deleteCollectionObject", dnfe); diff --git a/services/common/pom.xml b/services/common/pom.xml index 2b6c1657c..e9b0f3eee 100644 --- a/services/common/pom.xml +++ b/services/common/pom.xml @@ -76,7 +76,12 @@ 1.0.01 provided - + + javax.security + jacc + 1.0 + provided + - common authentication + common account relation diff --git a/services/relation/service/src/main/java/org/collectionspace/services/relation/NewRelationResource.java b/services/relation/service/src/main/java/org/collectionspace/services/relation/NewRelationResource.java index 552a34210..436ee70be 100644 --- a/services/relation/service/src/main/java/org/collectionspace/services/relation/NewRelationResource.java +++ b/services/relation/service/src/main/java/org/collectionspace/services/relation/NewRelationResource.java @@ -50,6 +50,7 @@ import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.relation.IRelationsManager; import org.collectionspace.services.common.document.DocumentNotFoundException; import org.collectionspace.services.common.document.DocumentHandler; +import org.collectionspace.services.common.security.UnauthorizedException; import org.collectionspace.services.relation.nuxeo.RelationHandlerFactory; import org.jboss.resteasy.plugins.providers.multipart.MultipartInput; import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput; @@ -76,7 +77,7 @@ public class NewRelationResource extends AbstractCollectionSpaceResource { ctx.getRepositoryClientType().toString()); docHandler.setServiceContext(ctx); if (ctx.getInput() != null) { - Object obj = ((MultipartServiceContext)ctx).getInputPart(ctx.getCommonPartLabel(), RelationsCommon.class); + Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), RelationsCommon.class); if (obj != null) { docHandler.setCommonPart((RelationsCommon) obj); } @@ -95,6 +96,10 @@ public class NewRelationResource extends AbstractCollectionSpaceResource { path.path("" + csid); Response response = Response.created(path.build()).build(); return response; + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in createRelation", e); @@ -124,6 +129,10 @@ public class NewRelationResource extends AbstractCollectionSpaceResource { DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).get(ctx, csid, handler); result = (MultipartOutput) ctx.getOutput(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("getRelation", dnfe); @@ -259,6 +268,10 @@ public class NewRelationResource extends AbstractCollectionSpaceResource { DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).update(ctx, csid, handler); result = (MultipartOutput) ctx.getOutput(); + } 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 updateRelation", dnfe); @@ -292,6 +305,10 @@ public class NewRelationResource extends AbstractCollectionSpaceResource { ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName()); getRepositoryClient(ctx).delete(ctx, csid); return Response.status(HttpResponseCodes.SC_OK).build(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("caught exception in deleteRelation", dnfe); @@ -332,6 +349,10 @@ public class NewRelationResource extends AbstractCollectionSpaceResource { propsFromPath.put(IRelationsManager.OBJECT, objectCsid); getRepositoryClient(ctx).getAll(ctx, handler); relationList = (RelationsCommonList) handler.getCommonPartList(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Get relations failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in getRelationList", e); diff --git a/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/VocabularyResource.java b/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/VocabularyResource.java index f627bb892..359580097 100644 --- a/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/VocabularyResource.java +++ b/services/vocabulary/service/src/main/java/org/collectionspace/services/vocabulary/VocabularyResource.java @@ -47,6 +47,7 @@ import org.collectionspace.services.common.context.ServiceContext; import org.collectionspace.services.common.document.DocumentFilter; import org.collectionspace.services.common.document.DocumentHandler; import org.collectionspace.services.common.document.DocumentNotFoundException; +import org.collectionspace.services.common.security.UnauthorizedException; import org.collectionspace.services.vocabulary.nuxeo.VocabularyHandlerFactory; import org.collectionspace.services.vocabulary.nuxeo.VocabularyItemDocumentModelHandler; import org.collectionspace.services.vocabulary.nuxeo.VocabularyItemHandlerFactory; @@ -109,7 +110,7 @@ public class VocabularyResource extends AbstractCollectionSpaceResource { docHandler.setServiceContext(ctx); ((VocabularyItemDocumentModelHandler) docHandler).setInVocabulary(inVocabulary); if (ctx.getInput() != null) { - Object obj = ((MultipartServiceContext)ctx).getInputPart(ctx.getCommonPartLabel(getItemServiceName()), + Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(getItemServiceName()), VocabularyitemsCommon.class); if (obj != null) { docHandler.setCommonPart((VocabularyitemsCommon) obj); @@ -129,6 +130,10 @@ public class VocabularyResource extends AbstractCollectionSpaceResource { path.path("" + csid); Response response = Response.created(path.build()).build(); return response; + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in createVocabulary", e); @@ -159,6 +164,10 @@ public class VocabularyResource extends AbstractCollectionSpaceResource { DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).get(ctx, csid, handler); result = (MultipartOutput) ctx.getOutput(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("getVocabulary", dnfe); @@ -192,15 +201,19 @@ public class VocabularyResource extends AbstractCollectionSpaceResource { ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName()); MultivaluedMap queryParams = ui.getQueryParameters(); DocumentHandler handler = createDocumentHandler(ctx); - DocumentFilter myFilter = - DocumentFilter.CreatePaginatedDocumentFilter(queryParams); - String nameQ = queryParams.getFirst("refName"); - if(nameQ!= null) { - myFilter.setWhereClause("vocabularies_common:refName='"+nameQ+"'"); - } + DocumentFilter myFilter = + DocumentFilter.CreatePaginatedDocumentFilter(queryParams); + String nameQ = queryParams.getFirst("refName"); + if (nameQ != null) { + myFilter.setWhereClause("vocabularies_common:refName='" + nameQ + "'"); + } handler.setDocumentFilter(myFilter); getRepositoryClient(ctx).getFiltered(ctx, handler); vocabularyObjectList = (VocabulariesCommonList) handler.getCommonPartList(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in getVocabularyList", e); @@ -233,6 +246,10 @@ public class VocabularyResource extends AbstractCollectionSpaceResource { DocumentHandler handler = createDocumentHandler(ctx); getRepositoryClient(ctx).update(ctx, csid, handler); result = (MultipartOutput) ctx.getOutput(); + } 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 updateVocabulary", dnfe); @@ -264,9 +281,13 @@ public class VocabularyResource extends AbstractCollectionSpaceResource { throw new WebApplicationException(response); } try { -ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName()); + ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName()); getRepositoryClient(ctx).delete(ctx, csid); return Response.status(HttpResponseCodes.SC_OK).build(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("caught exception in deleteVocabulary", dnfe); @@ -297,6 +318,10 @@ ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(n path.path(parentcsid + "/items/" + itemcsid); Response response = Response.created(path.build()).build(); return response; + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in createVocabularyItem", e); @@ -336,7 +361,11 @@ ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(n DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid); getRepositoryClient(ctx).get(ctx, itemcsid, handler); // TODO should we assert that the item is in the passed vocab? - result = (MultipartOutput)ctx.getOutput(); + result = (MultipartOutput) ctx.getOutput(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Get failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("getVocabularyItem", dnfe); @@ -378,6 +407,10 @@ ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(n handler.setDocumentFilter(myFilter); getRepositoryClient(ctx).getFiltered(ctx, handler); vocabularyItemObjectList = (VocabularyitemsCommonList) handler.getCommonPartList(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Index failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (Exception e) { if (logger.isDebugEnabled()) { logger.debug("Caught exception in getVocabularyItemList", e); @@ -418,7 +451,11 @@ ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(n ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(theUpdate, getItemServiceName()); DocumentHandler handler = createItemDocumentHandler(ctx, parentcsid); getRepositoryClient(ctx).update(ctx, itemcsid, handler); - result = (MultipartOutput)ctx.getOutput(); + result = (MultipartOutput) ctx.getOutput(); + } 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 updateVocabularyItem", dnfe); @@ -462,6 +499,10 @@ ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(n ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getItemServiceName()); getRepositoryClient(ctx).delete(ctx, itemcsid); return Response.status(HttpResponseCodes.SC_OK).build(); + } catch (UnauthorizedException ue) { + Response response = Response.status( + Response.Status.UNAUTHORIZED).entity("Delete failed reason " + ue.getErrorReason()).type("text/plain").build(); + throw new WebApplicationException(response); } catch (DocumentNotFoundException dnfe) { if (logger.isDebugEnabled()) { logger.debug("caught exception in deleteVocabulary", dnfe); -- 2.47.3