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
<enabled>false</enabled>\r
</snapshots>\r
</repository>\r
+ <!-- some security binaries available under .com only perhaps due to licensing issues -->\r
+ <repository>\r
+ <id>jboss</id>\r
+ <url>http://repository.jboss.com/maven2</url>\r
+ <snapshots>\r
+ <enabled>false</enabled>\r
+ </snapshots>\r
+ </repository>\r
<repository>\r
<id>mojo</id>\r
<name>mojo repo</name>\r
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;
return serviceName;
}
- private <T> ServiceContext createServiceContext(T obj) {
+ private <T> ServiceContext createServiceContext(T obj) throws Exception {
ServiceContext ctx = new RemoteServiceContextImpl<T, T>(getServiceName());
ctx.setInput(obj);
ctx.setDocumentType(AccountsCommon.class.getPackage().getName()); //persistence unit
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);
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);
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);
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);
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);
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;
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());
}
}
- 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));
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;
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);
}
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);
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);
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);
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);
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);
\r
<target name="create_db"\r
description="create tables(s), indices for authentication service">\r
- <ant antfile="service/build.xml" target="create_db" inheritAll="false"/>\r
+ <ant antfile="client/build.xml" target="create_db" inheritAll="false"/>\r
</target>\r
\r
<target name="deploy" depends="install"\r
description="deploy authentication service">\r
+ <ant antfile="client/build.xml" target="deploy" inheritAll="false"/>\r
<ant antfile="service/build.xml" target="deploy" inheritall="false"/>\r
</target>\r
\r
<target name="undeploy"\r
description="undeploy authentication service">\r
+ <ant antfile="client/build.xml" target="undeploy" inheritAll="false"/>\r
<ant antfile="service/build.xml" target="undeploy" inheritall="false"/>\r
</target>\r
\r
--- /dev/null
+\r
+<project name="authentication.client" default="package" basedir=".">\r
+ <description>\r
+ collectionspace authentication service\r
+ </description>\r
+ <!-- set global properties for this build -->\r
+ <property name="services.trunk" value="../../.."/>\r
+ <property file="${services.trunk}/build.properties" />\r
+ <property name="mvn.opts" value="" />\r
+ <property name="src" location="src"/>\r
+\r
+ <condition property="osfamily-unix">\r
+ <os family="unix" />\r
+ </condition>\r
+ <condition property="osfamily-windows">\r
+ <os family="windows" />\r
+ </condition>\r
+\r
+ <target name="init">\r
+ <!-- Create the time stamp -->\r
+ <tstamp/>\r
+ </target>\r
+\r
+\r
+ <target name="package" depends="package-unix,package-windows"\r
+ description="Package CollectionSpace Services" />\r
+ <target name="package-unix" if="osfamily-unix">\r
+ <exec executable="mvn" failonerror="true">\r
+ <arg value="package" />\r
+ <arg value="-Dmaven.test.skip=true" />\r
+ <arg value="-f" />\r
+ <arg value="${basedir}/pom.xml" />\r
+ <arg value="-N" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+ <target name="package-windows" if="osfamily-windows">\r
+ <exec executable="cmd" failonerror="true">\r
+ <arg value="/c" />\r
+ <arg value="mvn.bat" />\r
+ <arg value="package" />\r
+ <arg value="-Dmaven.test.skip=true" />\r
+ <arg value="-f" />\r
+ <arg value="${basedir}/pom.xml" />\r
+ <arg value="-N" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+\r
+ <target name="install" depends="package,install-unix,install-windows"\r
+ description="Install" />\r
+ <target name="install-unix" if="osfamily-unix">\r
+ <exec executable="mvn" failonerror="true">\r
+ <arg value="install" />\r
+ <arg value="-Dmaven.test.skip=true" />\r
+ <arg value="-f" />\r
+ <arg value="${basedir}/pom.xml" />\r
+ <arg value="-N" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+ <target name="install-windows" if="osfamily-windows">\r
+ <exec executable="cmd" failonerror="true">\r
+ <arg value="/c" />\r
+ <arg value="mvn.bat" />\r
+ <arg value="install" />\r
+ <arg value="-Dmaven.test.skip=true" />\r
+ <arg value="-f" />\r
+ <arg value="${basedir}/pom.xml" />\r
+ <arg value="-N" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+ \r
+ <target name="clean" depends="clean-unix,clean-windows"\r
+ description="Delete target directories" >\r
+ <delete dir="${build}"/>\r
+ </target>\r
+ <target name="clean-unix" if="osfamily-unix">\r
+ <exec executable="mvn" failonerror="true">\r
+ <arg value="clean" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+ <target name="clean-windows" if="osfamily-windows">\r
+ <exec executable="cmd" failonerror="true">\r
+ <arg value="/c" />\r
+ <arg value="mvn.bat" />\r
+ <arg value="clean" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+\r
+ <target name="test" depends="test-unix,test-windows" description="Run tests" />\r
+ <target name="test-unix" if="osfamily-unix">\r
+ <exec executable="mvn" failonerror="true">\r
+ <arg value="test" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+ <target name="test-windows" if="osfamily-windows">\r
+ <exec executable="cmd" failonerror="true">\r
+ <arg value="/c" />\r
+ <arg value="mvn.bat" />\r
+ <arg value="test" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+\r
+ <target name="gen_ddl" depends="gen_ddl-unix,gen_ddl-windows"\r
+ description="geneate ddl" />\r
+ <target name="gen_ddl-unix" if="osfamily-unix">\r
+ <exec executable="mvn" failonerror="true">\r
+ <arg value="-Pddl" />\r
+ <arg value="process-test-resources" />\r
+ <arg value="-f" />\r
+ <arg value="${basedir}/pom.xml" />\r
+ <arg value="-N" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+ <target name="gen_ddl-windows" if="osfamily-windows">\r
+ <exec executable="cmd" failonerror="true">\r
+ <arg value="/c" />\r
+ <arg value="mvn.bat" />\r
+ <arg value="-Pddl" />\r
+ <arg value="process-test-resources" />\r
+ <arg value="-f" />\r
+ <arg value="${basedir}/pom.xml" />\r
+ <arg value="-N" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+\r
+ <target name="create_db"\r
+ description="create tables(s), indices for authentication service">\r
+ <sql driver="com.mysql.jdbc.Driver"\r
+ url="jdbc:mysql://${db.host}:${db.port}/cspace"\r
+ userid="${db.user}"\r
+ password="${db.user.password}"\r
+ src="${db.script.dir}/authentication.sql"\r
+ >\r
+ <classpath>\r
+ <pathelement path="${db.driver.jar}"/>\r
+ </classpath>\r
+ </sql>\r
+ <sql driver="com.mysql.jdbc.Driver"\r
+ url="jdbc:mysql://${db.host}:${db.port}/cspace"\r
+ userid="${db.user}"\r
+ password="${db.user.password}"\r
+ src="${db.script.dir}/test_authn.sql"\r
+ >\r
+ <classpath>\r
+ <pathelement path="${db.driver.jar}"/>\r
+ </classpath>\r
+ </sql>\r
+ </target>\r
+ \r
+ <target name="deploy" depends="install"\r
+ description="deploy authentication service in ${jboss.server.cspace}">\r
+ <copy todir="${jboss.server.cspace}/cspace/services">\r
+ <fileset dir="${src}/main/resources/"/>\r
+ </copy>\r
+ </target>\r
+\r
+ <target name="undeploy"\r
+ description="undeploy authentication service from ${jboss.server.cspace}">\r
+ </target>\r
+\r
+ <target name="dist"\r
+ description="generate distribution for authentication service" depends="package">\r
+ <!-- copy db scripts, etc. -->\r
+ <copy todir="${services.trunk}/${dist.server.cspace}/cspace/services">\r
+ <fileset dir="${src}/main/resources/"/>\r
+ </copy>\r
+ </target>\r
+\r
+</project>\r
<artifactId>org.collectionspace.services.authentication.client</artifactId>\r
<version>1.0</version>\r
<name>services.authentication.client</name>\r
- \r
+ <properties>\r
+ <sql.file>authentication.sql</sql.file>\r
+ <sql.dir>${basedir}/src/main/resources/db/mysql</sql.dir>\r
+ </properties>\r
<dependencies>\r
<!-- keep slf4j dependencies on the top -->\r
<dependency>\r
<artifactId>slf4j-log4j12</artifactId>\r
<scope>test</scope>\r
</dependency>\r
+ <dependency>\r
+ <groupId>org.collectionspace.services</groupId>\r
+ <artifactId>org.collectionspace.services.authentication.jaxb</artifactId>\r
+ <version>1.0</version>\r
+ </dependency>\r
<dependency>\r
<groupId>org.collectionspace.services</groupId>\r
<artifactId>org.collectionspace.services.client</artifactId>\r
<artifactId>commons-httpclient</artifactId>\r
<version>3.1</version>\r
</dependency>\r
+ <dependency>\r
+ <groupId>mysql</groupId>\r
+ <artifactId>mysql-connector-java</artifactId>\r
+ </dependency>\r
</dependencies>\r
\r
<build>\r
</plugin>\r
</plugins>\r
</build>\r
+ <profiles>\r
+ <profile>\r
+ <!-- use profile as this task is not needed for every build and test -->\r
+ <id>ddl</id>\r
+ <build>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.codehaus.mojo</groupId>\r
+ <artifactId>hibernate3-maven-plugin</artifactId>\r
+ <version>2.2</version>\r
+ <executions>\r
+ <execution>\r
+ <phase>process-test-resources</phase>\r
+ <goals>\r
+ <goal>hbm2ddl</goal>\r
+ </goals>\r
+ </execution>\r
+ </executions>\r
+ <configuration>\r
+ <components>\r
+ <component>\r
+ <name>hbm2ddl</name>\r
+ </component>\r
+ </components>\r
+ <componentProperties>\r
+ <outputfilename>${sql.file}</outputfilename>\r
+ <implementation>jpaconfiguration</implementation>\r
+ <drop>true</drop>\r
+ <create>true</create>\r
+ <export>true</export>\r
+ <jdk5>true</jdk5>\r
+ <ejb3>false</ejb3>\r
+ <persistenceunit>org.collectionspace.services.authentication</persistenceunit>\r
+ </componentProperties>\r
+ </configuration>\r
+ <dependencies>\r
+ <dependency>\r
+ <groupId>mysql</groupId>\r
+ <artifactId>mysql-connector-java</artifactId>\r
+ <version>5.0.5</version>\r
+ </dependency>\r
+ </dependencies>\r
+ </plugin>\r
+ <plugin>\r
+ <artifactId>maven-antrun-plugin</artifactId>\r
+ <executions>\r
+ <execution>\r
+ <phase>process-test-resources</phase>\r
+ <configuration>\r
+ <tasks>\r
+ <copy file="${basedir}/target/hibernate3/sql/${sql.file}" tofile="${sql.dir}/${sql.file}"/>\r
+ </tasks>\r
+ </configuration>\r
+ <goals>\r
+ <goal>run</goal>\r
+ </goals>\r
+ </execution>\r
+ </executions>\r
+ </plugin>\r
+\r
+ </plugins>\r
+ </build>\r
+ </profile>\r
+ </profiles>\r
</project>\r
\r
--- /dev/null
+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));
--- /dev/null
+--\r
+-- Copyright 2009 University of California at Berkeley\r
+-- Licensed under the Educational Community License (ECL), Version 2.0.\r
+-- You may not use this file except in compliance with this License.\r
+--\r
+use cspace;\r
+\r
+INSERT INTO `users` (`username`,`passwd`, `tenantid`) VALUES ('test','n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=', '1');\r
+\r
+insert into roles (rolename, rolegroup, `tenantid`) values ('collections_manager', 'collections', '1');\r
+insert into roles (rolename, rolegroup, `tenantid`) values ('collections_registrar', 'collections', '1');\r
+\r
+insert into users_roles(username, rolename, `tenantid`) values ('test', 'collections_manager', '1');\r
+insert into users_roles(username, rolename, `tenantid`) values('admin', 'collections_registrar', '1');
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<persistence version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
+http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <persistence-unit name="org.collectionspace.services.authentication">
+ <class>org.collectionspace.services.authentication.User</class>
+ <class>org.collectionspace.services.authentication.Role</class>
+ <class>org.collectionspace.services.authentication.UserRole</class>
+ <properties>
+ <property name="hibernate.ejb.cfgfile" value="hibernate.cfg.xml"/>
+
+ <!--property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
+ <property name="hibernate.max_fetch_depth" value="3"/>
+ <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
+ <property name="hibernate.connection.username" value="test"/>
+ <property name="hibernate.connection.password" value="test"/>
+ <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/cspace"/-->
+ </properties>
+ </persistence-unit>
+</persistence>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Document : hibernate.cfg.xml.xml
+ Created on :
+ Author :
+ Description:
+ Hibernate configuration file for testing and tools
+-->
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+<hibernate-configuration>
+ <session-factory>
+ <property name="connection.url">jdbc:mysql://localhost:3306/cspace</property>
+ <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
+ <property name="connection.username">test</property>
+ <property name="connection.password">test</property>
+ <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
+ <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
+ <property name="current_session_context_class">thread</property>
+ <property name="hibernate.show_sql">true</property>
+ </session-factory>
+</hibernate-configuration>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
+ <!-- tenant id is not needed from service consumer, it will be ignored if provided -->
+ <!-- tenant id is for internal use for CollectionSpace -->
+ <!-- it is assumed that account creation is performed under valid -->
+ <!-- tenant context. tenant id is never returned in response -->
+ <xs:element name="tenantid" type="xs:string" minOccurs="0" maxOccurs="1">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="tenantid" nullable="false"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
<xs:element name="username" type="xs:string" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:appinfo>
<hj:id>
- <orm:column name="username" length="512" nullable="false"/>
+ <orm:column name="username" nullable="false"/>
</hj:id>
</xs:appinfo>
</xs:annotation>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
+ <!-- tenant id is not needed from service consumer, it will be ignored if provided -->
+ <!-- tenant id is for internal use for CollectionSpace -->
+ <!-- it is assumed that account creation is performed under valid -->
+ <!-- tenant context. tenant id is never returned in response -->
+ <xs:element name="tenantid" type="xs:string" minOccurs="0" maxOccurs="1">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="tenantid" nullable="false"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
<xs:element name="rolename" type="xs:string" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:appinfo>
<hj:id>
- <orm:column name="rolename" length="128" nullable="false"/>
+ <orm:column name="rolename" nullable="false"/>
</hj:id>
</xs:appinfo>
</xs:annotation>
<xs:annotation>
<xs:appinfo>
<hj:basic>
- <orm:column name="rolegroup" length="128" nullable="false"/>
+ <orm:column name="rolegroup" nullable="false"/>
</hj:basic>
</xs:appinfo>
</xs:annotation>
</xs:appinfo>
</xs:annotation>
<xs:sequence>
+ <!-- tenant id is not needed from service consumer, it will be ignored if provided -->
+ <!-- tenant id is for internal use for CollectionSpace -->
+ <!-- it is assumed that account creation is performed under valid -->
+ <!-- tenant context. tenant id is never returned in response -->
+ <xs:element name="tenantid" type="xs:string" minOccurs="0" maxOccurs="1">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="tenantid" nullable="false"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
<xs:element name="username" type="xs:string" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:appinfo>
<hj:basic>
- <orm:column name="username" length="128" nullable="false"/>
+ <orm:column name="username" nullable="false"/>
</hj:basic>
</xs:appinfo>
</xs:annotation>
<xs:annotation>
<xs:appinfo>
<hj:basic>
- <orm:column name="rolename" length="128" nullable="false"/>
+ <orm:column name="rolename" nullable="false"/>
</hj:basic>
</xs:appinfo>
</xs:annotation>
</exec>\r
</target>\r
\r
- <target name="create_db"\r
- description="create tables(s), indices for authentication service">\r
- <sql driver="com.mysql.jdbc.Driver"\r
- url="jdbc:mysql://${db.host}:${db.port}/cspace"\r
- userid="${db.user}"\r
- password="${db.user.password}"\r
- src="${db.script.dir}/authentication.sql"\r
- >\r
- <classpath>\r
- <pathelement path="${db.driver.jar}"/>\r
- </classpath>\r
- </sql>\r
- <sql driver="com.mysql.jdbc.Driver"\r
- url="jdbc:mysql://${db.host}:${db.port}/cspace"\r
- userid="${db.user}"\r
- password="${db.user.password}"\r
- src="${db.script.dir}/test_authn.sql"\r
- >\r
- <classpath>\r
- <pathelement path="${db.driver.jar}"/>\r
- </classpath>\r
- </sql>\r
- </target>\r
<target name="deploy" depends="install"\r
description="deploy authentication service in ${jboss.server.cspace}">\r
<copy file="${basedir}/target/${authentication.jar}" todir="${jboss.server.cspace}/lib"/>\r
<scope>test</scope>
</dependency>
+
+
<!-- javax -->
<dependency>
<groupId>javax.security</groupId>
<version>1.0.01</version>
<scope>provided</scope>
</dependency>
+
+ <!-- jboss -->
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging-log4j</artifactId>
+ <version>2.1.0.GA</version>
+ </dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jbosssx</artifactId>
import java.sql.SQLException;\r
\r
import java.util.HashMap;\r
+import java.util.Map;\r
import javax.naming.InitialContext;\r
import javax.naming.NamingException;\r
+import javax.security.auth.Subject;\r
+import javax.security.auth.callback.CallbackHandler;\r
import javax.security.auth.login.FailedLoginException;\r
import javax.security.auth.login.LoginException;\r
import javax.sql.DataSource;\r
import org.jboss.security.SimpleGroup;\r
import org.jboss.security.SimplePrincipal;\r
import org.jboss.security.auth.spi.DatabaseServerLoginModule;\r
-//import org.slf4j.Logger;\r
-//import org.slf4j.LoggerFactory;\r
\r
+/**\r
+ * CollectionSpace default identity provider supporting multi-tenancy\r
+ * @author\r
+ */\r
public class CSpaceDBLoginModule extends DatabaseServerLoginModule {\r
\r
+ protected String tenantQuery = "select tenantid from users where username=?";\r
//disabled due to classloading problem\r
// private Logger logger = LoggerFactory.getLogger(CSpaceDBLoginModule.class);\r
- private boolean log = true; //logger.isDebugEnabled();\r
-\r
- private void log(String str) {\r
- System.out.println(str);\r
- }\r
+ private String tenantId;\r
\r
protected String getUsersPassword() throws LoginException {\r
\r
Connection conn = null;\r
PreparedStatement ps = null;\r
ResultSet rs = null;\r
- InitialContext ctx = null;\r
try {\r
-\r
- ctx = new InitialContext();\r
- DataSource ds = (DataSource) ctx.lookup(dsJndiName);\r
- if (ds == null) {\r
- throw new IllegalArgumentException("datasource not found: " + dsJndiName);\r
- }\r
- conn = ds.getConnection();\r
+ conn = getConnection();\r
// Get the password\r
- if (log) {\r
- log("Executing query: " + principalsQuery + ", with username: " + username);\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("Executing query: " + principalsQuery + ", with username: " + username);\r
}\r
ps = conn.prepareStatement(principalsQuery);\r
ps.setString(1, username);\r
rs = ps.executeQuery();\r
if (rs.next() == false) {\r
- if (log) {\r
- log("Query returned no matches from db");\r
+ if (log.isDebugEnabled()) {\r
+ log.debug(principalsQuery + " returned no matches from db");\r
}\r
throw new FailedLoginException("No matching username found");\r
}\r
\r
password = rs.getString(1);\r
password = convertRawPassword(password);\r
- if (log) {\r
- log("Obtained user password");\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("Obtained user password");\r
}\r
- } catch (NamingException ex) {\r
- LoginException le = new LoginException("Error looking up DataSource from: " + dsJndiName);\r
- le.initCause(ex);\r
- throw le;\r
+ tenantId = rs.getString(2);\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("Obtained tenantId");\r
+ }\r
+ CSpacePrincipal principal = (CSpacePrincipal)getIdentity();\r
+ principal.setTenantId(tenantId);\r
} catch (SQLException ex) {\r
LoginException le = new LoginException("Query failed");\r
le.initCause(ex);\r
} catch (SQLException ex) {\r
}\r
}\r
- if (ctx != null) {\r
- try {\r
- ctx.close();\r
- } catch (Exception e) {\r
- }\r
- }\r
}\r
return password;\r
}\r
*/\r
protected Group[] getRoleSets() throws LoginException {\r
String username = getUsername();\r
- if (log) {\r
- log("getRoleSets using rolesQuery: " + rolesQuery + ", username: " + username);\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("getRoleSets using rolesQuery: " + rolesQuery + ", username: " + username);\r
}\r
\r
Connection conn = null;\r
ResultSet rs = null;\r
\r
try {\r
- InitialContext ctx = new InitialContext();\r
- DataSource ds = (DataSource) ctx.lookup(dsJndiName);\r
- conn = ds.getConnection();\r
+ conn = getConnection();\r
// Get the user role names\r
- if (log) {\r
- log("Executing query: " + rolesQuery + ", with username: " + username);\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("Executing query: " + rolesQuery + ", with username: " + username);\r
}\r
\r
ps = conn.prepareStatement(rolesQuery);\r
try {\r
ps.setString(1, username);\r
+ ps.setString(2, tenantId);\r
} catch (ArrayIndexOutOfBoundsException ignore) {\r
// The query may not have any parameters so just try it\r
}\r
rs = ps.executeQuery();\r
if (rs.next() == false) {\r
- if (log) {\r
- log("No roles found");\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("No roles found");\r
}\r
// if(aslm.getUnauthenticatedIdentity() == null){\r
// throw new FailedLoginException("No matching username found in Roles");\r
try {\r
// Principal p = aslm.createIdentity(name);\r
Principal p = createIdentity(name);\r
- if (log) {\r
- log("Assign user to role " + name);\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("Assign user to role " + name);\r
}\r
\r
group.addMember(p);\r
} catch (Exception e) {\r
- log("Failed to create principal: " + name + " " + e.toString());\r
+ log.error("Failed to create principal: " + name + " " + e.toString());\r
}\r
\r
} while (rs.next());\r
- } catch (NamingException ex) {\r
- LoginException le = new LoginException("Error looking up DataSource from: " + dsJndiName);\r
- le.initCause(ex);\r
- throw le;\r
} catch (SQLException ex) {\r
LoginException le = new LoginException("Query failed");\r
le.initCause(ex);\r
return roleSets;\r
}\r
\r
- /** Utility method to create a Principal for the given username. This\r
- * creates an instance of the principalClassName type if this option was\r
- * specified using the class constructor matching: ctor(String). If\r
- * principalClassName was not specified, a SimplePrincipal is created.\r
- *\r
- * @param username the name of the principal\r
- * @return the principal instance\r
- * @throws java.lang.Exception thrown if the custom principal type cannot be created.\r
- */\r
- protected Principal createIdentity(String username)\r
- throws Exception {\r
- Principal p = null;\r
- if (principalClassName == null) {\r
- p = new SimplePrincipal(username);\r
- } else {\r
- ClassLoader loader = Thread.currentThread().getContextClassLoader();\r
- Class clazz = loader.loadClass(principalClassName);\r
- Class[] ctorSig = {String.class};\r
- Constructor ctor = clazz.getConstructor(ctorSig);\r
- Object[] ctorArgs = {username};\r
- p = (Principal) ctor.newInstance(ctorArgs);\r
+\r
+ private Connection getConnection() throws LoginException, SQLException {\r
+ InitialContext ctx = null;\r
+ Connection conn = null;\r
+ try {\r
+ ctx = new InitialContext();\r
+ DataSource ds = (DataSource) ctx.lookup(dsJndiName);\r
+ if (ds == null) {\r
+ throw new IllegalArgumentException("datasource not found: " + dsJndiName);\r
+ }\r
+ conn = ds.getConnection();\r
+ return conn;\r
+ } catch (NamingException ex) {\r
+ LoginException le = new LoginException("Error looking up DataSource from: " + dsJndiName);\r
+ le.initCause(ex);\r
+ throw le;\r
+ } finally {\r
+ if (ctx != null) {\r
+ try {\r
+ ctx.close();\r
+ } catch (Exception e) {\r
+ }\r
+ }\r
}\r
\r
- return p;\r
}\r
}\r
--- /dev/null
+/**
+ * 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;
+ }
+}
copy before the "other" application-policy
-->
- <application-policy name="cspace">
- <authentication>
- <login-module code="org.collectionspace.authentication.CSpaceDBLoginModule"
+<application-policy name="cspace">
+ <authentication>
+ <login-module code="org.collectionspace.authentication.CSpaceDBLoginModule"
flag="required">
- <module-option name="dsJndiName">CspaceDS</module-option>
- <module-option name="hashAlgorithm">SHA-256</module-option>
- <module-option name="ignorePasswordCase">false</module-option>
- <module-option name="principalsQuery">
- select passwd from users where username=?
- </module-option>
- <module-option name="rolesQuery">
- select rolename, 'Roles' from users_roles where username=?
- </module-option>
- </login-module>
- </authentication>
- </application-policy>
+ <module-option name="dsJndiName">CspaceDS</module-option>
+ <module-option name="hashAlgorithm">SHA-256</module-option>
+ <module-option name="ignorePasswordCase">false</module-option>
+ <module-option name = "principalClass">org.collectionspace.authentication.CSpacePrincipal</module-option>
+ <module-option name="principalsQuery">
+ select passwd, tenantid from users where username=?
+ </module-option>
+ <module-option name="rolesQuery">
+ select rolename, 'Roles' from users_roles where username=? and tenantid=?
+ </module-option>
+ </login-module>
+ </authentication>
+</application-policy>
+++ /dev/null
---\r
--- Copyright 2009 University of California at Berkeley\r
--- Licensed under the Educational Community License (ECL), Version 2.0.\r
--- You may not use this file except in compliance with this License.\r
---\r
-use cspace;\r
-\r
-DROP TABLE IF EXISTS users;\r
-CREATE TABLE users(username VARCHAR(512) PRIMARY KEY, passwd VARCHAR(128) NOT NULL );\r
-CREATE INDEX username_users on users(username);\r
-\r
-DROP TABLE IF EXISTS roles;\r
-CREATE TABLE roles(rolename VARCHAR(128) PRIMARY KEY, rolegroup VARCHAR(128));\r
-CREATE INDEX rolename_roles on roles(rolename);\r
-\r
-DROP TABLE IF EXISTS users_roles;\r
-CREATE TABLE users_roles(username VARCHAR(512) NOT NULL, rolename VARCHAR(128) NOT NULL);\r
-CREATE INDEX username_users_roles on users_roles(username);
\ No newline at end of file
+++ /dev/null
---\r
--- Copyright 2009 University of California at Berkeley\r
--- Licensed under the Educational Community License (ECL), Version 2.0.\r
--- You may not use this file except in compliance with this License.\r
---\r
-use cspace;\r
-\r
-INSERT INTO `users` (`username`,`passwd`) VALUES ('test','n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=');\r
-\r
-insert into roles (rolename, rolegroup) values ('collections_manager', 'collections');\r
-insert into roles (rolename, rolegroup) values ('collections_registrar', 'collections');\r
-\r
-insert into users_roles(username, rolename) values ('test', 'collections_manager');\r
-insert into users_roles(username, rolename) values('admin', 'collections_registrar');
\ No newline at end of file
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;
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);
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);
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);
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);
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);
<version>1.0.01</version>\r
<scope>provided</scope>\r
</dependency>\r
-\r
+ <dependency>\r
+ <groupId>javax.security</groupId>\r
+ <artifactId>jacc</artifactId>\r
+ <version>1.0</version>\r
+ <scope>provided</scope>\r
+ </dependency>\r
<!--\r
<dependency>\r
<groupId>dom4j</groupId>\r
--- /dev/null
+/**
+ * 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.services.common;
+
+/**
+ * ServiceException is a base exception for any exception thrown by the service layer
+ * The error code is the code that is sent to the service consumer with relevant
+ * error reason. Note that detail message could be server side service-centric message.
+ * This message should not be sent to the service consumer who does not need to know
+ * about the internals of the service. The service consumer should see error code
+ * and error reason only. CollectionSpace service documentation should be checked
+ * to get help on troubleshooting the error.
+ * @author
+ */
+public class ServiceException extends Exception {
+
+ private int errorCode;
+ private String errorReason;
+
+ /**
+ * Creates a new instance of <code>ServiceException</code> without detail message, error code
+ * or error reason.
+ */
+ public ServiceException() {
+ }
+
+ /**
+ * Constructs an instance of <code>ServiceException</code> with the specified detail message
+ * without error code or error reason.
+ * @param msg the detail message.
+ */
+ public ServiceException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Constructs an instance of <code>ServiceException</code> with the specified error code.
+ * @param errorCode error code
+ */
+ public ServiceException(int errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * Constructs an instance of <code>ServiceException</code> with the specified error code and error reason.
+ * @param errorCode error code
+ * @param errorReason reason for error
+ */
+ public ServiceException(int errorCode, String errorReason) {
+ this.errorCode = errorCode;
+ this.errorReason = errorReason;
+ }
+
+ /**
+ * Constructs a new an instance of <code>ServiceException</code> with the specified detail message and
+ * cause. <p>Note that the detail message associated with
+ * <code>cause</code> is <i>not</i> automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param msg the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ */
+ public ServiceException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+
+ /**
+ * Constructs a new an instance of <code>ServiceException</code> with the specified cause and a detail
+ * message of <tt>(cause==null ? null : cause.toString())</tt> (which
+ * typically contains the class and detail message of <tt>cause</tt>).
+ * This constructor is useful for exceptions that are little more than
+ * wrappers for other throwables (for example, {@link
+ * java.security.PrivilegedActionException}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ */
+ public ServiceException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * @return the errorCode
+ */
+ public int getErrorCode() {
+ return errorCode;
+ }
+
+ /**
+ * @param errorCode the errorCode to set
+ */
+ public void setErrorCode(int errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ /**
+ * @return the errorReason
+ */
+ public String getErrorReason() {
+ return errorReason;
+ }
+
+ /**
+ * @param errorReason the ErrorReason to set
+ */
+ public void setErrorReason(String errorReason) {
+ this.errorReason = errorReason;
+ }
+}
*/
package org.collectionspace.services.common.context;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Principal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.security.jacc.PolicyContext;
+import javax.security.jacc.PolicyContextException;
+
import org.collectionspace.services.common.ClientType;
import org.collectionspace.services.common.ServiceMain;
import org.collectionspace.services.common.config.TenantBindingConfigReader;
+import org.collectionspace.services.common.security.UnauthorizedException;
import org.collectionspace.services.common.service.ObjectPartType;
import org.collectionspace.services.common.service.ServiceBindingType;
import org.collectionspace.services.common.service.ServiceObjectType;
private TenantBindingType tenantBinding;
private String overrideDocumentType = null;
- public AbstractServiceContext(String serviceName) {
+ public AbstractServiceContext(String serviceName) throws UnauthorizedException {
TenantBindingConfigReader tReader =
ServiceMain.getInstance().getTenantBindingConfigReader();
- //TODO: get tenant binding from security context (Subject.g
- String tenantId = "1"; //hardcoded for movingimages.us
+ //TODO: get tenant binding from security context
+ String tenantId = retrieveTenantId();
+ if (tenantId == null) {
+ //for testing purposes
+ tenantId = "1"; //hardcoded for movingimages.us
+ }
tenantBinding = tReader.getTenantBinding(tenantId);
if (tenantBinding == null) {
String msg = "No tenant binding found while processing request for " +
public void setProperty(String name, Object o) {
properties.put(name, o);
}
+ private static final String SUBJECT_CONTEXT_KEY = "javax.security.auth.Subject.container";
+
+ private String retrieveTenantId() throws UnauthorizedException {
+
+ String tenantId = null;
+ Set<Principal> principals = null;
+ try {
+ Subject caller = (Subject) PolicyContext.getContext(SUBJECT_CONTEXT_KEY);
+ if(caller == null) {
+ //logger.warn("security not enabled...");
+ return tenantId;
+ }
+ principals = caller.getPrincipals(Principal.class);
+ } catch (PolicyContextException pce) {
+ String msg = "Could not retrieve principal information";
+ logger.error(msg, pce);
+ throw new UnauthorizedException(msg);
+ }
+ for (Principal p : principals) {
+ try {
+ Method m = p.getClass().getMethod("getTenantId");
+ Object r = m.invoke(p);
+ if (logger.isDebugEnabled()) {
+ logger.debug("retrieved tenantid=" + r +
+ " for principal=" + p.getName());
+ }
+ tenantId = (String) r;
+ break;
+ } catch (Exception e) {
+ //continue with next principal
+ }
+ }
+ if(tenantId == null) {
+ String msg = "Could not find tenant context";
+ logger.error(msg);
+ throw new UnauthorizedException(msg);
+ }
+ return tenantId;
+ }
@Override
public String toString() {
msg.append("tenant name=" + tenantBinding.getName() + " ");
msg.append(tenantBinding.getDisplayName() + " ");
msg.append("tenant repository domain=" + tenantBinding.getRepositoryDomain());
- for(Map.Entry<String, Object> entry : properties.entrySet()) {
+ for (Map.Entry<String, Object> entry : properties.entrySet()) {
msg.append("property name=" + entry.getKey() + " value=" + entry.getValue().toString());
}
msg.append("]");
import java.lang.reflect.Constructor;
import javax.ws.rs.core.MediaType;
import org.collectionspace.services.common.document.DocumentUtils;
+import org.collectionspace.services.common.security.UnauthorizedException;
import org.jboss.resteasy.plugins.providers.multipart.InputPart;
import org.jboss.resteasy.plugins.providers.multipart.MultipartInput;
import org.jboss.resteasy.plugins.providers.multipart.MultipartOutput;
import org.w3c.dom.Document;
/**
- * RemoteServiceContextImpl
+ * MultipartServiceContextImpl takes Multipart Input/Output
*
* $LastChangedRevision: $
* $LastChangedDate: $
final Logger logger = LoggerFactory.getLogger(MultipartServiceContextImpl.class);
- public MultipartServiceContextImpl(String serviceName) {
+ public MultipartServiceContextImpl(String serviceName) throws UnauthorizedException {
super(serviceName);
setOutput(new MultipartOutput());
}
package org.collectionspace.services.common.context;
import java.lang.reflect.Constructor;
+import org.collectionspace.services.common.security.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private IT input;
private OT output;
- public RemoteServiceContextImpl(String serviceName) {
+ public RemoteServiceContextImpl(String serviceName) throws UnauthorizedException {
super(serviceName);
}
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.collectionspace.services.common.document;
+import org.collectionspace.services.common.ServiceException;
+
/**
* BadRequestException
*
*/
-public class BadRequestException extends Exception {
+public class BadRequestException extends ServiceException {
+
+ final public static int HTTP_CODE = 400;
/**
* Creates a new instance of <code>BadRequestException</code> without detail message.
*/
public BadRequestException() {
+ super(HTTP_CODE);
}
-
/**
* Constructs an instance of <code>BadRequestException</code> with the specified detail message.
* @param msg the detail message.
*/
public BadRequestException(String msg) {
super(msg);
+ setErrorCode(HTTP_CODE);
}
-
/**
* Constructs a new exception with the specified detail message and
* cause. <p>Note that the detail message associated with
*/
public BadRequestException(String message, Throwable cause) {
super(message, cause);
+ setErrorCode(HTTP_CODE);
}
/**
*/
public BadRequestException(Throwable cause) {
super(cause);
+ setErrorCode(HTTP_CODE);
}
}
package org.collectionspace.services.common.document;
+import org.collectionspace.services.common.ServiceException;
+
/**
* DocumentException
* document handling exception
*/
-public class DocumentException extends Exception {
+public class DocumentException extends ServiceException {
- /**
- * collectionspace specific error code
- */
- private int errorCode;
/**
* Creates a new instance of <code>DocumentException</code> without detail message.
super(msg);
}
-
/**
- * DocumentException with application specific code and message
- * @param code
- * @param msg
+ * DocumentException with application specific code
+ * @param errorCode
*/
- public DocumentException(int code, String msg) {
- super(msg);
- this.errorCode = code;
+ public DocumentException(int errorCode) {
+ super(errorCode);
+ }
+ /**
+ * DocumentException with application specific code and reason
+ * @param errorCode
+ * @param errorReason
+ */
+ public DocumentException(int errorCode, String errorReason) {
+ super(errorCode, errorReason);
}
/**
* Constructs a new exception with the specified detail message and
super(cause);
}
-
- /**
- * @return the collectionspace errorCode
- */
- public int getErrorCode() {
- return errorCode;
- }
-
- /**
- * @param errorCode the errorCode to set
- */
- public void setErrorCode(int errorCode) {
- this.errorCode = errorCode;
- }
}
* https://source.collectionspace.org/collection-space/LICENSE.txt
*/
-
package org.collectionspace.services.common.document;
/**
*/
public class DocumentNotFoundException extends DocumentException {
+ final public static int HTTP_CODE = 404;
+
/**
* Creates a new instance of <code>DocumentNotFoundException</code> without detail message.
*/
public DocumentNotFoundException() {
+ setErrorCode(HTTP_CODE);
}
-
/**
* Constructs an instance of <code>DocumentNotFoundException</code> with the specified detail message.
* @param msg the detail message.
*/
public DocumentNotFoundException(String msg) {
super(msg);
+ setErrorCode(HTTP_CODE);
}
-
/**
* Constructs a new exception with the specified detail message and
* cause. <p>Note that the detail message associated with
*/
public DocumentNotFoundException(String message, Throwable cause) {
super(message, cause);
+ setErrorCode(HTTP_CODE);
}
/**
*/
public DocumentNotFoundException(Throwable cause) {
super(cause);
+ setErrorCode(HTTP_CODE);
}
}
--- /dev/null
+/**
+ * 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.services.common.security;
+
+import org.collectionspace.services.common.ServiceException;
+
+/**
+ * ServiceForbidenException is thrown when access to service is not allowed for
+ * one or more of the following reasons:
+ * - access not allowed
+ * - no application key found
+ * @author
+ */
+public class ServiceForbiddenException extends ServiceException {
+
+ final public static int HTTP_CODE = 401;
+
+ /**
+ * Creates a new instance of <code>UnauthorizedException</code> without detail message.
+ */
+ public ServiceForbiddenException() {
+ super(HTTP_CODE);
+ }
+
+ /**
+ * Constructs an instance of <code>UnauthorizedException</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public ServiceForbiddenException(String msg) {
+ super(msg);
+ setErrorCode(HTTP_CODE);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause. <p>Note that the detail message associated with
+ * <code>cause</code> is <i>not</i> automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public ServiceForbiddenException(String message, Throwable cause) {
+ super(message, cause);
+ setErrorCode(HTTP_CODE);
+ }
+
+ /**
+ * Constructs a new exception with the specified cause and a detail
+ * message of <tt>(cause==null ? null : cause.toString())</tt> (which
+ * typically contains the class and detail message of <tt>cause</tt>).
+ * This constructor is useful for exceptions that are little more than
+ * wrappers for other throwables (for example, {@link
+ * java.security.PrivilegedActionException}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public ServiceForbiddenException(Throwable cause) {
+ super(cause);
+ setErrorCode(HTTP_CODE);
+ }
+}
--- /dev/null
+/**
+ * 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.services.common.security;
+
+import org.collectionspace.services.common.ServiceException;
+
+/**
+ * ServiceForbidenException is thrown when access to service is not allowed for
+ * one or more of the following reasons:
+ * - tenant id not found
+ * @author
+ */
+public class UnauthorizedException extends ServiceException {
+
+ final public static int HTTP_CODE = 401;
+
+ /**
+ * Creates a new instance of <code>UnauthorizedException</code> without detail message.
+ */
+ public UnauthorizedException() {
+ super(HTTP_CODE);
+ }
+
+ /**
+ * Constructs an instance of <code>UnauthorizedException</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public UnauthorizedException(String msg) {
+ super(msg);
+ setErrorCode(HTTP_CODE);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message and
+ * cause. <p>Note that the detail message associated with
+ * <code>cause</code> is <i>not</i> automatically incorporated in
+ * this exception's detail message.
+ *
+ * @param message the detail message (which is saved for later retrieval
+ * by the {@link #getMessage()} method).
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public UnauthorizedException(String message, Throwable cause) {
+ super(message, cause);
+ setErrorCode(HTTP_CODE);
+ }
+
+ /**
+ * Constructs a new exception with the specified cause and a detail
+ * message of <tt>(cause==null ? null : cause.toString())</tt> (which
+ * typically contains the class and detail message of <tt>cause</tt>).
+ * This constructor is useful for exceptions that are little more than
+ * wrappers for other throwables (for example, {@link
+ * java.security.PrivilegedActionException}).
+ *
+ * @param cause the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public UnauthorizedException(Throwable cause) {
+ super(cause);
+ setErrorCode(HTTP_CODE);
+ }
+}
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;
ctx.getRepositoryClientType().toString());
docHandler.setServiceContext(ctx);
if (ctx.getInput() != null) {
- Object obj = ((MultipartServiceContext)ctx).getInputPart(ctx.getCommonPartLabel(), IntakesCommon.class);
+ Object obj = ((MultipartServiceContext) ctx).getInputPart(ctx.getCommonPartLabel(), IntakesCommon.class);
if (obj != null) {
docHandler.setCommonPart((IntakesCommon) obj);
}
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 createIntake", e);
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("getIntake", dnfe);
DocumentHandler handler = createDocumentHandler(ctx);
getRepositoryClient(ctx).getAll(ctx, handler);
intakeObjectList = (IntakesCommonList) 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 getIntakeList", e);
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 updateIntake", dnfe);
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 deleteIntake", dnfe);
<modules>
<!-- add modules below in the order based on dependencies -->
- <module>common</module>
<module>authentication</module>
+ <module>common</module>
<module>account</module>
<module>relation</module>
<!--module>query</module-->
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;
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);
}
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);
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);
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);
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);
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);
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;
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);
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);
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);
ServiceContext ctx = MultipartServiceContextFactory.get().createServiceContext(null, getServiceName());
MultivaluedMap<String, String> 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);
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);
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);
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);
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);
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);
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);
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);