]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
CSPACE-656 1-1 user-tenant association removed, added 1-many account-tenant association.
authorSanjay Dalal <sanjay.dalal@berkeley.edu>
Thu, 17 Dec 2009 02:07:37 +0000 (02:07 +0000)
committerSanjay Dalal <sanjay.dalal@berkeley.edu>
Thu, 17 Dec 2009 02:07:37 +0000 (02:07 +0000)
Default id provider is made less JBoss dependent. Tenant info is now put as group in security context with tenant as CSpaceTenant group-memeber
Common depends on authn service (for CSpaceTenant)
Account throws 400 if tenant and/or userid are missing. Provisioned test account with tenant association for testing purposes. Added account tests for the same.
Account client now packages all required classes. Used in authentication service tests.
Servicecontext now retrieves one or more tenants from security context before retrieving bindings. Still uses one tenant only (needs consumer to send tenant info if user is associated with n tenants. Client test now recognizes 401 for all service operations.

tests: service tests. account (new) tests. authn tests by enabling service side security

M    services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceDBLoginModule.java
A    services/authentication/service/src/main/java/org/collectionspace/authentication/DatabaseRealm.java
A    services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceTenant.java
M    services/authentication/service/src/main/resources/config/jboss-login-config.xml
M    services/authentication/service/pom.xml
M    services/authentication/jaxb/src/main/resources/authentication_identity_provider.xsd
M    services/authentication/jaxb/pom.xml
M    services/authentication/client/src/test/java/org/collectionspace/services/authentication/client/AuthenticationServiceTest.java
M    services/authentication/client/src/main/resources/db/mysql/test_authn.sql
M    services/authentication/client/src/main/resources/db/mysql/authentication.sql
M    services/authentication/client/pom.xml
M    services/JaxRsServiceProvider/src/main/resources/META-INF/persistence.xml
_M   services/dimension/service
_M   services/dimension/jaxb
M    services/common/src/main/java/org/collectionspace/services/common/context/ServiceContext.java
M    services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContext.java
M    services/common/pom.xml
M    services/pom.xml
M    services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java
M    services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java
M    services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java
M    services/account/service/pom.xml
M    services/account/jaxb/src/main/resources/accounts_common.xsd
A    services/account/client/src/test/java/org/collectionspace/services/account
A    services/account/client/src/test/java/org/collectionspace/services/account/client
A    services/account/client/src/test/java/org/collectionspace/services/account/client/test
A  + services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountTest.java
A  + services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountServiceTest.java
D    services/account/client/src/test/java/org/collectionspace/services/client/test/AccountTest.java
D    services/account/client/src/test/java/org/collectionspace/services/client/test/AccountServiceTest.java
D    services/account/client/src/test/java/org/collectionspace/services/client/AccountClient.java
D    services/account/client/src/test/java/org/collectionspace/services/client/AccountProxy.java
M    services/account/client/src/test/resources/META-INF/persistence.xml
M    services/account/client/src/test/resources/log4j.properties
A  + services/account/client/src/main/java/org/collectionspace/services/client/AccountClient.java
A  + services/account/client/src/main/java/org/collectionspace/services/client/AccountProxy.java
A    services/account/client/src/main/resources/db/mysql/test_account.sql
M    services/account/client/src/main/resources/db/mysql/account.sql
M    services/account/client/pom.xml
M    services/account/client/build.xml
M    services/build.xml
M    services/client/src/main/java/org/collectionspace/services/client/test/AbstractServiceTest.java
M    services/client/src/main/java/org/collectionspace/services/client/test/ServiceRequestType.java

34 files changed:
services/JaxRsServiceProvider/src/main/resources/META-INF/persistence.xml
services/account/client/build.xml
services/account/client/pom.xml
services/account/client/src/main/java/org/collectionspace/services/client/AccountClient.java [moved from services/account/client/src/test/java/org/collectionspace/services/client/AccountClient.java with 100% similarity]
services/account/client/src/main/java/org/collectionspace/services/client/AccountProxy.java [moved from services/account/client/src/test/java/org/collectionspace/services/client/AccountProxy.java with 100% similarity]
services/account/client/src/main/resources/db/mysql/account.sql
services/account/client/src/main/resources/db/mysql/test_account.sql [new file with mode: 0644]
services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountServiceTest.java [moved from services/account/client/src/test/java/org/collectionspace/services/client/test/AccountServiceTest.java with 78% similarity]
services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountTest.java [moved from services/account/client/src/test/java/org/collectionspace/services/client/test/AccountTest.java with 63% similarity]
services/account/client/src/test/resources/META-INF/persistence.xml
services/account/client/src/test/resources/log4j.properties
services/account/jaxb/src/main/resources/accounts_common.xsd
services/account/service/pom.xml
services/account/service/src/main/java/org/collectionspace/services/account/AccountResource.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java
services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountStorageClient.java
services/authentication/client/pom.xml
services/authentication/client/src/main/resources/db/mysql/authentication.sql
services/authentication/client/src/main/resources/db/mysql/test_authn.sql
services/authentication/client/src/test/java/org/collectionspace/services/authentication/client/AuthenticationServiceTest.java
services/authentication/jaxb/pom.xml
services/authentication/jaxb/src/main/resources/authentication_identity_provider.xsd
services/authentication/service/pom.xml
services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceDBLoginModule.java
services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceTenant.java [new file with mode: 0644]
services/authentication/service/src/main/java/org/collectionspace/authentication/DatabaseRealm.java [new file with mode: 0644]
services/authentication/service/src/main/resources/config/jboss-login-config.xml
services/build.xml
services/client/src/main/java/org/collectionspace/services/client/test/AbstractServiceTest.java
services/client/src/main/java/org/collectionspace/services/client/test/ServiceRequestType.java
services/common/pom.xml
services/common/src/main/java/org/collectionspace/services/common/context/AbstractServiceContext.java
services/common/src/main/java/org/collectionspace/services/common/context/ServiceContext.java
services/pom.xml

index c8b051378bf992fb8371f4a85b951b8c08f75f71..b200fabf5a17beb0247ad31cb954e2a03c1548ac 100644 (file)
@@ -1,15 +1,17 @@
 <?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">
+             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">
         <provider>org.hibernate.ejb.HibernatePersistence</provider>
         <non-jta-data-source>CspaceDS</non-jta-data-source>
         <class>org.collectionspace.services.account.AccountsCommon</class>
+        <class>org.collectionspace.services.account.AccountsCommon$Tenant</class>
         <class>org.collectionspace.services.account.AccountsCommonList</class>
         <class>org.collectionspace.services.account.AccountsCommonList$AccountListItem</class>
         <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.dialect" value="org.hibernate.dialect.MySQLDialect"/>
             <property name="hibernate.max_fetch_depth" value="3"/>
index 538e37c770dbde7c9bf06313b8c1a91ed83be3e8..b41dd80a0b07ec70c5765ed40dcc91bbf827db0b 100644 (file)
@@ -3,7 +3,7 @@
     <description>\r
         collectionspace account service\r
     </description>\r
-  <!-- set global properties for this build -->\r
+    <!-- set global properties for this build -->\r
     <property name="services.trunk" value="../../.."/>\r
     <!-- enviornment should be declared before reading build.properties -->\r
     <property environment="env" />\r
     </condition>\r
 \r
     <target name="init">\r
-    <!-- Create the time stamp -->\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
+            description="Package CollectionSpace Services" />\r
     <target name="package-unix" if="osfamily-unix">\r
         <exec executable="mvn" failonerror="true">\r
             <arg value="package" />\r
@@ -50,7 +50,7 @@
     </target>\r
 \r
     <target name="install" depends="package,install-unix,install-windows"\r
-  description="Install" />\r
+            description="Install" />\r
     <target name="install-unix" if="osfamily-unix">\r
         <exec executable="mvn" failonerror="true">\r
             <arg value="install" />\r
@@ -73,9 +73,9 @@
             <arg value="${mvn.opts}" />\r
         </exec>\r
     </target>\r
-    \r
+\r
     <target name="clean" depends="clean-unix,clean-windows"\r
-  description="Delete target directories" >\r
+            description="Delete target directories" >\r
         <delete dir="${build}"/>\r
     </target>\r
     <target name="clean-unix" if="osfamily-unix">\r
     </target>\r
 \r
     <target name="gen_ddl" depends="gen_ddl-unix,gen_ddl-windows"\r
-  description="geneate ddl" />\r
+            description="geneate ddl" />\r
     <target name="gen_ddl-unix" if="osfamily-unix" depends="setup_hibernate.cfg">\r
         <exec executable="mvn" failonerror="true">\r
             <arg value="-Pddl" />\r
     </target>\r
 \r
     <target name="create_db"\r
-    description="create tables(s), indices for account service">\r
+            description="create tables(s), indices for account 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}/account.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}/account.sql"\r
-        >\r
+             url="jdbc:mysql://${db.host}:${db.port}/cspace"\r
+             userid="${db.user}"\r
+             password="${db.user.password}"\r
+             src="${db.script.dir}/test_account.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 account service in ${jboss.server.cspace}">\r
+            description="deploy account 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 account service from ${jboss.server.cspace}">\r
+            description="undeploy account service from ${jboss.server.cspace}">\r
     </target>\r
 \r
     <target name="dist"\r
-    description="generate distribution for account service" depends="package">\r
+            description="generate distribution for account 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
index 8991f43d6fe02f929dd6deb04325c9c560e11f9b..3f0d57433670ad1a618e266f75eb026d42240164 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 <project xmlns="http://maven.apache.org/POM/4.0.0"\r
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">\r
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">\r
 \r
     <parent>\r
         <artifactId>org.collectionspace.services.account</artifactId>\r
@@ -40,7 +40,7 @@
             <artifactId>org.collectionspace.services.client</artifactId>\r
             <version>1.0</version>\r
         </dependency>\r
-<!-- Needed if/when client test framework files are moved into\r
+        <!-- Needed if/when client test framework files are moved into\r
 /services/client/src/test from /services/client/src/main -->     \r
 <!--    <dependency>\r
             <groupId>org.collectionspace.services</groupId>\r
@@ -49,7 +49,7 @@
             <scope>test</scope>\r
             <type>test-jar</type>\r
         </dependency>-->\r
-        \r
+\r
         <dependency>\r
             <groupId>org.testng</groupId>\r
             <artifactId>testng</artifactId>\r
@@ -89,7 +89,7 @@
             <artifactId>mysql-connector-java</artifactId>\r
         </dependency>\r
     </dependencies>\r
-    \r
+\r
     <build>\r
         <finalName>cspace-services-account-client</finalName>\r
         <plugins>\r
index 6a3122c6ffade6d15778bd3f2bc66eb9cb110d86..2f5c9a0b1a4ac053cfda2033f7fe340cd677b569 100644 (file)
@@ -1,2 +1,6 @@
+alter table tenants drop foreign key FKAAE82D09C4F08FD6;
 drop table if exists accounts_common;
-create table accounts_common (csid varchar(255) not null, email longtext not null, first_name longtext not null, last_name longtext not null, mi varchar(1), mobile varchar(255), phone varchar(255), screen_name varchar(128) not null, status varchar(15) not null, tenantid varchar(255) not null, userid longtext not null, primary key (csid));
+drop table if exists tenants;
+create table accounts_common (csid varchar(255) not null, email longtext not null, mobile varchar(255), phone varchar(255), screen_name varchar(128) not null, status varchar(15) not null, userid longtext not null, primary key (csid));
+create table tenants (HJID bigint not null auto_increment, id varchar(255) not null, name varchar(255) not null, TENANT_ACCOUNTSCOMMON_CSID varchar(255), primary key (HJID));
+alter table tenants add index FKAAE82D09C4F08FD6 (TENANT_ACCOUNTSCOMMON_CSID), add constraint FKAAE82D09C4F08FD6 foreign key (TENANT_ACCOUNTSCOMMON_CSID) references accounts_common (csid);
diff --git a/services/account/client/src/main/resources/db/mysql/test_account.sql b/services/account/client/src/main/resources/db/mysql/test_account.sql
new file mode 100644 (file)
index 0000000..ddc6e7b
--- /dev/null
@@ -0,0 +1,9 @@
+--
+-- 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 `cspace`.`accounts_common` VALUES  ('eeca40d7-dc77-4cc5-b489-16a53c75525a','test.test@berkeley.edu',NULL,NULL,'test','ACTIVE','test');
+
+INSERT INTO `cspace`.`tenants` VALUES  (1,'1','movingimages.us','eeca40d7-dc77-4cc5-b489-16a53c75525a');
\ No newline at end of file
similarity index 78%
rename from services/account/client/src/test/java/org/collectionspace/services/client/test/AccountServiceTest.java
rename to services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountServiceTest.java
index bf5ac4ab839eeb9af6be2bfde2ef7191c4b8735d..3939470ae2cd622701301bad363508ea3f464dff 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.collectionspace.services.client.test;
+package org.collectionspace.services.account.client.test;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.UUID;
 import javax.ws.rs.core.Response;
 
 import org.apache.commons.codec.binary.Base64;
@@ -30,6 +32,8 @@ import org.collectionspace.services.client.AccountClient;
 import org.collectionspace.services.account.AccountsCommon;
 import org.collectionspace.services.account.AccountsCommonList;
 import org.collectionspace.services.account.Status;
+import org.collectionspace.services.client.test.AbstractServiceTest;
+import org.collectionspace.services.client.test.ServiceRequestType;
 import org.jboss.resteasy.client.ClientResponse;
 
 import org.testng.Assert;
@@ -76,7 +80,7 @@ public class AccountServiceTest extends AbstractServiceTest {
 
         // Submit the request to the service and store the response.
         AccountsCommon account =
-                createAccountInstance("barney", "dino", "barney", "hithere08", "barney@dinoland.com");
+                createAccountInstance("barney", "hithere08", "barney@dinoland.com", true, true, true);
         ClientResponse<Response> res = client.create(account);
         int statusCode = res.getStatus();
 
@@ -101,6 +105,47 @@ public class AccountServiceTest extends AbstractServiceTest {
         }
     }
 
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
+    dependsOnMethods = {"create"})
+    public void createWithoutTenant(String testName) throws Exception {
+
+        setupCreate(testName);
+
+        // Submit the request to the service and store the response.
+        AccountsCommon account =
+                createAccountInstance("babybop", "hithere08", "babybop@dinoland.com", false, true, true);
+        ClientResponse<Response> res = client.create(account);
+        int statusCode = res.getStatus();
+        // Does it exactly match the expected status code?
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
+
+    }
+
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
+    dependsOnMethods = {"create"})
+    public void createWithoutUser(String testName) throws Exception {
+
+        setupCreate(testName);
+
+        // Submit the request to the service and store the response.
+        AccountsCommon account =
+                createAccountInstance("babybop", "hithere08", "babybop@dinoland.com", true, false, true);
+        ClientResponse<Response> res = client.create(account);
+        int statusCode = res.getStatus();
+        // Does it exactly match the expected status code?
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
+    }
+
     //to not cause uniqueness violation for account, createList is removed
     @Override
     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
@@ -209,12 +254,12 @@ public class AccountServiceTest extends AbstractServiceTest {
             int i = 0;
 
             for (AccountsCommonList.AccountListItem item : items) {
-                logger.debug(testName + ": list-item[" + i + "] csid=" +
-                        item.getCsid());
-                logger.debug(testName + ": list-item[" + i + "] screenName=" +
-                        item.getScreenName());
-                logger.debug(testName + ": list-item[" + i + "] URI=" +
-                        item.getUri());
+                logger.debug(testName + ": list-item[" + i + "] csid="
+                        item.getCsid());
+                logger.debug(testName + ": list-item[" + i + "] screenName="
+                        item.getScreenName());
+                logger.debug(testName + ": list-item[" + i + "] URI="
+                        item.getUri());
                 i++;
 
             }
@@ -293,7 +338,7 @@ public class AccountServiceTest extends AbstractServiceTest {
         Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
 
         if (logger.isDebugEnabled()) {
-            logger.debug("got object to update with ID: " + knownResourceId);
+            logger.debug(testName + ": got object to update password with ID: " + knownResourceId);
         }
         AccountsCommon toUpdateAccount =
                 (AccountsCommon) res.getEntity();
@@ -302,7 +347,7 @@ public class AccountServiceTest extends AbstractServiceTest {
         //change password
         toUpdateAccount.setPassword(Base64.encodeBase64("imagination".getBytes()));
         if (logger.isDebugEnabled()) {
-            logger.debug("updated object");
+            logger.debug(testName + ": updated object");
             logger.debug(objectAsXmlString(toUpdateAccount,
                     AccountsCommon.class));
         }
@@ -328,7 +373,50 @@ public class AccountServiceTest extends AbstractServiceTest {
     }
 
     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
-    dependsOnMethods = {"updatePassword"})
+    dependsOnMethods = {"update"})
+    public void updatePasswordWithoutUser(String testName) throws Exception {
+
+        // Perform setup.
+        setupUpdate(testName);
+
+        ClientResponse<AccountsCommon> res =
+                client.read(knownResourceId);
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": read status = " + res.getStatus());
+        }
+        Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + " : got object to update with ID: " + knownResourceId);
+        }
+        AccountsCommon toUpdateAccount =
+                (AccountsCommon) res.getEntity();
+        Assert.assertNotNull(toUpdateAccount);
+
+        toUpdateAccount.setUserId(null);
+        //change password
+        toUpdateAccount.setPassword(Base64.encodeBase64("imagination".getBytes()));
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + " : updated object");
+            logger.debug(objectAsXmlString(toUpdateAccount,
+                    AccountsCommon.class));
+        }
+
+        // Submit the request to the service and store the response.
+        res = client.update(knownResourceId, toUpdateAccount);
+        int statusCode = res.getStatus();
+        // Check the status code of the response: does it match the expected response(s)?
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
+
+    }
+
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
+    dependsOnMethods = {"updatePasswordWithoutUser"})
     public void deactivate(String testName) throws Exception {
 
         // Perform setup.
@@ -405,7 +493,7 @@ public class AccountServiceTest extends AbstractServiceTest {
         // Note: The ID used in this 'create' call may be arbitrary.
         // The only relevant ID may be the one used in updateAccount(), below.
         AccountsCommon account =
-                createAccountInstance("simba", "mufasa", "simba", "tiger", "simba@lionking.com");
+                createAccountInstance("simba", "tiger", "simba@lionking.com", true, true, true);
         ClientResponse<AccountsCommon> res =
                 client.update(NON_EXISTENT_ID, account);
         int statusCode = res.getStatus();
@@ -429,7 +517,7 @@ public class AccountServiceTest extends AbstractServiceTest {
         //
         // Note: The ID used in this 'create' call may be arbitrary.
         // The only relevant ID may be the one used in updateAccount(), below.
-         ClientResponse<AccountsCommon> res =
+        ClientResponse<AccountsCommon> res =
                 client.read(knownResourceId);
         if (logger.isDebugEnabled()) {
             logger.debug(testName + ": read status = " + res.getStatus());
@@ -449,7 +537,7 @@ public class AccountServiceTest extends AbstractServiceTest {
             logger.debug(objectAsXmlString(toUpdateAccount,
                     AccountsCommon.class));
         }
-                EXPECTED_STATUS_CODE = Response.Status.BAD_REQUEST.getStatusCode();
+
         res = client.update(knownResourceId, toUpdateAccount);
         int statusCode = res.getStatus();
 
@@ -460,7 +548,7 @@ public class AccountServiceTest extends AbstractServiceTest {
         }
         Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
                 invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
-        Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+        Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
     }
 
     // ---------------------------------------------------------------
@@ -469,7 +557,7 @@ public class AccountServiceTest extends AbstractServiceTest {
     // Success outcomes
     @Override
     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
-    dependsOnMethods = {"testSubmitRequest", "updateNonExistent"})
+    dependsOnMethods = {"testSubmitRequest", "updateWrongUser"})
     public void delete(String testName) throws Exception {
 
         // Perform setup.
@@ -533,8 +621,8 @@ public class AccountServiceTest extends AbstractServiceTest {
         // Check the status code of the response: does it match
         // the expected response(s)?
         if (logger.isDebugEnabled()) {
-            logger.debug("testSubmitRequest: url=" + url +
-                    " status=" + statusCode);
+            logger.debug("testSubmitRequest: url=" + url
+                    " status=" + statusCode);
         }
         Assert.assertEquals(statusCode, EXPECTED_STATUS);
 
@@ -543,17 +631,38 @@ public class AccountServiceTest extends AbstractServiceTest {
     // ---------------------------------------------------------------
     // Utility methods used by tests above
     // ---------------------------------------------------------------
-    private AccountsCommon createAccountInstance(String firstName, String lastName, String screenName,
-            String passwd, String email) {
+    /*
+     * createAccountInstance
+     * @param tenant fillup tenant
+     * @param user to fill up user
+     * @param password to fill up password
+     */
+    private AccountsCommon createAccountInstance(String screenName,
+            String passwd, String email, boolean tenant, boolean user, boolean password) {
 
         AccountsCommon account = new AccountsCommon();
-        account.setFirstName(firstName);
-        account.setLastName(lastName);
         account.setScreenName(screenName);
-        account.setUserId(screenName);
-        account.setPassword(Base64.encodeBase64(passwd.getBytes()));
+        if (user) {
+            account.setUserId(screenName);
+        }
+        if (password) {
+            account.setPassword(Base64.encodeBase64(passwd.getBytes()));
+        }
         account.setEmail(email);
         account.setPhone("1234567890");
+        if (tenant) {
+            List<AccountsCommon.Tenant> atl = new ArrayList<AccountsCommon.Tenant>();
+            AccountsCommon.Tenant at = new AccountsCommon.Tenant();
+            at.setId(UUID.randomUUID().toString());
+            at.setName("movingimages.us");
+            atl.add(at);
+
+            AccountsCommon.Tenant at2 = new AccountsCommon.Tenant();
+            at2.setId(UUID.randomUUID().toString());
+            at2.setName("collectionspace.org");
+            atl.add(at2);
+            account.setTenant(atl);
+        }
         if (logger.isDebugEnabled()) {
             logger.debug("to be created, account common");
             logger.debug(objectAsXmlString(account,
similarity index 63%
rename from services/account/client/src/test/java/org/collectionspace/services/client/test/AccountTest.java
rename to services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountTest.java
index a2c6ed970949d0eff0f95994677843d16c90f29f..de083f7a1b58f83fcc1fabed30d1089da397f851 100644 (file)
@@ -2,16 +2,20 @@
  * To change this template, choose Tools | Templates
  * and open the template in the editor.
  */
-package org.collectionspace.services.client.test;
+package org.collectionspace.services.account.client.test;
 
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.UUID;
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
+import javax.persistence.NoResultException;
 import javax.persistence.Persistence;
 
 import javax.persistence.Query;
 import org.collectionspace.services.account.AccountsCommon;
+import org.collectionspace.services.account.AccountsCommon.Tenant;
 import org.collectionspace.services.account.Status;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
@@ -52,27 +56,69 @@ public class AccountTest {
         }
     }
 
+    @SuppressWarnings("unchecked")
+    @Test(dataProvider = "testName", dataProviderClass = AccountTest.class)
+    public void createTest(String testName) throws Exception {
+        AccountsCommon account = null;
+        try {
+            account = findAccount("test");
+            if (account != null) {
+                return;
+            }
+        } catch (NoResultException nre) {
+            //ignore
+        }
+        if (account == null) {
+            account = new AccountsCommon();
+        }
+        account.setScreenName("test");
+        account.setEmail("test.test@berkeley.edu");
+        account.setUserId("test");
+        account.setStatus(Status.ACTIVE);
+        id = UUID.randomUUID().toString();
+        account.setCsid(id);
+
+        Tenant tenant = new Tenant();
+        tenant.setId("1");
+        tenant.setName("movingimages.us");
+        List<Tenant> lt = new ArrayList<Tenant>();
+        lt.add(tenant);
+        account.setTenant(lt);
+        em.getTransaction().begin();
+        em.persist(account);
+        // Commit the transaction
+        em.getTransaction().commit();
+        if (logger.isDebugEnabled()) {
+            logger.debug("created/updated account "
+                    + " screen name=" + account.getScreenName()
+                    + " email=" + account.getEmail());
+        }
+    }
+
     @SuppressWarnings("unchecked")
     @Test(dataProvider = "testName", dataProviderClass = AccountTest.class)
     public void create(String testName) throws Exception {
         AccountsCommon account = new AccountsCommon();
         account.setScreenName("john");
-        account.setFirstName("John");
-        account.setLastName("Doe");
         account.setEmail("john.doe@berkeley.edu");
         account.setUserId("johndoe");
         account.setStatus(Status.ACTIVE);
         id = UUID.randomUUID().toString();
         account.setCsid(id);
-        account.setTenantid("123"); //set by service runtime
+        Tenant tenant = new Tenant();
+        tenant.setId("123");
+        tenant.setName("movingimages.us.standalone");
+        List<Tenant> lt = new ArrayList<Tenant>();
+        lt.add(tenant);
+        account.setTenant(lt);
         em.getTransaction().begin();
         em.persist(account);
         // Commit the transaction
         em.getTransaction().commit();
         if (logger.isDebugEnabled()) {
-            logger.debug("created account " +
-                    " first name=" + account.getFirstName() +
-                    " email=" + account.getEmail());
+            logger.debug("created account "
+                    + " screen name=" + account.getScreenName()
+                    " email=" + account.getEmail());
         }
     }
 
@@ -83,8 +129,8 @@ public class AccountTest {
         AccountsCommon account = findAccount("john");
         Assert.assertNotNull(account);
         if (logger.isDebugEnabled()) {
-            logger.debug("read account " +
-                    " first name=" + account.getFirstName());
+            logger.debug("read account "
+                    + " screen name=" + account.getScreenName());
         }
     }
 
@@ -109,9 +155,9 @@ public class AccountTest {
         Assert.assertEquals(no, 1);
         AccountsCommon account = findAccount("john");
         if (logger.isDebugEnabled()) {
-            logger.debug("updated account " +
-                    " first name=" + account.getFirstName() +
-                    " email=" + account.getEmail());
+            logger.debug("updated account "
+                    + " screen name=" + account.getScreenName()
+                    " email=" + account.getEmail());
         }
     }
 
@@ -119,22 +165,19 @@ public class AccountTest {
     @Test(dataProvider = "testName", dataProviderClass = AccountTest.class,
     dependsOnMethods = {"update"})
     public void delete(String testName) throws Exception {
-        Query q = em.createQuery("delete from org.collectionspace.services.account.AccountsCommon where csid=:csid");
-        q.setParameter("csid", id);
         // Begin transaction
         em.getTransaction().begin();
-        int no = q.executeUpdate();
-        ;
+        AccountsCommon account = findAccount("john");
+        em.remove(account);
         if (logger.isDebugEnabled()) {
-            logger.debug("deleting account " +
-                    " csid=" + id);
+            logger.debug("deleting account "
+                    " csid=" + id);
         }
         // Commit the transaction
         em.getTransaction().commit();
-        Assert.assertEquals(no, 1);
         if (logger.isDebugEnabled()) {
-            logger.debug("deleted account " +
-                    " csid=" + id);
+            logger.debug("deleted account "
+                    " csid=" + id);
         }
     }
 
index 123eef2d61801b8aaeb13dc7e8857733b812453b..f4c1e8b49436751aa8005a4db47a482352dbc68e 100644 (file)
@@ -3,6 +3,7 @@
 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.account">
         <class>org.collectionspace.services.account.AccountsCommon</class>
+        <class>org.collectionspace.services.account.AccountsCommon$Tenant</class>
         <class>org.collectionspace.services.account.AccountsCommonList</class>
         <class>org.collectionspace.services.account.AccountsCommonList$AccountListItem</class>
         <properties>
index fa374e9247a5312a8291264f0aa0e2e1a201863b..f9c47870a50e1b0f12349ecbf8b9da7cfc8db2b1 100644 (file)
@@ -22,3 +22,4 @@ log4j.logger.org.apache=INFO
 log4j.logger.httpclient=INFO\r
 log4j.logger.org.jboss.resteasy=INFO\r
 log4j.logger.org.hibernate=INFO\r
+log4j.logger.org.hibernate.cfg=WARN\r
index 169858c3bbf93b4debc6de6f7fe1e651bbbb564c..efc5f0336a62933e2dcd0e962b7c3911621c162a 100644 (file)
@@ -2,28 +2,28 @@
 
 <!--
     Account schema (XSD)
-    
+
     Entity  : Account
     Part    : Common
     Used for: JAXB binding between XML and Java objects
-    
+
     $LastChangedRevision: 916 $
     $LastChangedDate: 2009-11-05 16:59:20 -0800 (Thu, 05 Nov 2009) $
 -->
 
 <xs:schema 
-  xmlns:xs="http://www.w3.org/2001/XMLSchema"
-  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
-  xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
-  xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
-  xmlns:ns="http://collectionspace.org/servics/account"
-  xmlns="http://collectionspace.org/services/account"
-  targetNamespace="http://collectionspace.org/services/account"
-  version="0.1"
-  jaxb:extensionBindingPrefixes="hj orm"
->
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+    xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
+    xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
+    xmlns:ns="http://collectionspace.org/servics/account"
+    xmlns="http://collectionspace.org/services/account"
+    targetNamespace="http://collectionspace.org/services/account"
+    version="0.1"
+    jaxb:extensionBindingPrefixes="hj orm"
+    >
 
-<!--
+    <!--
     Avoid XmlRootElement nightmare:
     See http://weblogs.java.net/blog/kohsuke/archive/2006/03/why_does_jaxb_p.html
 -->
                         </xs:appinfo>
                     </xs:annotation>
                 </xs:element>
-                <xs:element name="firstName" type="xs:string" minOccurs="1" maxOccurs="1">
-                    <xs:annotation>
-                        <xs:appinfo>
-                            <hj:basic>
-                                <orm:column name="first_name" length="256" nullable="false"/>
-                            </hj:basic>
-                        </xs:appinfo>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="lastName" type="xs:string" minOccurs="1" maxOccurs="1">
-                    <xs:annotation>
-                        <xs:appinfo>
-                            <hj:basic>
-                                <orm:column name="last_name" length="256" nullable="false"/>
-                            </hj:basic>
-                        </xs:appinfo>
-                    </xs:annotation>
-                </xs:element>
-                <xs:element name="mi" type="xs:string">
-                    <xs:annotation>
-                        <xs:appinfo>
-                            <hj:basic>
-                                <orm:column name="mi" length="1" nullable="true"/>
-                            </hj:basic>
-                        </xs:appinfo>
-                    </xs:annotation>
-                </xs:element>
                 <xs:element name="email" type="xs:string" minOccurs="1" maxOccurs="1">
                     <xs:annotation>
                         <xs:appinfo>
                     </xs:annotation>
                 </xs:element>
                 <!-- userid, could be calnet id, openid URI -->
-                <xs:element name="userId" type="xs:string" minOccurs="0" maxOccurs="1">
+                <xs:element name="userId" type="xs:string" minOccurs="1" maxOccurs="1">
                     <xs:annotation>
                         <xs:appinfo>
                             <hj:basic>
                         </xs:appinfo>
                     </xs:annotation>
                 </xs:element>
-                <!-- 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 name="tenant" minOccurs="1" maxOccurs="unbounded">
+                    <xs:complexType>
+                        <xs:annotation>
+                            <xs:appinfo>
+                                <hj:entity>
+                                    <orm:table name="tenants"/>
+                                </hj:entity>
+                            </xs:appinfo>
+                        </xs:annotation>
+                        <xs:sequence>
+                            <xs:element name="id" type="xs:string" minOccurs="1">
+                                <xs:annotation>
+                                    <xs:appinfo>
+                                        <hj:basic>
+                                            <orm:column name="id" nullable="false"/>
+                                        </hj:basic>
+                                    </xs:appinfo>
+                                </xs:annotation>
+                            </xs:element>
+                            <xs:element name="name" type="xs:string" minOccurs="1">
+                                <xs:annotation>
+                                    <xs:appinfo>
+                                        <hj:basic>
+                                            <orm:column name="name" nullable="false"/>
+                                        </hj:basic>
+                                    </xs:appinfo>
+                                </xs:annotation>
+                            </xs:element>
+                        </xs:sequence>
+
+                    </xs:complexType>
                 </xs:element>
                 <xs:element name="status" type="status">
                     <xs:annotation>
index 85138a9adf4db8b2b381d00acc6b0ae890c73ce5..327d1bd1ac6dc438e17e244d177d8e0ffe7beec4 100644 (file)
@@ -6,7 +6,7 @@
         <groupId>org.collectionspace.services</groupId>\r
         <version>1.0</version>\r
     </parent>\r
-    \r
+\r
     <modelVersion>4.0.0</modelVersion>\r
     <groupId>org.collectionspace.services</groupId>\r
     <artifactId>org.collectionspace.services.account.service</artifactId>\r
@@ -38,7 +38,7 @@
             <groupId>org.slf4j</groupId>\r
             <artifactId>slf4j-log4j12</artifactId>\r
         </dependency>\r
-        \r
+\r
         <dependency>\r
             <groupId>junit</groupId>\r
             <artifactId>junit</artifactId>\r
@@ -50,7 +50,7 @@
             <artifactId>testng</artifactId>\r
             <version>5.6</version>\r
         </dependency>\r
-        \r
+\r
         <!-- apache -->\r
         <dependency>\r
             <groupId>commons-beanutils</groupId>\r
@@ -62,7 +62,7 @@
             <artifactId>commons-logging</artifactId>\r
             <version>1.1</version>\r
         </dependency>\r
-      <!-- javax -->\r
+        <!-- javax -->\r
 \r
 \r
         <dependency>\r
@@ -72,7 +72,7 @@
             <scope>provided</scope>\r
         </dependency>\r
 \r
-        \r
+\r
         <!-- jboss -->\r
 \r
         <dependency>\r
             <artifactId>resteasy-multipart-provider</artifactId>\r
             <version>1.1.GA</version>\r
         </dependency>\r
-        \r
+\r
 \r
     </dependencies>\r
-    \r
+\r
     <build>\r
         <finalName>collectionspace-services-account</finalName>\r
         <plugins>\r
index dca0561d1c2df872b1b084fe013faea301aebe05..9261e4d9513a4ed60089a2921895fe184acdb089 100644 (file)
@@ -100,6 +100,10 @@ public class AccountResource
             path.path("" + csid);
             Response response = Response.created(path.build()).build();
             return response;
+        } catch (BadRequestException bre) {
+            Response response = Response.status(
+                    Response.Status.BAD_REQUEST).entity("Create failed reason " + bre.getErrorReason()).type("text/plain").build();
+            throw new WebApplicationException(response);
         } catch (UnauthorizedException ue) {
             Response response = Response.status(
                     Response.Status.UNAUTHORIZED).entity("Create failed reason " + ue.getErrorReason()).type("text/plain").build();
index bdc735a85db346021d0d8af5fe1d6efc3463f5d4..afe561ad0584efe7b3411fdcaf35c0b97c3a87c3 100644 (file)
@@ -30,8 +30,10 @@ import org.collectionspace.services.account.AccountsCommonList;
 import org.collectionspace.services.account.AccountsCommonList.AccountListItem;
 import org.collectionspace.services.account.Status;
 import org.collectionspace.services.common.document.AbstractDocumentHandler;
+import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentWrapper;
-import org.collectionspace.services.nuxeo.util.NuxeoUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  *
@@ -40,6 +42,7 @@ import org.collectionspace.services.nuxeo.util.NuxeoUtils;
 public class AccountDocumentHandler
         extends AbstractDocumentHandler<AccountsCommon, AccountsCommonList, AccountsCommon, List> {
 
+    private final Logger logger = LoggerFactory.getLogger(AccountDocumentHandler.class);
     private AccountsCommon account;
     private AccountsCommonList accountList;
 
@@ -47,12 +50,29 @@ public class AccountDocumentHandler
     public void handleCreate(DocumentWrapper<AccountsCommon> wrapDoc) throws Exception {
         String id = UUID.randomUUID().toString();
         AccountsCommon account = wrapDoc.getWrappedObject();
+        if (account.getUserId() == null || "".equals(account.getUserId())) {
+            String msg = "userId is missing";
+            logger.error(msg);
+            throw new BadRequestException(msg);
+        }
+        List<AccountsCommon.Tenant> tl = account.getTenant();
+        if (tl == null || tl.size() == 0) {
+            String msg = "missing tenant information!";
+            logger.error(msg);
+            throw new BadRequestException(msg);
+        }
         account.setCsid(id);
         account.setStatus(Status.ACTIVE);
     }
 
     @Override
     public void handleUpdate(DocumentWrapper<AccountsCommon> wrapDoc) throws Exception {
+        if (account.getPassword() != null
+                && (account.getUserId() == null || "".equals(account.getUserId()))) {
+            String msg = "userId is missing";
+            logger.error(msg);
+            throw new BadRequestException(msg);
+        }
     }
 
     @Override
@@ -102,8 +122,6 @@ public class AccountDocumentHandler
             AccountListItem accListItem = new AccountListItem();
             accListItem.setScreenName(account.getScreenName());
             accListItem.setEmail(account.getEmail());
-            accListItem.setFirstName(account.getFirstName());
-            accListItem.setLastName(account.getLastName());
             accListItem.setStatus(account.getStatus());
             String id = account.getCsid();
             accListItem.setUri(getServiceContextPath() + id);
@@ -144,7 +162,6 @@ public class AccountDocumentHandler
      * @param account
      */
     private void sanitize(AccountsCommon account) {
-        account.setTenantid("");
         account.setPassword(null);
     }
 }
index f069b0f9e6befd4c03ce5bf412a07d724215561b..0e1dcd8f0839406d9a3019aa6536db424031b312 100644 (file)
  */
 package org.collectionspace.services.account.storage;
 
+import java.util.ArrayList;
+import java.util.List;
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
-import javax.persistence.NoResultException;
 import javax.persistence.Query;
 import org.apache.commons.codec.binary.Base64;
 import org.collectionspace.services.account.AccountsCommon;
@@ -33,7 +34,6 @@ import org.collectionspace.services.authentication.User;
 import org.collectionspace.services.common.context.ServiceContext;
 import org.collectionspace.services.common.document.BadRequestException;
 import org.collectionspace.services.common.document.DocumentException;
-import org.collectionspace.services.common.document.DocumentFilter;
 import org.collectionspace.services.common.document.DocumentHandler;
 import org.collectionspace.services.common.document.DocumentHandler.Action;
 import org.collectionspace.services.common.document.DocumentNotFoundException;
@@ -41,6 +41,7 @@ import org.collectionspace.services.common.document.DocumentWrapper;
 import org.collectionspace.services.common.document.DocumentWrapperImpl;
 import org.collectionspace.services.common.security.SecurityUtils;
 import org.collectionspace.services.common.storage.jpa.JpaStorageClient;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -83,14 +84,22 @@ 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, ctx.getTenantId());
+                User user = createUser(account);
                 em.persist(user);
             }
-            account.setTenantid(ctx.getTenantId());
+//            if (account.getTenant() != null) {
+//                UserTenant ut = createTenantAssoc(account);
+//                em.persist(ut);
+//            }
             em.persist(account);
             em.getTransaction().commit();
             handler.complete(Action.CREATE, wrapDoc);
             return (String) getValue(account, "getCsid");
+        } catch (BadRequestException bre) {
+            if (em != null && em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
+            throw bre;
         } catch (Exception e) {
             if (em != null && em.getTransaction().isActive()) {
                 em.getTransaction().rollback();
@@ -138,15 +147,21 @@ public class AccountStorageClient extends JpaStorageClient {
             if (account.getUserId() != null && account.getPassword() != null) {
 
                 User userFound = getUser(em, account);
-                User user = createUser(account, ctx.getTenantId());
+                User user = createUser(account);
                 em.merge(user);
             }
             em.merge(account);
             em.getTransaction().commit();
             handler.complete(Action.UPDATE, wrapDoc);
         } catch (BadRequestException bre) {
+            if (em != null && em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
             throw bre;
         } catch (DocumentException de) {
+            if (em != null && em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
             throw de;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
@@ -192,8 +207,8 @@ public class AccountStorageClient extends JpaStorageClient {
 
             //if userid gives any indication about the id provider, it should
             //be used to avoid the following approach
-            User userLocal = em.find(User.class, accountFound.getUserId());
             Query usrDel = null;
+            User userLocal = getUser(em, accountFound);
             if (userLocal != null) {
                 StringBuilder usrDelStr = new StringBuilder("DELETE FROM ");
                 usrDelStr.append(User.class.getCanonicalName());
@@ -203,12 +218,12 @@ public class AccountStorageClient extends JpaStorageClient {
                 usrDel.setParameter("username", accountFound.getUserId());
             }
             em.getTransaction().begin();
-            int accDelCount = accDel.executeUpdate();
-            if (accDelCount != 1) {
-                if (em != null && em.getTransaction().isActive()) {
-                    em.getTransaction().rollback();
-                }
-            }
+//            int accDelCount = accDel.executeUpdate();
+//            if (accDelCount != 1) {
+//                if (em != null && em.getTransaction().isActive()) {
+//                    em.getTransaction().rollback();
+//                }
+//            }
             if (userLocal != null) {
                 int usrDelCount = usrDel.executeUpdate();
                 if (usrDelCount != 1) {
@@ -222,9 +237,13 @@ public class AccountStorageClient extends JpaStorageClient {
                     throw new DocumentNotFoundException(msg);
                 }
             }
+            em.remove(accountFound);
             em.getTransaction().commit();
 
         } catch (DocumentException de) {
+            if (em != null && em.getTransaction().isActive()) {
+                em.getTransaction().rollback();
+            }
             throw de;
         } catch (Exception e) {
             if (logger.isDebugEnabled()) {
@@ -264,9 +283,8 @@ public class AccountStorageClient extends JpaStorageClient {
         return true;
     }
 
-    private User createUser(AccountsCommon account, String tenantId) {
+    private User createUser(AccountsCommon account) {
         User user = new User();
-        user.setTenantid(tenantId);
         user.setUsername(account.getUserId());
         byte[] bpass = Base64.decodeBase64(account.getPassword());
         SecurityUtils.validatePassword(new String(bpass));
@@ -288,4 +306,20 @@ public class AccountStorageClient extends JpaStorageClient {
         }
         return userFound;
     }
+
+//    private UserTenant createTenantAssoc(AccountsCommon account) {
+//        UserTenant userTenant = new UserTenant();
+//        userTenant.setUserId(account.getUserId());
+//        List<AccountsCommon.Tenant> atl = account.getTenant();
+//        List<UserTenant.Tenant> utl =
+//                new ArrayList<UserTenant.Tenant>();
+//        for (AccountsCommon.Tenant at : atl) {
+//            UserTenant.Tenant ut = new UserTenant.Tenant();
+//            ut.setId(at.getId());
+//            ut.setName(at.getName());
+//            utl.add(ut);
+//        }
+//        userTenant.setTenant(utl);
+//        return userTenant;
+//    }
 }
index 0c3c0182266e71dec4232f7d7d3a3725beb33099..44c8cf0fb83bc18d6c46ed1234877307161f29a8 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 <project xmlns="http://maven.apache.org/POM/4.0.0"\r
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">\r
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">\r
 \r
     <parent>\r
         <artifactId>org.collectionspace.services.authentication</artifactId>\r
             <artifactId>org.collectionspace.services.client</artifactId>\r
             <version>1.0</version>\r
         </dependency>\r
-        <!-- authentication tests use CollectionObject service -->\r
+        <!-- authentication tests use CollectionObject service and Account service -->\r
+        <dependency>\r
+            <groupId>org.collectionspace.services</groupId>\r
+            <artifactId>org.collectionspace.services.account.client</artifactId>\r
+            <version>1.0</version>\r
+        </dependency>\r
         <dependency>\r
             <groupId>org.collectionspace.services</groupId>\r
             <artifactId>org.collectionspace.services.collectionobject.client</artifactId>\r
@@ -83,7 +88,7 @@
             <artifactId>mysql-connector-java</artifactId>\r
         </dependency>\r
     </dependencies>\r
-    \r
+\r
     <build>\r
         <finalName>cspace-services-collectionobject-client</finalName>\r
         <plugins>\r
index 863a09caaea9c4ec62d4ca8092668f048474d200..a985e957e635c801b1d97b48ed1c94f9379046bf 100644 (file)
@@ -1,6 +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));
+create table roles (rolename varchar(255) not null, rolegroup varchar(255) not null, primary key (rolename));
+create table users (username varchar(255) not null, passwd varchar(128) not null, primary key (username));
+create table users_roles (HJID bigint not null auto_increment, rolename varchar(255) not null, username varchar(255) not null, primary key (HJID));
index dde95566a85dce01082834af1ab30e68a9ff99ff..8daa17f59a978d9dbe96f03c7c1818f5a405d592 100644 (file)
@@ -5,10 +5,11 @@
 --\r
 use cspace;\r
 \r
-INSERT INTO `users` (`username`,`passwd`, `tenantid`) VALUES ('test','n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=', '1');\r
+insert into `users` (`username`,`passwd`) VALUES ('test','n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=');\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
+insert into `roles` (`rolename`, `rolegroup`) values ('kernel', 'kernel');\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, `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
+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
index 2ca1edb11be47ba5eb96bba32b848495c9492092..3ead7909ac219d6e260609d4b199ffeeb06e576b 100644 (file)
  */
 package org.collectionspace.services.authentication.client;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import org.apache.commons.codec.binary.Base64;
+import org.collectionspace.services.client.AccountClient;
+import org.collectionspace.services.account.AccountsCommon;
 import org.jboss.resteasy.client.ClientResponse;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -48,6 +54,8 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
 
     /** The known resource id. */
     private String knownResourceId = null;
+    private String barneyAccountId = null;
+    private String babybopAccountId = null;
     /** The logger. */
     final Logger logger = LoggerFactory.getLogger(AuthenticationServiceTest.class);
 
@@ -61,12 +69,69 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
         return null;
     }
 
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class)
+    public void createAccounts(String testName) throws Exception {
+        // Perform setup, such as initializing the type of service request
+        // (e.g. CREATE, DELETE), its valid and expected status codes, and
+        // its associated HTTP method name (e.g. POST, DELETE).
+        setupCreate(testName);
+        AccountClient accountClient = new AccountClient();
+        if (!accountClient.isServerSecure()) {
+            logger.warn("set -Dcspace.server.secure=true to run security tests");
+            return;
+        }
+        accountClient.setProperty(CollectionSpaceClient.AUTH_PROPERTY,
+                "true");
+        accountClient.setProperty(CollectionSpaceClient.USER_PROPERTY,
+                "test");
+        accountClient.setProperty(
+                CollectionSpaceClient.PASSWORD_PROPERTY, "test");
+        // Submit the request to the service and store the response.
+        AccountsCommon account =
+                createAccountInstance("barney", "barney08", "barney@dinoland.com", "1");
+        ClientResponse<Response> res = accountClient.create(account);
+        int statusCode = res.getStatus();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": barney status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+        // Store the ID returned from this create operation
+        // for additional tests below.
+        barneyAccountId = extractId(res);
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": barneyAccountId=" + barneyAccountId);
+        }
+
+        account = createAccountInstance("babybop", "babybop09", "babybop@dinoland.com", "non-existent");
+        res = accountClient.create(account);
+        statusCode = res.getStatus();
+
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": babybop status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+
+        // Store the ID returned from this create operation
+        // for additional tests below.
+        babybopAccountId = extractId(res);
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": babybopAccountId=" + babybopAccountId);
+        }
+
+    }
+
+
     /* (non-Javadoc)
      * @see org.collectionspace.services.client.test.AbstractServiceTest#create()
      */
-    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class)
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
+    dependsOnMethods = {"createAccounts"})
     @Override
     public void create(String testName) {
+        setupCreate(testName);
         CollectionObjectClient collectionObjectClient = new CollectionObjectClient();
         String identifier = this.createIdentifier();
         MultipartOutput multipart = createCollectionObjectInstance(
@@ -79,9 +144,9 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
         collectionObjectClient.setProperty(CollectionSpaceClient.AUTH_PROPERTY,
                 "true");
         collectionObjectClient.setProperty(CollectionSpaceClient.USER_PROPERTY,
-                "test");
+                "barney");
         collectionObjectClient.setProperty(
-                CollectionSpaceClient.PASSWORD_PROPERTY, "test");
+                CollectionSpaceClient.PASSWORD_PROPERTY, "barney08");
         try {
             collectionObjectClient.setupHttpClient();
             collectionObjectClient.setProxy();
@@ -101,10 +166,11 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
     }
 
     /**
-     * Creates the collection object instance without user.
+     * Creates the collection object instance without password.
      */
-    @Test(dependsOnMethods = {"create"})
-    public void createWithoutUser() {
+    @Test(dependsOnMethods = {"createAccounts"})
+    public void createWithoutPassword() {
+        banner("createWithoutPassword");
         CollectionObjectClient collectionObjectClient = new CollectionObjectClient();
         String identifier = this.createIdentifier();
         MultipartOutput multipart = createCollectionObjectInstance(
@@ -115,28 +181,29 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
         }
         collectionObjectClient.setProperty(CollectionSpaceClient.AUTH_PROPERTY,
                 "true");
-        collectionObjectClient.removeProperty(CollectionSpaceClient.USER_PROPERTY);
-        collectionObjectClient.setProperty(
-                CollectionSpaceClient.PASSWORD_PROPERTY, "test");
+        collectionObjectClient.setProperty(CollectionSpaceClient.USER_PROPERTY,
+                "test");
+        collectionObjectClient.removeProperty(CollectionSpaceClient.PASSWORD_PROPERTY);
         try {
             collectionObjectClient.setupHttpClient();
             collectionObjectClient.setProxy();
         } catch (Exception e) {
-            logger.error("createWithoutUser: caught " + e.getMessage());
+            logger.error("createWithoutPassword: caught " + e.getMessage());
             return;
         }
         ClientResponse<Response> res = collectionObjectClient.create(multipart);
         if (logger.isDebugEnabled()) {
-            logger.debug("createWithoutUser: status = " + res.getStatus());
+            logger.debug("createWithoutPassword: status = " + res.getStatus());
         }
         Assert.assertEquals(res.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode(), "expected " + Response.Status.UNAUTHORIZED.getStatusCode());
     }
 
     /**
-     * Creates the collection object instance without password.
+     * Creates the collection object with unknown user
      */
-    @Test(dependsOnMethods = {"createWithoutUser"})
-    public void createWithoutPassword() {
+    @Test(dependsOnMethods = {"createAccounts"})
+    public void createWithUnknownUser() {
+        banner("createWithUnknownUser");
         CollectionObjectClient collectionObjectClient = new CollectionObjectClient();
         String identifier = this.createIdentifier();
         MultipartOutput multipart = createCollectionObjectInstance(
@@ -148,18 +215,19 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
         collectionObjectClient.setProperty(CollectionSpaceClient.AUTH_PROPERTY,
                 "true");
         collectionObjectClient.setProperty(CollectionSpaceClient.USER_PROPERTY,
-                "test");
-        collectionObjectClient.removeProperty(CollectionSpaceClient.PASSWORD_PROPERTY);
+                "foo");
+        collectionObjectClient.setProperty(CollectionSpaceClient.PASSWORD_PROPERTY,
+                "bar");
         try {
             collectionObjectClient.setupHttpClient();
             collectionObjectClient.setProxy();
         } catch (Exception e) {
-            logger.error("createWithoutPassword: caught " + e.getMessage());
+            logger.error("createWithUnknownUser: caught " + e.getMessage());
             return;
         }
         ClientResponse<Response> res = collectionObjectClient.create(multipart);
         if (logger.isDebugEnabled()) {
-            logger.debug("createWithoutPassword: status = " + res.getStatus());
+            logger.debug("createWithUnknownUser: status = " + res.getStatus());
         }
         Assert.assertEquals(res.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode(), "expected " + Response.Status.UNAUTHORIZED.getStatusCode());
     }
@@ -167,8 +235,9 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
     /**
      * Creates the collection object instance with incorrect password.
      */
-    @Test(dependsOnMethods = {"createWithoutPassword"})
+    @Test(dependsOnMethods = {"createAccounts"})
     public void createWithIncorrectPassword() {
+        banner("createWithIncorrectPassword");
         CollectionObjectClient collectionObjectClient = new CollectionObjectClient();
         String identifier = this.createIdentifier();
         MultipartOutput multipart = createCollectionObjectInstance(
@@ -198,10 +267,11 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
     }
 
     /**
-     * Creates the collection object instance without user password.
+     * Creates the collection object instance with incorrect user password.
      */
-    @Test(dependsOnMethods = {"createWithoutPassword"})
-    public void createWithoutUserPassword() {
+    @Test(dependsOnMethods = {"createAccounts"})
+    public void createWithIncorrectUserPassword() {
+        banner("createWithIncorrectUserPassword");
         CollectionObjectClient collectionObjectClient = new CollectionObjectClient();
         String identifier = this.createIdentifier();
         MultipartOutput multipart = createCollectionObjectInstance(
@@ -212,27 +282,31 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
         }
         collectionObjectClient.setProperty(CollectionSpaceClient.AUTH_PROPERTY,
                 "true");
-        collectionObjectClient.removeProperty(CollectionSpaceClient.USER_PROPERTY);
-        collectionObjectClient.removeProperty(CollectionSpaceClient.PASSWORD_PROPERTY);
+        collectionObjectClient.setProperty(CollectionSpaceClient.USER_PROPERTY,
+                "foo");
+        collectionObjectClient.setProperty(
+                CollectionSpaceClient.PASSWORD_PROPERTY, "bar");
         try {
             collectionObjectClient.setupHttpClient();
             collectionObjectClient.setProxy();
         } catch (Exception e) {
-            logger.error("createWithoutUserPassword: caught " + e.getMessage());
+            logger.error("createWithIncorrectUserPassword: caught " + e.getMessage());
             return;
         }
         ClientResponse<Response> res = collectionObjectClient.create(multipart);
         if (logger.isDebugEnabled()) {
-            logger.debug("createWithoutUserPassword: status = " + res.getStatus());
+            logger.debug("createWithIncorrectUserPassword: status = "
+                    + res.getStatus());
         }
-        Assert.assertEquals(res.getStatus(), Response.Status.FORBIDDEN.getStatusCode(), "expected " + Response.Status.FORBIDDEN.getStatusCode());
+        Assert.assertEquals(res.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode(), "expected " + Response.Status.UNAUTHORIZED.getStatusCode());
     }
 
     /**
      * Creates the collection object instance with incorrect user password.
      */
-    @Test(dependsOnMethods = {"createWithoutPassword"})
-    public void createWithIncorrectUserPassword() {
+    @Test(dependsOnMethods = {"createAccounts"})
+    public void createWithoutTenant() {
+        banner("createWithoutTenant");
         CollectionObjectClient collectionObjectClient = new CollectionObjectClient();
         String identifier = this.createIdentifier();
         MultipartOutput multipart = createCollectionObjectInstance(
@@ -244,20 +318,20 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
         collectionObjectClient.setProperty(CollectionSpaceClient.AUTH_PROPERTY,
                 "true");
         collectionObjectClient.setProperty(CollectionSpaceClient.USER_PROPERTY,
-                "foo");
+                "babybop");
         collectionObjectClient.setProperty(
-                CollectionSpaceClient.PASSWORD_PROPERTY, "bar");
+                CollectionSpaceClient.PASSWORD_PROPERTY, "babybop09");
         try {
             collectionObjectClient.setupHttpClient();
             collectionObjectClient.setProxy();
         } catch (Exception e) {
-            logger.error("createWithIncorrectUserPassword: caught " + e.getMessage());
+            logger.error("createWithoutTenant: caught " + e.getMessage());
             return;
         }
         ClientResponse<Response> res = collectionObjectClient.create(multipart);
         if (logger.isDebugEnabled()) {
-            logger.debug("createWithIncorrectUserPassword: status = " +
-                    res.getStatus());
+            logger.debug("createWithoutTenant: status = "
+                    res.getStatus());
         }
         Assert.assertEquals(res.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode(), "expected " + Response.Status.UNAUTHORIZED.getStatusCode());
     }
@@ -267,8 +341,9 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
      */
     @Override
     @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
-    dependsOnMethods = {"createWithIncorrectUserPassword"})
+    dependsOnMethods = {"create"})
     public void delete(String testName) {
+        setupDelete(testName);
         CollectionObjectClient collectionObjectClient = new CollectionObjectClient();
         collectionObjectClient = new CollectionObjectClient();
         if (!collectionObjectClient.isServerSecure()) {
@@ -299,6 +374,41 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
                 Response.Status.OK.getStatusCode(), "expected " + Response.Status.OK.getStatusCode());
     }
 
+    @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
+    dependsOnMethods = {"delete"})
+    public void deleteAccounts(String testName) throws Exception {
+
+        // Perform setup.
+        setupDelete(testName);
+        AccountClient accountClient = new AccountClient();
+        if (!accountClient.isServerSecure()) {
+            logger.warn("set -Dcspace.server.secure=true to run security tests");
+            return;
+        }
+        accountClient.setProperty(CollectionSpaceClient.AUTH_PROPERTY,
+                "true");
+        accountClient.setProperty(CollectionSpaceClient.USER_PROPERTY,
+                "test");
+        accountClient.setProperty(
+                CollectionSpaceClient.PASSWORD_PROPERTY, "test");
+        // Submit the request to the service and store the response.
+        ClientResponse<Response> res = accountClient.delete(barneyAccountId);
+        int statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": barney status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+
+        res = accountClient.delete(babybopAccountId);
+        statusCode = res.getStatus();
+        if (logger.isDebugEnabled()) {
+            logger.debug(testName + ": babybop status = " + statusCode);
+        }
+        Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+                invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+    }
+
     // ---------------------------------------------------------------
     // Utility methods used by tests above
     // ---------------------------------------------------------------
@@ -342,6 +452,38 @@ public class AuthenticationServiceTest extends AbstractServiceTest {
         return multipart;
     }
 
+    private AccountsCommon createAccountInstance(String screenName,
+            String passwd, String email, String tenantId) {
+
+        AccountsCommon account = new AccountsCommon();
+        account.setScreenName(screenName);
+        account.setUserId(screenName);
+        account.setPassword(Base64.encodeBase64(passwd.getBytes()));
+        account.setEmail(email);
+        account.setPhone("1234567890");
+        List<AccountsCommon.Tenant> atl = new ArrayList<AccountsCommon.Tenant>();
+
+        AccountsCommon.Tenant at = new AccountsCommon.Tenant();
+        at.setId(tenantId);//for testing purposes
+        at.setName("movingimages.us");
+        atl.add(at);
+        //disable 2nd tenant till tenant identification is in effect
+        //on the service side for 1-n user-tenants
+//        AccountsCommon.Tenant at2 = new AccountsCommon.Tenant();
+//        at2.setId(UUID.randomUUID().toString());
+//        at2.setName("collectionspace.org");
+//        atl.add(at2);
+        account.setTenant(atl);
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("to be created, account common");
+            logger.debug(objectAsXmlString(account,
+                    AccountsCommon.class));
+        }
+        return account;
+
+    }
+
     /* (non-Javadoc)
      * @see org.collectionspace.services.client.test.AbstractServiceTest#createList()
      */
index 5510cb66683dbab212383f21a0694bf83bab1052..583abbe5f77e09b0880f4f1099123f5dfc3ced32 100644 (file)
             <artifactId>testng</artifactId>
             <version>5.6</version>
         </dependency>
-        <dependency>
-            <groupId>org.collectionspace.services</groupId>
-            <artifactId>org.collectionspace.services.client</artifactId>
-            <version>1.0</version>
-        </dependency>
     </dependencies>
 
     <build>
index e50ed0fa72e36ee3176c1c17f55e3942596f3e34..76eca985bd1788b828a05b409ca35a9d2883c439 100644 (file)
                 </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>
                 </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>
                 </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>
index d0574ba170bb4db2e3a155c57f616238e107db3a..4ee88351143537cce374c0fa2f7a12e691840f72 100644 (file)
     </properties>
 
     <dependencies>
+        <!-- slf4j not available due to classloading issues perhaps -->
         <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
+            <groupId>commons-logging</groupId>
+            <artifactId>commons-logging</artifactId>
+            <version>1.1.1</version>
         </dependency>
+
         <!-- utilities -->
         <dependency>
             <groupId>junit</groupId>
@@ -35,9 +34,7 @@
             <scope>test</scope>
         </dependency>
 
-
-
-      <!-- javax -->
+        <!-- javax -->
         <dependency>
             <groupId>javax.security</groupId>
             <artifactId>jaas</artifactId>
index 6ef9ba8270e7dcee3485fcd1990f3823bd85c4dd..d79b54ff810ba1ae67294000b44d8d8899d3013b 100644 (file)
  */\r
 package org.collectionspace.authentication;\r
 \r
-import java.lang.reflect.Constructor;\r
-import java.security.Principal;\r
 import java.security.acl.Group;\r
-import java.sql.Connection;\r
-import java.sql.PreparedStatement;\r
-import java.sql.ResultSet;\r
-import java.sql.SQLException;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\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.jboss.security.auth.spi.UsernamePasswordLoginModule;\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
+public class CSpaceDBLoginModule extends UsernamePasswordLoginModule {\r
+\r
+    private DatabaseRealm realm;\r
+\r
+    /**\r
+     * Initialize CSpaceDBLoginModule\r
+     *\r
+     * @param options -\r
+     * dsJndiName: The name of the DataSource of the database containing the\r
+     *    Principals, Roles tables\r
+     * principalsQuery: The prepared statement query, equivalent to:\r
+     *    "select Password from Principals where PrincipalID=?"\r
+     * rolesQuery: The prepared statement query, equivalent to:\r
+     *    "select Role, RoleGroup from Roles where PrincipalID=?"\r
+     * tenantsQuery:\r
+     * "select TenantId, TenantName, TenantGroup from Tenants where PrincipalID=?"\r
+     */\r
+    public void initialize(Subject subject, CallbackHandler callbackHandler,\r
+            Map sharedState, Map options) {\r
+        super.initialize(subject, callbackHandler, sharedState, options);\r
+        realm = new DatabaseRealm(options);\r
+    }\r
     //disabled due to classloading problem\r
 //    private Logger logger = LoggerFactory.getLogger(CSpaceDBLoginModule.class);\r
-    private String tenantId;\r
 \r
     protected String getUsersPassword() throws LoginException {\r
 \r
         String username = getUsername();\r
         String password = null;\r
-        Connection conn = null;\r
-        PreparedStatement ps = null;\r
-        ResultSet rs = null;\r
         try {\r
-            conn = getConnection();\r
-            // Get the password\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.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 = realm.getUsersPassword(username);\r
             password = convertRawPassword(password);\r
             if (log.isDebugEnabled()) {\r
                 log.debug("Obtained user password");\r
             }\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
-            throw le;\r
+        } catch (LoginException lex) {\r
+            throw lex;\r
         } catch (Exception ex) {\r
             LoginException le = new LoginException("Unknown Exception");\r
             le.initCause(ex);\r
             throw le;\r
-        } finally {\r
-            if (rs != null) {\r
-                try {\r
-                    rs.close();\r
-                } catch (SQLException e) {\r
-                }\r
-            }\r
-            if (ps != null) {\r
-                try {\r
-                    ps.close();\r
-                } catch (SQLException e) {\r
-                }\r
-            }\r
-            if (conn != null) {\r
-                try {\r
-                    conn.close();\r
-                } catch (SQLException ex) {\r
-                }\r
-            }\r
         }\r
         return password;\r
     }\r
@@ -127,126 +90,30 @@ public class CSpaceDBLoginModule extends DatabaseServerLoginModule {
      */\r
     protected Group[] getRoleSets() throws LoginException {\r
         String username = getUsername();\r
-        if (log.isDebugEnabled()) {\r
-            log.debug("getRoleSets using rolesQuery: " + rolesQuery + ", username: " + username);\r
-        }\r
-\r
-        Connection conn = null;\r
-        HashMap setsMap = new HashMap();\r
-        PreparedStatement ps = null;\r
-        ResultSet rs = null;\r
-\r
-        try {\r
-            conn = getConnection();\r
-            // Get the user role names\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.isDebugEnabled()) {\r
-                    log.debug("No roles found");\r
-                }\r
-//                if(aslm.getUnauthenticatedIdentity() == null){\r
-//                    throw new FailedLoginException("No matching username found in Roles");\r
-//                }\r
-                /* We are running with an unauthenticatedIdentity so create an\r
-                empty Roles set and return.\r
-                 */\r
-\r
-                Group[] roleSets = {new SimpleGroup("Roles")};\r
-                return roleSets;\r
-            }\r
-\r
-            do {\r
-                String name = rs.getString(1);\r
-                String groupName = rs.getString(2);\r
-                if (groupName == null || groupName.length() == 0) {\r
-                    groupName = "Roles";\r
-                }\r
-\r
-                Group group = (Group) setsMap.get(groupName);\r
-                if (group == null) {\r
-                    group = new SimpleGroup(groupName);\r
-                    setsMap.put(groupName, group);\r
-                }\r
-\r
-                try {\r
-//                    Principal p = aslm.createIdentity(name);\r
-                    Principal p = createIdentity(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.error("Failed to create principal: " + name + " " + e.toString());\r
-                }\r
-\r
-            } while (rs.next());\r
-        } catch (SQLException ex) {\r
-            LoginException le = new LoginException("Query failed");\r
-            le.initCause(ex);\r
-            throw le;\r
-        } finally {\r
-            if (rs != null) {\r
-                try {\r
-                    rs.close();\r
-                } catch (SQLException e) {\r
-                }\r
-            }\r
-            if (ps != null) {\r
-                try {\r
-                    ps.close();\r
-                } catch (SQLException e) {\r
-                }\r
-            }\r
-            if (conn != null) {\r
-                try {\r
-                    conn.close();\r
-                } catch (Exception ex) {\r
-                }\r
-            }\r
+        Collection<Group> roles = realm.getRoles(username,\r
+                "org.collectionspace.authentication.CSpacePrincipal",\r
+                "org.jboss.security.SimpleGroup");\r
 \r
-        }\r
+        Collection<Group> tenants = realm.getTenants(username,\r
+                "org.collectionspace.authentication.CSpacePrincipal",\r
+                "org.jboss.security.SimpleGroup");\r
 \r
-        Group[] roleSets = new Group[setsMap.size()];\r
-        setsMap.values().toArray(roleSets);\r
+        List<Group> all = new ArrayList<Group>();\r
+        all.addAll(roles);\r
+        all.addAll(tenants);\r
+        Group[] roleSets = new Group[all.size()];\r
+        all.toArray(roleSets);\r
         return roleSets;\r
     }\r
 \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
+    /** A hook to allow subclasses to convert a password from the database\r
+    into a plain text string or whatever form is used for matching against\r
+    the user input. It is called from within the getUsersPassword() method.\r
+    @param rawPassword - the password as obtained from the database\r
+    @return the argument rawPassword\r
+     */\r
+    protected String convertRawPassword(String rawPassword) {\r
+        return rawPassword;\r
     }\r
 }\r
diff --git a/services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceTenant.java b/services/authentication/service/src/main/java/org/collectionspace/authentication/CSpaceTenant.java
new file mode 100644 (file)
index 0000000..5b4565e
--- /dev/null
@@ -0,0 +1,169 @@
+/**
+ *  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;
+import java.security.acl.Group;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * A CSpace Principal representing a tenant
+ * A class derived (in principle) from JBoss SimpleGroup and SimplePrincipal
+ * @author 
+ */
+public class CSpaceTenant implements Group, Cloneable {
+
+    /** The serialVersionUID */
+    private static final long serialVersionUID = 1L;
+    private String name;
+    private String id;
+    private HashMap members = new HashMap(3);
+
+    public CSpaceTenant(String name, String id) {
+        if(name == null || id == null) {
+            String msg = "CSpaceTenant: invalid argument(s), can't be null" +
+                    "name=" + name + " id=" + id;
+            throw new IllegalArgumentException(msg);
+        }
+        this.name = name;
+        this.id = id;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    /** 
+     * Adds the specified member to the tenant.
+     * @param user the principal to add to this tenant.
+     * @return true if the member was successfully added,
+     * false if the principal was already a member.
+     */
+    @Override
+    public boolean addMember(Principal user) {
+        boolean isMember = members.containsKey(user);
+        if (isMember == false) {
+            members.put(user, user);
+        }
+        return isMember == false;
+    }
+
+    /** 
+     * isMember returns true if the passed principal is a member of the tenant.
+     * This method does a recursive search, so if a principal belongs to a
+     * tenant which is a member of this tenant, true is returned.
+     * @param member the principal whose membership is to be checked.
+     * @return true if the principal is a member of this tenant, false otherwise.
+     */
+    @Override
+    public boolean isMember(Principal member) {
+        // First see if there is a key with the member name
+        boolean isMember = members.containsKey(member);
+        if (isMember == false) {   // Check any tenants for membership
+            Collection values = members.values();
+            Iterator iter = values.iterator();
+            while (isMember == false && iter.hasNext()) {
+                Object next = iter.next();
+                if (next instanceof Group) {
+                    Group tenant = (Group) next;
+                    isMember = tenant.isMember(member);
+                }
+            }
+        }
+        return isMember;
+    }
+
+    /** 
+     * members returns an enumeration of the members in the tenant.
+     * The returned objects can be instances of either Principal
+     * or Group (which is a subinterface of Principal).
+     * @return an enumeration of the tenant members.
+     */
+    @Override
+    public Enumeration members() {
+        return Collections.enumeration(members.values());
+    }
+
+    /** 
+     * removeMember removes the specified member from the tenant.
+     * @param user the principal to remove from this tenant.
+     * @return true if the principal was removed, or
+     * false if the principal was not a member.
+     */
+    @Override
+    public boolean removeMember(Principal user) {
+        Object prev = members.remove(user);
+        return prev != null;
+    }
+
+    /**
+     * Compare this tenant against another tenant
+     * @return true if name equals another.getName();
+     */
+    @Override
+    public boolean equals(Object another) {
+        if (!(another instanceof CSpaceTenant)) {
+            return false;
+        }
+        String anotherName = ((CSpaceTenant) another).getName();
+        String anotherId = ((CSpaceTenant) another).getId();
+        return name.equals(anotherName) && id.equals(anotherId);
+    }
+
+    @Override
+    public int hashCode() {
+        return (name + id).hashCode();
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer tmp = new StringBuffer(getName());
+        tmp.append("(members:");
+        Iterator iter = members.keySet().iterator();
+        while (iter.hasNext()) {
+            tmp.append(iter.next());
+            tmp.append(',');
+        }
+        tmp.setCharAt(tmp.length() - 1, ')');
+        return tmp.toString();
+    }
+
+    @Override
+    public synchronized Object clone() throws CloneNotSupportedException {
+        CSpaceTenant clone = (CSpaceTenant) super.clone();
+        if (clone != null) {
+            clone.members = (HashMap) this.members.clone();
+        }
+        return clone;
+    }
+}
diff --git a/services/authentication/service/src/main/java/org/collectionspace/authentication/DatabaseRealm.java b/services/authentication/service/src/main/java/org/collectionspace/authentication/DatabaseRealm.java
new file mode 100644 (file)
index 0000000..39147af
--- /dev/null
@@ -0,0 +1,469 @@
+/**
+ *  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.
+ *//**
+ *  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.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.collectionspace.authentication;
+
+import java.lang.reflect.Constructor;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+import javax.sql.DataSource;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * DatabaseRealm provides access to user, password, role, tenant database
+ * @author 
+ */
+public class DatabaseRealm {
+
+    private static Log log = LogFactory.getLog(DatabaseRealm.class);
+    private String datasourceName;
+    private String principalsQuery;
+    private String rolesQuery;
+    private String tenantsQuery;
+    private boolean suspendResume;
+
+    /**
+     * create DatabaseRelam 
+     * @param datasourceName datasource name
+     */
+    public DatabaseRealm(Map options) {
+        datasourceName = (String) options.get("dsJndiName");
+        if (datasourceName == null) {
+            datasourceName = "java:/DefaultDS";
+        }
+        Object tmp = options.get("principalsQuery");
+        if (tmp != null) {
+            principalsQuery = tmp.toString();
+        }
+        tmp = options.get("rolesQuery");
+        if (tmp != null) {
+            rolesQuery = tmp.toString();
+        }
+        tmp = options.get("tenantsQuery");
+        if (tmp != null) {
+            tenantsQuery = tmp.toString();
+        }
+        tmp = options.get("suspendResume");
+        if (tmp != null) {
+            suspendResume = Boolean.valueOf(tmp.toString()).booleanValue();
+        }
+        if (log.isTraceEnabled()) {
+            log.trace("DatabaseServerLoginModule, dsJndiName=" + datasourceName);
+            log.trace("principalsQuery=" + principalsQuery);
+            log.trace("rolesQuery=" + rolesQuery);
+            log.trace("suspendResume=" + suspendResume);
+        }
+
+    }
+
+    String getUsersPassword(String username) throws LoginException {
+
+        String password = null;
+        Connection conn = null;
+        PreparedStatement ps = null;
+        ResultSet rs = null;
+        try {
+            conn = getConnection();
+            // Get the password
+            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.isDebugEnabled()) {
+                    log.debug(principalsQuery + " returned no matches from db");
+                }
+                throw new FailedLoginException("No matching username found");
+            }
+
+            password = rs.getString(1);
+        } catch (SQLException ex) {
+            LoginException le = new LoginException("Query failed");
+            le.initCause(ex);
+            throw le;
+        } catch (Exception ex) {
+            LoginException le = new LoginException("Unknown Exception");
+            le.initCause(ex);
+            throw le;
+        } finally {
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException e) {
+                }
+            }
+            if (ps != null) {
+                try {
+                    ps.close();
+                } catch (SQLException e) {
+                }
+            }
+            if (conn != null) {
+                try {
+                    conn.close();
+                } catch (SQLException ex) {
+                }
+            }
+        }
+        return password;
+    }
+
+    /**
+     * Execute the rolesQuery against the datasourceName to obtain the roles for
+     * the authenticated user.
+     * @return collection containing the roles
+     */
+    Collection<Group> getRoles(String username, String principalClassName, String groupClassName) throws LoginException {
+
+        if (log.isDebugEnabled()) {
+            log.debug("getRoleSets using rolesQuery: " + rolesQuery + ", username: " + username);
+        }
+
+        Connection conn = null;
+        HashMap<String, Group> groupsMap = new HashMap<String, Group>();
+        PreparedStatement ps = null;
+        ResultSet rs = null;
+
+        try {
+            conn = getConnection();
+            // Get the user role names
+            if (log.isDebugEnabled()) {
+                log.debug("Executing query: " + rolesQuery + ", with username: " + username);
+            }
+
+            ps = conn.prepareStatement(rolesQuery);
+            try {
+                ps.setString(1, username);
+            } catch (ArrayIndexOutOfBoundsException ignore) {
+                // The query may not have any parameters so just try it
+            }
+            rs = ps.executeQuery();
+            if (rs.next() == false) {
+                if (log.isDebugEnabled()) {
+                    log.debug("No roles found");
+                }
+//                if(aslm.getUnauthenticatedIdentity() == null){
+//                    throw new FailedLoginException("No matching username found in Roles");
+//                }
+                /* We are running with an unauthenticatedIdentity so create an
+                empty Roles set and return.
+                 */
+
+                Group g = createGroup(groupClassName, "Roles");
+                groupsMap.put(g.getName(), g);
+                return groupsMap.values();
+            }
+
+            do {
+                String roleName = rs.getString(1);
+                String groupName = rs.getString(2);
+                if (groupName == null || groupName.length() == 0) {
+                    groupName = "Roles";
+                }
+
+                Group group = (Group) groupsMap.get(groupName);
+                if (group == null) {
+                    group = createGroup(groupClassName, groupName);
+                    groupsMap.put(groupName, group);
+                }
+
+                try {
+                    Principal p = createPrincipal(principalClassName, roleName);
+                    if (log.isDebugEnabled()) {
+                        log.debug("Assign user to role " + roleName);
+                    }
+
+                    group.addMember(p);
+                } catch (Exception e) {
+                    log.error("Failed to create principal: " + roleName + " " + e.toString());
+                }
+
+            } while (rs.next());
+        } catch (SQLException ex) {
+            LoginException le = new LoginException("Query failed");
+            le.initCause(ex);
+            throw le;
+        } catch (Exception e) {
+            LoginException le = new LoginException("unknown exception");
+            le.initCause(e);
+            throw le;
+        } finally {
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException e) {
+                }
+            }
+            if (ps != null) {
+                try {
+                    ps.close();
+                } catch (SQLException e) {
+                }
+            }
+            if (conn != null) {
+                try {
+                    conn.close();
+                } catch (Exception ex) {
+                }
+            }
+
+        }
+
+        return groupsMap.values();
+
+    }
+
+    /**
+     * Execute the tenantsQuery against the datasourceName to obtain the tenants for
+     * the authenticated user.
+     * @return collection containing the roles
+     */
+    Collection<Group> getTenants(String username, String principalClassName, String groupClassName) throws LoginException {
+
+        if (log.isDebugEnabled()) {
+            log.debug("getTenants using tenantsQuery: " + tenantsQuery + ", username: " + username);
+        }
+
+        Connection conn = null;
+        HashMap<String, Group> groupsMap = new HashMap<String, Group>();
+        PreparedStatement ps = null;
+        ResultSet rs = null;
+
+        try {
+            conn = getConnection();
+            // Get the user role names
+            if (log.isDebugEnabled()) {
+                log.debug("Executing query: " + tenantsQuery + ", with username: " + username);
+            }
+
+            ps = conn.prepareStatement(tenantsQuery);
+            try {
+                ps.setString(1, username);
+            } catch (ArrayIndexOutOfBoundsException ignore) {
+                // The query may not have any parameters so just try it
+            }
+            rs = ps.executeQuery();
+            if (rs.next() == false) {
+                if (log.isDebugEnabled()) {
+                    log.debug("No tenants found");
+                }
+                // We are running with an unauthenticatedIdentity so create an
+                // empty Tenants set and return.
+                // FIXME  should this be allowed?
+                Group g = createGroup(groupClassName, "Tenants");
+                groupsMap.put(g.getName(), g);
+                return groupsMap.values();
+            }
+
+            do {
+                String tenantId = rs.getString(1);
+                String tenantName = rs.getString(2);
+                String groupName = rs.getString(3);
+                if (groupName == null || groupName.length() == 0) {
+                    groupName = "Tenants";
+                }
+
+                Group group = (Group) groupsMap.get(groupName);
+                if (group == null) {
+                    group = createGroup(groupClassName, groupName);
+                    groupsMap.put(groupName, group);
+                }
+
+                try {
+                    Principal p = createTenant(tenantName, tenantId);
+                    if (log.isDebugEnabled()) {
+                        log.debug("Assign user to tenant " + tenantName);
+                    }
+
+                    group.addMember(p);
+                } catch (Exception e) {
+                    log.error("Failed to create tenant: " + tenantName + " " + e.toString());
+                }
+            } while (rs.next());
+        } catch (SQLException ex) {
+            LoginException le = new LoginException("Query failed");
+            le.initCause(ex);
+            throw le;
+        } catch (Exception e) {
+            LoginException le = new LoginException("unknown exception");
+            le.initCause(e);
+            throw le;
+        } finally {
+            if (rs != null) {
+                try {
+                    rs.close();
+                } catch (SQLException e) {
+                }
+            }
+            if (ps != null) {
+                try {
+                    ps.close();
+                } catch (SQLException e) {
+                }
+            }
+            if (conn != null) {
+                try {
+                    conn.close();
+                } catch (Exception ex) {
+                }
+            }
+
+        }
+
+        return groupsMap.values();
+    }
+
+    private CSpaceTenant createTenant(String name, String id) throws Exception {
+        return new CSpaceTenant(name, id);
+    }
+
+    private Group createGroup(String groupClassName, String name) throws Exception {
+        return (Group) createPrincipal(groupClassName, name);
+    }
+
+    private Principal createPrincipal(String principalClassName, String name) throws Exception {
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+        Class clazz = loader.loadClass(principalClassName);
+        Class[] ctorSig = {String.class};
+        Constructor ctor = clazz.getConstructor(ctorSig);
+        Object[] ctorArgs = {name};
+        Principal p = (Principal) ctor.newInstance(ctorArgs);
+        return p;
+    }
+
+    private Connection getConnection() throws LoginException, SQLException {
+        InitialContext ctx = null;
+        Connection conn = null;
+        try {
+            ctx = new InitialContext();
+            DataSource ds = (DataSource) ctx.lookup(getDataSourceName());
+            if (ds == null) {
+                throw new IllegalArgumentException("datasource not found: " + getDataSourceName());
+            }
+            conn = ds.getConnection();
+            return conn;
+        } catch (NamingException ex) {
+            LoginException le = new LoginException("Error looking up DataSource from: " + getDataSourceName());
+            le.initCause(ex);
+            throw le;
+        } finally {
+            if (ctx != null) {
+                try {
+                    ctx.close();
+                } catch (Exception e) {
+                }
+            }
+        }
+
+    }
+
+    /**
+     * @return the datasourceName
+     */
+    public String getDataSourceName() {
+        return datasourceName;
+    }
+
+    /**
+     * @return the principalQuery
+     */
+    public String getPrincipalQuery() {
+        return principalsQuery;
+    }
+
+    /**
+     * @param principalQuery the principalQuery to set
+     */
+    public void setPrincipalQuery(String principalQuery) {
+        this.principalsQuery = principalQuery;
+    }
+
+    /**
+     * @return the roleQuery
+     */
+    public String getRoleQuery() {
+        return rolesQuery;
+    }
+
+    /**
+     * @param roleQuery the roleQuery to set
+     */
+    public void setRoleQuery(String roleQuery) {
+        this.rolesQuery = roleQuery;
+    }
+
+    /**
+     * @return the tenantQuery
+     */
+    public String getTenantQuery() {
+        return tenantsQuery;
+    }
+
+    /**
+     * @param tenantQuery the tenantQuery to set
+     */
+    public void setTenantQuery(String tenantQuery) {
+        this.tenantsQuery = tenantQuery;
+    }
+}
index 9d4221a702ceb1539a7c194a55b82930008f5fe7..53fd571c3af55c7e3580c4ea699d263874a4fb9e 100644 (file)
@@ -4,10 +4,10 @@
     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.
-    
+
     Document   : jboss-login-config.xml
     Created on : June 19, 2009, 9:58 AM
-    Author     : 
+    Author     :
     Description:
         jboss config for JAAS DatabaseServerLoginModule
 -->
@@ -19,16 +19,19 @@ copy before the "other" application-policy
 <application-policy name="cspace">
     <authentication>
         <login-module code="org.collectionspace.authentication.CSpaceDBLoginModule"
-                             flag="required">
+                      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 = "principalClass">org.collectionspace.authentication.CSpacePrincipal</module-option>
             <module-option name="principalsQuery">
-                    select passwd, tenantid from users where username=?
+                select passwd from users where username=?
             </module-option>
             <module-option name="rolesQuery">
-                    select rolename, 'Roles' from users_roles where username=? and tenantid=?
+                select rolename, 'Roles' from users_roles where username=?
+            </module-option>
+            <module-option name="tenantsQuery">
+                select id, name, 'Tenants' from accounts_common a, tenants as t where a.userid=? and a.csid = t.TENANT_ACCOUNTSCOMMON_CSID
             </module-option>
         </login-module>
     </authentication>
index e36b150ba1b621075e94251f0ca591ef13bf45d8..02d4002d49b5e97c30b2ff3c5625061020ebee01 100644 (file)
@@ -3,7 +3,7 @@
     <description>\r
         collectionspace services main\r
     </description>\r
-  <!-- set global properties for this build -->\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
@@ -17,8 +17,8 @@
     </condition>\r
 \r
     <target name="package" depends="package-unix,package-windows"\r
-  description="Package CollectionSpace Services" />\r
-  \r
+            description="Package CollectionSpace Services" />\r
+\r
     <target name="package-unix" if="osfamily-unix">\r
         <exec executable="mvn" failonerror="true">\r
             <arg value="package" />\r
@@ -29,7 +29,7 @@
             <arg value="${mvn.opts}" />\r
         </exec>\r
     </target>\r
-    \r
+\r
     <target name="package-windows" if="osfamily-windows">\r
         <exec executable="cmd" failonerror="true">\r
             <arg value="/c" />\r
@@ -45,7 +45,7 @@
 \r
 \r
     <target name="install" depends="package,install-unix,install-windows"\r
-  description="Install" />\r
+            description="Install" />\r
     <target name="install-unix" if="osfamily-unix">\r
         <exec executable="mvn" failonerror="true">\r
             <arg value="install" />\r
@@ -70,7 +70,7 @@
     </target>\r
 \r
     <target name="clean" depends="clean-unix,clean-windows"\r
-  description="Delete target directories" >\r
+            description="Delete target directories" >\r
         <delete dir="${build}"/>\r
     </target>\r
     <target name="clean-unix" if="osfamily-unix">\r
     </target>\r
 \r
     <target name="create_db"\r
-    description="create service-specific tables(s), indices, etc.">\r
+            description="create service-specific tables(s), indices, etc.">\r
         <ant antfile="authentication/build.xml" target="create_db" inheritAll="false"/>\r
         <ant antfile="account/build.xml" target="create_db" inheritAll="false"/>\r
         <ant antfile="id/build.xml" target="create_db" inheritAll="false"/>\r
 \r
     <!-- this target is called in order based on the dependencies between the services -->\r
     <target name="deploy" depends="install"\r
-    description="deploy services in ${jboss.server.cspace}">\r
-        <ant antfile="common/build.xml" target="deploy" inheritAll="false"/>\r
+            description="deploy services in ${jboss.server.cspace}">\r
         <ant antfile="authentication/build.xml" target="deploy" inheritAll="false"/>\r
+        <ant antfile="common/build.xml" target="deploy" inheritAll="false"/>\r
         <ant antfile="relation/build.xml" target="deploy" inheritAll="false"/>\r
         <ant antfile="id/build.xml" target="deploy" inheritAll="false"/>\r
         <ant antfile="collectionobject/build.xml" target="deploy" inheritAll="false"/>\r
 \r
     <!-- this target is called in revese order of deploy targets -->\r
     <target name="undeploy"\r
-    description="undeploy services from ${jboss.server.cspace}">\r
+            description="undeploy services from ${jboss.server.cspace}">\r
         <ant antfile="JaxRsServiceProvider/build.xml" target="undeploy" inheritAll="false"/>\r
         <ant antfile="vocabulary/build.xml" target="undeploy" inheritAll="false"/>\r
         <ant antfile="contact/build.xml" target="undeploy" inheritAll="false"/>        \r
         <ant antfile="collectionobject/build.xml" target="undeploy" inheritAll="false"/>\r
         <ant antfile="id/build.xml" target="undeploy" inheritAll="false"/>\r
         <ant antfile="relation/build.xml" target="undeploy" inheritAll="false"/>\r
-        <ant antfile="authentication/build.xml" target="undeploy" inheritAll="false"/>\r
         <ant antfile="common/build.xml" target="undeploy" inheritAll="false"/>\r
+        <ant antfile="authentication/build.xml" target="undeploy" inheritAll="false"/>\r
     </target>\r
 \r
     <target name="hotdeploy" depends="install"\r
-    description="deploy services in running ${jboss.server.cspace}">\r
+            description="deploy services in running ${jboss.server.cspace}">\r
         <ant antfile="JaxRsServiceProvider/build.xml" target="hotdeploy" inheritAll="false"/>\r
     </target>\r
 \r
     <!-- this target is called in order based on the dependencies between the services -->\r
     <target name="dist" depends="package"\r
-    description="create distribution for services">\r
+            description="create distribution for services">\r
         <ant antfile="common/build.xml" target="dist" inheritAll="false"/>\r
         <ant antfile="authentication/build.xml" target="dist" inheritAll="false"/>\r
+        <ant antfile="common/build.xml" target="dist" inheritAll="false"/>\r
         <ant antfile="relation/build.xml" target="dist" inheritAll="false"/>\r
         <ant antfile="id/build.xml" target="dist" inheritAll="false"/>\r
         <ant antfile="collectionobject/build.xml" target="dist" inheritAll="false"/>\r
         <ant antfile="acquisition/build.xml" target="dist" inheritAll="false"/>\r
         <ant antfile="JaxRsServiceProvider/build.xml" target="dist" inheritAll="false"/>\r
     </target>\r
-    \r
+\r
     <!-- this target is called in order based on the dependencies between the services -->\r
     <target name="dist_installer"\r
-       description="create distribution for CollectionSpace installer">\r
-    \r
+            description="create distribution for CollectionSpace installer">\r
+\r
         <!-- copy install scripts, etc. -->\r
         <copy todir="${services.trunk}/${dist.installer.services}">\r
             <fileset dir="./installer"/>\r
         <ant antfile="id/build.xml" target="dist_installer" inheritAll="false"/>\r
         <ant antfile="collectionobject/build.xml" target="dist_installer" inheritAll="false"/>\r
         <ant antfile="vocabulary/build.xml" target="dist_installer" inheritAll="false"/>\r
-<!--\r
+        <!--\r
         <ant antfile="common/build.xml" target="dist_installer" inheritAll="false"/>\r
         <ant antfile="authentication/build.xml" target="dist_installer" inheritAll="false"/>\r
         <ant antfile="relation/build.xml" target="dist_installer" inheritAll="false"/>\r
 -->        \r
     </target>\r
 \r
-    \r
+\r
 </project>\r
index d5fc0bbf257679f8616b39b2a2661fa6e3ecdc50..235d6b52555a3e74e8a8f46671a784f23f74fa01 100644 (file)
@@ -66,7 +66,7 @@ public abstract class AbstractServiceTest implements ServiceTest {
     protected final String NON_EXISTENT_ID = createNonExistentIdentifier();
     // The HTTP status code expected to be returned in the response,
     // from a request made to a service (where relevant).
-    int EXPECTED_STATUS_CODE = 0;
+    protected int EXPECTED_STATUS_CODE = 0;
     // The generic type of service request being tested
     // (e.g. CREATE, UPDATE, DELETE).
     //
@@ -654,7 +654,7 @@ public abstract class AbstractServiceTest implements ServiceTest {
         return sb.toString();
     }
 
-    private void banner(String label) {
+    protected void banner(String label) {
         if(logger.isDebugEnabled()){
             logger.debug("===================================================");
             logger.debug(" Test = " + label);
index 87363d4bba8b84cdd5b9b9d3ee95f576522accfb..92de8f03983ef29a565136cf6172d4fee83342e3 100644 (file)
@@ -20,7 +20,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 package org.collectionspace.services.client.test;
 
 import java.util.Arrays;
@@ -40,194 +39,212 @@ import org.slf4j.LoggerFactory;
  * $LastChangedDate$
  */
 public enum ServiceRequestType {
-   
+
     // Define each of the service request types and their valid HTTP status codes.
-    
     CREATE {
+
         @Override
-        public int[] validStatusCodes() { 
-              final int[] STATUS_CODES = {
-                    Response.Status.CREATED.getStatusCode(),
-                    Response.Status.BAD_REQUEST.getStatusCode(),
-                    Response.Status.FORBIDDEN.getStatusCode(),
-                    Response.Status.CONFLICT.getStatusCode(),
-                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
-              };
-              Arrays.sort(STATUS_CODES);
-              return STATUS_CODES;
+        public int[] validStatusCodes() {
+            final int[] STATUS_CODES = {
+                Response.Status.CREATED.getStatusCode(),
+                Response.Status.BAD_REQUEST.getStatusCode(),
+                Response.Status.UNAUTHORIZED.getStatusCode(),
+                Response.Status.FORBIDDEN.getStatusCode(),
+                Response.Status.CONFLICT.getStatusCode(),
+                Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
+            };
+            Arrays.sort(STATUS_CODES);
+            return STATUS_CODES;
         }
+
         @Override
         public boolean isValidStatusCode(int statusCode) {
-              if (Arrays.binarySearch(CREATE.validStatusCodes(), statusCode) >= 0) {
-                    return true;
-              } else {
-                    return false;
-              }
+            if (Arrays.binarySearch(CREATE.validStatusCodes(), statusCode) >= 0) {
+                return true;
+            } else {
+                return false;
+            }
         }
+
         @Override
         public String validStatusCodesAsString() {
-              return Arrays.toString(CREATE.validStatusCodes());
+            return Arrays.toString(CREATE.validStatusCodes());
         }
+
         @Override
         public String httpMethodName() {
             return javax.ws.rs.HttpMethod.POST;
         }
-    },  // Note that commas are required at the end of each enum block, except the last.
-    
-    
+    }, // Note that commas are required at the end of each enum block, except the last.
+
     READ {
+
         @Override
-        public int[] validStatusCodes() { 
-              final int[] STATUS_CODES = {
-                    Response.Status.OK.getStatusCode(),
-                    Response.Status.FORBIDDEN.getStatusCode(),
-                    Response.Status.NOT_FOUND.getStatusCode(),
-                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
-              };
-              Arrays.sort(STATUS_CODES);
-              return STATUS_CODES;
+        public int[] validStatusCodes() {
+            final int[] STATUS_CODES = {
+                Response.Status.OK.getStatusCode(),
+                Response.Status.UNAUTHORIZED.getStatusCode(),
+                Response.Status.FORBIDDEN.getStatusCode(),
+                Response.Status.NOT_FOUND.getStatusCode(),
+                Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
+            };
+            Arrays.sort(STATUS_CODES);
+            return STATUS_CODES;
         }
+
         @Override
         public boolean isValidStatusCode(int statusCode) {
-              if (Arrays.binarySearch(READ.validStatusCodes(), statusCode) >= 0) {
-                    return true;
-              } else {
-                    return false;
-              }
+            if (Arrays.binarySearch(READ.validStatusCodes(), statusCode) >= 0) {
+                return true;
+            } else {
+                return false;
+            }
         }
+
         @Override
         public String validStatusCodesAsString() {
-              return Arrays.toString(READ.validStatusCodes());
+            return Arrays.toString(READ.validStatusCodes());
         }
+
         @Override
         public String httpMethodName() {
             return javax.ws.rs.HttpMethod.GET;
         }
     },
-    
-    
     READ_LIST {
+
         @Override
-        public int[] validStatusCodes() { 
-              final int[] STATUS_CODES = {
-                    Response.Status.OK.getStatusCode(),
-                    Response.Status.BAD_REQUEST.getStatusCode(),
-                    Response.Status.FORBIDDEN.getStatusCode(),
-                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
-              };
-              Arrays.sort(STATUS_CODES);
-              return STATUS_CODES;
+        public int[] validStatusCodes() {
+            final int[] STATUS_CODES = {
+                Response.Status.OK.getStatusCode(),
+                Response.Status.BAD_REQUEST.getStatusCode(),
+                Response.Status.UNAUTHORIZED.getStatusCode(),
+                Response.Status.FORBIDDEN.getStatusCode(),
+                Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
+            };
+            Arrays.sort(STATUS_CODES);
+            return STATUS_CODES;
         }
+
         @Override
         public boolean isValidStatusCode(int statusCode) {
-              if (Arrays.binarySearch(READ_LIST.validStatusCodes(), statusCode) >= 0) {
-                    return true;
-              } else {
-                    return false;
-              }
+            if (Arrays.binarySearch(READ_LIST.validStatusCodes(), statusCode) >= 0) {
+                return true;
+            } else {
+                return false;
+            }
         }
+
         @Override
         public String validStatusCodesAsString() {
-              return Arrays.toString(READ_LIST.validStatusCodes());
+            return Arrays.toString(READ_LIST.validStatusCodes());
         }
+
         @Override
         public String httpMethodName() {
             return javax.ws.rs.HttpMethod.GET;
         }
     },
-    
-    
     UPDATE {
+
         @Override
-        public int[] validStatusCodes() { 
-              final int[] STATUS_CODES = {
-                    Response.Status.OK.getStatusCode(),
-                    Response.Status.BAD_REQUEST.getStatusCode(),
-                    Response.Status.FORBIDDEN.getStatusCode(),
-                    Response.Status.NOT_FOUND.getStatusCode(),
-                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
-              };
-              Arrays.sort(STATUS_CODES);
-              return STATUS_CODES;
+        public int[] validStatusCodes() {
+            final int[] STATUS_CODES = {
+                Response.Status.OK.getStatusCode(),
+                Response.Status.BAD_REQUEST.getStatusCode(),
+                Response.Status.UNAUTHORIZED.getStatusCode(),
+                Response.Status.FORBIDDEN.getStatusCode(),
+                Response.Status.NOT_FOUND.getStatusCode(),
+                Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
+            };
+            Arrays.sort(STATUS_CODES);
+            return STATUS_CODES;
         }
+
         @Override
         public boolean isValidStatusCode(int statusCode) {
-              if (Arrays.binarySearch(UPDATE.validStatusCodes(), statusCode) >= 0) {
-                    return true;
-              } else {
-                    return false;
-              }
+            if (Arrays.binarySearch(UPDATE.validStatusCodes(), statusCode) >= 0) {
+                return true;
+            } else {
+                return false;
+            }
         }
+
         @Override
         public String validStatusCodesAsString() {
-              return Arrays.toString(UPDATE.validStatusCodes());
+            return Arrays.toString(UPDATE.validStatusCodes());
         }
+
         @Override
         public String httpMethodName() {
             return javax.ws.rs.HttpMethod.PUT;
         }
     },
-    
-    
     DELETE {
+
         @Override
-        public int[] validStatusCodes() { 
-              final int[] STATUS_CODES = {
-                    Response.Status.OK.getStatusCode(),
-                    Response.Status.FORBIDDEN.getStatusCode(),
-                    Response.Status.NOT_FOUND.getStatusCode(),
-                    Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
-              };
-              Arrays.sort(STATUS_CODES);
-              return STATUS_CODES;
+        public int[] validStatusCodes() {
+            final int[] STATUS_CODES = {
+                Response.Status.OK.getStatusCode(),
+                Response.Status.UNAUTHORIZED.getStatusCode(),
+                Response.Status.FORBIDDEN.getStatusCode(),
+                Response.Status.NOT_FOUND.getStatusCode(),
+                Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()
+            };
+            Arrays.sort(STATUS_CODES);
+            return STATUS_CODES;
         }
+
         @Override
         public boolean isValidStatusCode(int statusCode) {
-              if (Arrays.binarySearch(DELETE.validStatusCodes(), statusCode) >= 0) {
-                    return true;
-              } else {
-                    return false;
-              }
+            if (Arrays.binarySearch(DELETE.validStatusCodes(), statusCode) >= 0) {
+                return true;
+            } else {
+                return false;
+            }
         }
+
         @Override
         public String validStatusCodesAsString() {
-              return Arrays.toString(DELETE.validStatusCodes());
+            return Arrays.toString(DELETE.validStatusCodes());
         }
+
         @Override
         public String httpMethodName() {
             return javax.ws.rs.HttpMethod.DELETE;
         }
     },
-    
-    
     // Used by guard code.
     NON_EXISTENT {
+
         @Override
-        public int[] validStatusCodes() { 
-              final int[] STATUS_CODES = { 0 };
-              Arrays.sort(STATUS_CODES);
-              return STATUS_CODES;
+        public int[] validStatusCodes() {
+            final int[] STATUS_CODES = {0};
+            Arrays.sort(STATUS_CODES);
+            return STATUS_CODES;
         }
+
         @Override
         public boolean isValidStatusCode(int statusCode) {
-              return false;
+            return false;
         }
+
         @Override
         public String validStatusCodesAsString() {
-              return Arrays.toString(NON_EXISTENT.validStatusCodes());
+            return Arrays.toString(NON_EXISTENT.validStatusCodes());
         }
+
         @Override
         public String httpMethodName() {
-              return "";
+            return "";
         }
     };
-    
+
     // Template methods to be implemented by each ServiceRequestType.
-    
     public abstract int[] validStatusCodes();
-    
+
     public abstract boolean isValidStatusCode(int statusCode);
-    
+
     public abstract String validStatusCodesAsString();
 
     public abstract String httpMethodName();
index e9b0f3eeedb53f9d212e93c0643bd9294c6206d8..44214b6eeba5ac5f47dbb3d83540f2a813bcd712 100644 (file)
     <packaging>jar</packaging>\r
     <version>1.0</version>\r
     <name>services.common</name>\r
-    \r
+\r
     <dependencies>\r
-        <dependency>\r
-            <groupId>com.sun.xml.bind</groupId>\r
-            <artifactId>jaxb-impl</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.jvnet.jaxb2-commons</groupId>\r
-            <artifactId>property-listener-injector</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.jvnet.jaxb2_commons</groupId>\r
-            <artifactId>runtime</artifactId>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.jboss.resteasy</groupId>\r
-            <artifactId>resteasy-jaxrs</artifactId>\r
-            <exclusions>\r
-                <exclusion>\r
-                    <groupId>tjws</groupId>\r
-                    <artifactId>webserver</artifactId>\r
-                </exclusion>\r
-            </exclusions>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.jboss.resteasy</groupId>\r
-            <artifactId>resteasy-jaxb-provider</artifactId>\r
-            <version>1.1.GA</version>\r
-        </dependency>\r
-        <dependency>\r
-            <groupId>org.jboss.resteasy</groupId>\r
-            <artifactId>resteasy-multipart-provider</artifactId>\r
-            <version>1.1.GA</version>\r
-        </dependency>\r
 \r
         <!-- utilities -->\r
         <dependency>\r
@@ -61,7 +29,7 @@
             <groupId>org.slf4j</groupId>\r
             <artifactId>slf4j-log4j12</artifactId>\r
         </dependency>\r
-      <!-- javax -->\r
+        <!-- javax -->\r
 \r
         <dependency>\r
             <groupId>javax.servlet</groupId>\r
@@ -69,7 +37,7 @@
             <version>2.5</version>\r
             <scope>provided</scope>\r
         </dependency>\r
-        \r
+\r
         <dependency>\r
             <groupId>javax.security</groupId>\r
             <artifactId>jaas</artifactId>\r
@@ -80,7 +48,7 @@
             <groupId>javax.security</groupId>\r
             <artifactId>jacc</artifactId>\r
             <version>1.0</version>\r
-             <scope>provided</scope>\r
+            <scope>provided</scope>\r
         </dependency>\r
         <!--\r
             <dependency>\r
             <scope>provided</scope>\r
         </dependency>\r
         -->\r
+        <dependency>\r
+            <groupId>mysql</groupId>\r
+            <artifactId>mysql-connector-java</artifactId>\r
+        </dependency>\r
         <dependency>\r
             <groupId>javax.persistence</groupId>\r
             <artifactId>persistence-api</artifactId>\r
         </dependency>\r
+\r
+        <dependency>\r
+            <groupId>com.sun.xml.bind</groupId>\r
+            <artifactId>jaxb-impl</artifactId>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.jvnet.jaxb2-commons</groupId>\r
+            <artifactId>property-listener-injector</artifactId>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.jvnet.jaxb2_commons</groupId>\r
+            <artifactId>runtime</artifactId>\r
+        </dependency>\r
+\r
+        <!-- jboss -->\r
+        <dependency>\r
+            <groupId>org.jboss.resteasy</groupId>\r
+            <artifactId>resteasy-jaxrs</artifactId>\r
+            <exclusions>\r
+                <exclusion>\r
+                    <groupId>tjws</groupId>\r
+                    <artifactId>webserver</artifactId>\r
+                </exclusion>\r
+            </exclusions>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.jboss.resteasy</groupId>\r
+            <artifactId>resteasy-jaxb-provider</artifactId>\r
+            <version>1.1.GA</version>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.jboss.resteasy</groupId>\r
+            <artifactId>resteasy-multipart-provider</artifactId>\r
+            <version>1.1.GA</version>\r
+        </dependency>\r
+\r
         <dependency>\r
             <groupId>org.hibernate</groupId>\r
             <artifactId>hibernate-entitymanager</artifactId>\r
             <version>1.1.1</version>\r
         </dependency>\r
 \r
-\r
+        <dependency>\r
+            <groupId>org.collectionspace.services</groupId>\r
+            <artifactId>org.collectionspace.services.authentication.jaxb</artifactId>\r
+            <version>1.0</version>\r
+            <scope>provided</scope>\r
+        </dependency>\r
+        <dependency>\r
+            <groupId>org.collectionspace.services</groupId>\r
+            <artifactId>org.collectionspace.services.authentication.service</artifactId>\r
+            <version>1.0</version>\r
+            <scope>provided</scope>\r
+        </dependency>\r
     </dependencies>\r
-    \r
+\r
     <build>\r
         <finalName>collectionspace-services-common</finalName>\r
         <plugins>\r
             <plugin>\r
                 <groupId>org.jvnet.jaxb2.maven2</groupId>\r
                 <artifactId>maven-jaxb2-plugin</artifactId>\r
+                <!-- version is very important here as we want to explicitly\r
+                use jaxb2 plugin only and not jaxb2 bundled with hyperjaxb3\r
+                that does not allow to invoke generate from base plugin -->\r
+                <version>0.7.0</version>\r
                 <executions>\r
                     <execution>\r
                         <goals>\r
                         <arg>-XtoString</arg>\r
                         <arg>-Xinject-listener-code</arg>\r
 \r
-                     <!-- <arg>-Xcollection-setter-injector</arg>\r
+                        <!-- <arg>-Xcollection-setter-injector</arg>\r
                                 <arg>-Xfluent-api</arg> -->\r
                     </args>\r
                     <plugins>\r
                         <plugin>\r
                             <groupId>\r
-                           org.jvnet.jaxb2_commons\r
+                                org.jvnet.jaxb2_commons\r
                             </groupId>\r
                             <artifactId>basic</artifactId>\r
                             <version>0.4.1</version>\r
                         </plugin>\r
                         <plugin>\r
                             <groupId>\r
-                           org.jvnet.jaxb2-commons\r
+                                org.jvnet.jaxb2-commons\r
                             </groupId>\r
                             <artifactId>\r
-                           property-listener-injector\r
+                                property-listener-injector\r
                             </artifactId>\r
                             <version>1.0</version>\r
                         </plugin>\r
index d67d684607d3919a3c1d070a8dbf8eb36acb9592..c0a4fc1c950a7765ecc83bd0aee289948cc36acb 100644 (file)
@@ -23,9 +23,8 @@
  */
 package org.collectionspace.services.common.context;
 
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -33,6 +32,7 @@ import java.util.Set;
 import javax.security.auth.Subject;
 import javax.security.jacc.PolicyContext;
 import javax.security.jacc.PolicyContextException;
+import org.collectionspace.authentication.CSpaceTenant;
 
 import org.collectionspace.services.common.ClientType;
 import org.collectionspace.services.common.ServiceMain;
@@ -66,29 +66,29 @@ public abstract class AbstractServiceContext<IT, OT>
                 ServiceMain.getInstance().getTenantBindingConfigReader();
         //FIXME retrieveTenantId is not working consistently in non-auth mode
         //TODO: get tenant binding from security context
-        String tenantId = null; //retrieveTenantId();
+        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 " +
-                    serviceName;
+            String msg = "No tenant binding found for tenantId=" + tenantId + 
+                    " while processing request for service= " + serviceName;
             logger.error(msg);
             throw new IllegalStateException(msg);
         }
         serviceBinding = tReader.getServiceBinding(tenantId, serviceName);
         if (serviceBinding == null) {
-            String msg = "No service binding found while processing request for " +
-                    serviceName + " for tenant id=" + getTenantId() +
-                    " name=" + getTenantName();
+            String msg = "No service binding found while processing request for "
+                    + serviceName + " for tenant id=" + getTenantId()
+                    " name=" + getTenantName();
             logger.error(msg);
             throw new IllegalStateException(msg);
         }
         if (logger.isDebugEnabled()) {
-            logger.debug("tenantId=" + tenantId +
-                    " service binding=" + serviceBinding.getName());
+            logger.debug("tenantId=" + tenantId
+                    " service binding=" + serviceBinding.getName());
         }
     }
 
@@ -225,18 +225,18 @@ public abstract class AbstractServiceContext<IT, OT>
 
         String tenantId = null;
         Subject caller = null;
-        Set<Principal> principals = null;
+        Set<Group> groups = null;
         try {
             caller = (Subject) PolicyContext.getContext(SUBJECT_CONTEXT_KEY);
             if (caller == null) {
                 //logger.warn("security not enabled...");
                 return tenantId;
             }
-            principals = caller.getPrincipals(Principal.class);
-            if (principals != null && principals.size() == 0) {
+            groups = caller.getPrincipals(Group.class);
+            if (groups != null && groups.size() == 0) {
                 //TODO: find out why subject is not null
                 if (logger.isDebugEnabled()) {
-                    logger.debug("weird case where subject is not null and there are no principals");
+                    logger.debug("no tenant(s) found!");
                 }
                 return tenantId;
             }
@@ -245,20 +245,21 @@ public abstract class AbstractServiceContext<IT, OT>
             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());
+        for (Group g : groups) {
+            if ("Tenants".equals(g.getName())) {
+                Enumeration members = g.members();
+                while (members.hasMoreElements()) {
+                    CSpaceTenant tenant = (CSpaceTenant) members.nextElement();
+                    tenantId = tenant.getId();
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("found tenant id=" + tenant.getId()
+                                + " name=" + tenant.getName());
+                    }
                 }
-                tenantId = (String) r;
-                break;
-            } catch (Exception e) {
-                //continue with next principal
             }
         }
+        //TODO: if a user is associated with more than one tenants, the tenant
+        //id should be matched with sent over the wire
         if (tenantId == null) {
             String msg = "Could not find tenant context";
             logger.error(msg);
index b3e8e3adcd50c1d7e61fcffe26641de8e64c1b04..cbe2dd3ab8ab265a447d88ff03554201ef2d51fc 100644 (file)
@@ -45,7 +45,7 @@ public interface ServiceContext<IT, OT> {
     public static final String PART_COMMON_LABEL = "common";
        
     /**
-     * getTenantId get tenant id
+     * getTenantId get id of tenant for which service is accessed
      * @return tenant id
      */
     public String getTenantId();
index 98a2e96c734f1edc4202cde68b9c74284e8d4d67..d8e530a07ce8c7f626ba169cc0734adb5a99be63 100644 (file)
@@ -13,7 +13,6 @@
     <name>services.main</name>
 
     <modules>
-        <!-- add modules below in the order based on dependencies -->
         <module>authentication</module>
         <module>common</module>
         <!-- module>account</module -->