CSPACE-1031 tenants table is separated from account. added accounts_tenants association table. tenant validation updated (if tenant id not in create request, takes from secuirty context), if in (create or update) the request, validates against valid tenants from the tenant table
Requires ant deploy (for authn service...also requires changes in login-config (see jboss-login-config.xml for updated snippet...tenant query has changed)
test: account and security tests with and without authn
M services/authentication/service/src/main/resources/config/jboss-login-config.xml
A services/authentication/pstore/src/main/resources/db/mysql/authentication_index.sql
M services/authentication/pstore/build.xml
M services/JaxRsServiceProvider/src/main/resources/META-INF/persistence.xml
M services/common/src/main/java/org/collectionspace/services/common/storage/jpa/JpaStorageClientImpl.java
M services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountValidatorHandler.java
M services/account/service/src/main/java/org/collectionspace/services/account/storage/AccountDocumentHandler.java
M services/account/jaxb/src/main/resources/accounts_common.xsd
M services/account/pstore/src/test/resources/META-INF/persistence.xml
A services/account/pstore/src/main/resources/db/mysql/account_index.sql
M services/account/pstore/src/main/resources/db/mysql/test_account.sql
M services/account/pstore/src/main/resources/db/mysql/account.sql
M services/account/pstore/build.xml
M services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountTest.java
M services/account/client/src/test/java/org/collectionspace/services/account/client/test/AccountServiceTest.java
M services/account/client/src/test/resources/META-INF/persistence.xml
M services/security/client/src/test/java/org/collectionspace/services/authentication/client/test/AuthenticationServiceTest.java
<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.account.Tenant</class>
+ <class>org.collectionspace.services.account.AccountTenant</class>
+ <class>org.collectionspace.services.account.Status</class>
<class>org.collectionspace.services.authentication.User</class>
<class>org.collectionspace.services.authentication.Role</class>
<class>org.collectionspace.services.authentication.UserRole</class>
import org.collectionspace.services.account.AccountsCommon;
import org.collectionspace.services.account.AccountsCommonList;
import org.collectionspace.services.account.Status;
+import org.collectionspace.services.account.AccountTenant;
import org.collectionspace.services.client.test.AbstractServiceTestImpl;
import org.collectionspace.services.client.test.ServiceRequestType;
import org.jboss.resteasy.client.ClientResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.testng.annotations.AfterClass;
/**
* AccountServiceTest, carries out tests against a
// Instance variables specific to this test.
private AccountClient client = new AccountClient();
private String knownResourceId = null;
- private String resource1Id = null;
- private String resource2Id = null;
- private String resource3Id = null;
+ private List<String> allResourceIdsCreated = new ArrayList();
+ boolean addTenant = true;
/*
* This method is called only by the parent class, AbstractServiceTestImpl
*/
// Submit the request to the service and store the response.
AccountsCommon account =
createAccountInstance("barney", "barney", "hithere08", "barney@dinoland.com",
- true, true, true, true);
+ true, false, true, true);
ClientResponse<Response> res = client.create(account);
int statusCode = res.getStatus();
// Submit the request to the service and store the response.
AccountsCommon account =
createAccountInstance("barney1", "barney", "hithere08", "barney@dinoland.com",
- true, true, true, true);
+ true, false, true, true);
ClientResponse<Response> res = client.create(account);
int statusCode = res.getStatus();
// Submit the request to the service and store the response.
AccountsCommon account =
createAccountInstance("barney", "otherUser", "hithere08", "barney@dinoland.com",
- true, true, true, true);
+ true, false, true, true);
ClientResponse<Response> res = client.create(account);
int statusCode = res.getStatus();
@Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
dependsOnMethods = {"create"})
- public void createWithoutTenant(String testName) throws Exception {
+ public void createWithInvalidTenant(String testName) throws Exception {
setupCreate(testName);
// Submit the request to the service and store the response.
AccountsCommon account =
createAccountInstance("babybop", "babybop", "hithere08", "babybop@dinoland.com",
- true, false, true, true);
+ true, true, true, true);
ClientResponse<Response> res = client.create(account);
int statusCode = res.getStatus();
// Does it exactly match the expected status code?
// Submit the request to the service and store the response.
AccountsCommon account =
createAccountInstance("babybop", "babybop", "hithere08", "babybop@dinoland.com",
- true, true, false, true);
+ true, false, false, true);
ClientResponse<Response> res = client.create(account);
int statusCode = res.getStatus();
// Does it exactly match the expected status code?
// Submit the request to the service and store the response.
AccountsCommon account =
createAccountInstance("babybop", "babybop", "hithere08", "babybop.dinoland.com",
- true, true, true, true);
+ true, false, true, true);
ClientResponse<Response> res = client.create(account);
int statusCode = res.getStatus();
// Does it exactly match the expected status code?
// Submit the request to the service and store the response.
AccountsCommon account =
createAccountInstance("babybop", "babybop", "hithere08", "babybop@dinoland.com",
- false, true, true, true);
+ false, false, true, true);
ClientResponse<Response> res = client.create(account);
int statusCode = res.getStatus();
// Does it exactly match the expected status code?
// Submit the request to the service and store the response.
AccountsCommon account =
createAccountInstance("babybop", "babybop", "hithere08", "babybop/dinoland.com",
- false, false, false, false);
+ false, true, false, false);
ClientResponse<Response> res = client.create(account);
int statusCode = res.getStatus();
// Does it exactly match the expected status code?
// Submit the request to the service and store the response.
AccountsCommon account1 =
createAccountInstance("curious", "curious", "hithere08", "curious@george.com",
- true, true, true, true);
+ true, false, true, true);
ClientResponse<Response> res = client.create(account1);
int statusCode = res.getStatus();
Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
- resource1Id = extractId(res);
+ allResourceIdsCreated.add(extractId(res));
AccountsCommon account2 =
createAccountInstance("tom", "tom", "hithere09", "tom@jerry.com",
- true, true, true, true);
+ true, false, true, true);
res = client.create(account2);
statusCode = res.getStatus();
Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
- resource2Id = extractId(res);
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+ allResourceIdsCreated.add(extractId(res));
AccountsCommon account3 =
createAccountInstance("mj", "mj", "hithere10", "mj@dinoland.com",
- true, true, true, true);
+ true, false, true, true);
res = client.create(account3);
statusCode = res.getStatus();
Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
- resource3Id = extractId(res);
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+ allResourceIdsCreated.add(extractId(res));
}
// Failure outcomes
// The only relevant ID may be the one used in updateAccount(), below.
AccountsCommon account =
createAccountInstance("simba", "simba", "tiger", "simba@lionking.com",
- true, true, true, true);
+ true, false, true, true);
ClientResponse<AccountsCommon> res =
client.update(NON_EXISTENT_ID, account);
int statusCode = res.getStatus();
Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
}
- @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
- dependsOnMethods = {"testSubmitRequest", "updateWrongUser"})
- public void deleteList(String testName) throws Exception {
-
- // Perform setup.
- setupDelete(testName);
-
- ClientResponse<Response> res = client.delete(resource1Id);
- int statusCode = res.getStatus();
- Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
- invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
- Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
-
- res = client.delete(resource2Id);
- statusCode = res.getStatus();
- Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
- invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
- Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
-
- res = client.delete(resource3Id);
- statusCode = res.getStatus();
- Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
- invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
- Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
- }
-
// Failure outcomes
@Override
@Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
* @param passwd
* @param email
* @param useScreenName
- * @param useTenant
+ * @param invalidTenant
* @param useUser
* @param usePassword
* @return
*/
private AccountsCommon createAccountInstance(String screenName,
String userName, String passwd, String email,
- boolean useScreenName, boolean useTenant, boolean useUser, boolean usePassword) {
+ boolean useScreenName, boolean invalidTenant, boolean useUser, boolean usePassword) {
AccountsCommon account = new AccountsCommon();
if (useScreenName) {
account.setPersonRefName(screenName);
account.setEmail(email);
account.setPhone("1234567890");
- if (useTenant) {
- 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);
+ List<AccountTenant> atList = new ArrayList<AccountTenant>();
+ AccountTenant at = new AccountTenant();
+ if (!invalidTenant) {
+ //tenant is not required to be added during create, service layer
+ //picks up tenant from security context if needed
+ if (addTenant) {
+ at.setTenantId("1");
+ atList.add(at);
+ account.setTenants(atList);
+ addTenant = !addTenant;
+ }
+ } else {
+ //use invalid tenant id...called from validation test
+ at.setTenantId(UUID.randomUUID().toString());
+ atList.add(at);
+ account.setTenants(atList);
}
+
if (logger.isDebugEnabled()) {
logger.debug("to be created, account common");
logger.debug(objectAsXmlString(account,
}
+ @AfterClass(alwaysRun = true)
+ public void cleanUp() {
+ setupDelete("delete");
+ if (logger.isDebugEnabled()) {
+ logger.debug("Cleaning up temporary resources created for testing ...");
+ }
+ for (String resourceId : allResourceIdsCreated) {
+ // Note: Any non-success responses are ignored and not reported.
+ ClientResponse<Response> res = client.delete(resourceId);
+ int statusCode = res.getStatus();
+ Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+ }
+ }
+
private void printList(String testName, AccountsCommonList list) {
List<AccountsCommonList.AccountListItem> items =
list.getAccountListItem();
import javax.persistence.Persistence;
import javax.persistence.Query;
+import org.collectionspace.services.account.AccountTenant;
import org.collectionspace.services.account.AccountsCommon;
-import org.collectionspace.services.account.AccountsCommon.Tenant;
+import org.collectionspace.services.account.Tenant;
import org.collectionspace.services.account.Status;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
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);
+ AccountTenant tenant = new AccountTenant();
+ tenant.setTenantId("1");
+ List<AccountTenant> tList = new ArrayList<AccountTenant>();
+ tList.add(tenant);
+ account.setTenants(tList);
em.getTransaction().begin();
em.persist(account);
// Commit the transaction
id = UUID.randomUUID().toString();
account.setCsid(id);
account.setCreatedAtItem(new Date());
- Tenant tenant = new Tenant();
- tenant.setId("123");
- tenant.setName("movingimages.us.standalone");
- List<Tenant> lt = new ArrayList<Tenant>();
- lt.add(tenant);
- account.setTenant(lt);
+ AccountTenant tenant = new AccountTenant();
+ tenant.setTenantId("123");
+ List<AccountTenant> tList = new ArrayList<AccountTenant>();
+ tList.add(tenant);
+ account.setTenants(tList);
em.getTransaction().begin();
em.persist(account);
// Commit the transaction
<?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.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>
+ <class>org.collectionspace.services.account.Tenant</class>
+ <class>org.collectionspace.services.account.AccountTenant</class>
+ <class>org.collectionspace.services.account.Status</class>
<properties>
<property name="hibernate.ejb.cfgfile" value="hibernate.cfg.xml"/>
<!--
Account schema (XSD)
- Entity : Account
+ Entity : Account, Tenant
Part : Common
Used for: JAXB binding between XML and Java objects
<xs:annotation>
<xs:appinfo>
<hj:basic>
- <orm:column name="person_ref_name" length="250" />
+ <orm:column name="person_ref_name" />
</hj:basic>
</xs:appinfo>
</xs:annotation>
<xs:annotation>
<xs:appinfo>
<hj:basic>
- <orm:column name="email" length="512" nullable="false"/>
+ <orm:column name="email" nullable="false"/>
</hj:basic>
</xs:appinfo>
</xs:annotation>
</xs:appinfo>
</xs:annotation>
</xs:element>
- <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 name="tenants" type="account_tenant" minOccurs="1" maxOccurs="unbounded">
</xs:element>
<xs:element name="status" type="status">
<xs:annotation>
<xs:annotation>
<xs:appinfo>
<hj:id>
- <orm:column name="csid" nullable="false"/>
+ <orm:column name="csid" length="128" nullable="false"/>
</hj:id>
</xs:appinfo>
</xs:annotation>
<xs:enumeration value="inactive" />
</xs:restriction>
</xs:simpleType>
+
+ <xs:complexType name="account_tenant">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:entity>
+ <orm:table name="accounts_tenants">
+ </orm:table>
+ </hj:entity>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="tenant_id" type="xs:string" minOccurs="1">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="tenant_id" length="128" nullable="false"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="tenant">
+ <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:id>
+ <orm:column name="id" length="128" nullable="false"/>
+ </hj:id>
+ </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:element name="createdAt" type="xs:dateTime">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="created_at" nullable="false"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="updatedAt" type="xs:dateTime">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="updated_at" />
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
</xs:schema>
<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_index.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
-alter table tenants drop foreign key FKAAE82D09C4F08FD6;
+alter table accounts_tenants drop foreign key FKFDA649B05A9CEEB5;
drop table if exists accounts_common;
+drop table if exists accounts_tenants;
drop table if exists tenants;
-create table accounts_common (csid varchar(255) not null, created_at datetime not null, email longtext not null, mobile varchar(255), person_ref_name varchar(250), phone varchar(255), screen_name varchar(128) not null, status varchar(15) not null, updated_at datetime, userid varchar(128) not null, primary key (csid), unique (screen_name));
-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);
+create table accounts_common (csid varchar(128) not null, created_at datetime not null, email varchar(255) not null, mobile varchar(255), person_ref_name varchar(255), phone varchar(255), screen_name varchar(128) not null, status varchar(15) not null, updated_at datetime, userid varchar(128) not null, primary key (csid), unique (screen_name));
+create table accounts_tenants (HJID bigint not null auto_increment, tenant_id varchar(128) not null, TENANTS_ACCOUNTSCOMMON_CSID varchar(128), primary key (HJID));
+create table tenants (id varchar(128) not null, created_at datetime not null, name varchar(255) not null, updated_at datetime, primary key (id));
+alter table accounts_tenants add index FKFDA649B05A9CEEB5 (TENANTS_ACCOUNTSCOMMON_CSID), add constraint FKFDA649B05A9CEEB5 foreign key (TENANTS_ACCOUNTSCOMMON_CSID) references accounts_common (csid);
--- /dev/null
+--
+-- Copyright 20010 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;
+CREATE INDEX index_userid ON accounts_common (userid);
+CREATE INDEX index_screen_name ON accounts_common (screen_name);
+CREATE INDEX index_email ON accounts_common (email);
+CREATE INDEX index_person_ref_name ON accounts_common (person_ref_name);
+CREATE INDEX index_update_at ON accounts_common (updated_at);
+CREATE INDEX index_status ON accounts_common (status);
\ No newline at end of file
--
use cspace;
INSERT INTO `cspace`.`accounts_common` (`csid`, `email`, `phone`, `mobile`, `userid`, `status`, `screen_name`, `created_at`) VALUES ('eeca40d7-dc77-4cc5-b489-16a53c75525a','test.test@berkeley.edu',NULL,NULL,'test','ACTIVE','test', '2010-02-17 16:31:48');
-
-INSERT INTO `cspace`.`tenants` VALUES (1,'1','movingimages.us','eeca40d7-dc77-4cc5-b489-16a53c75525a');
\ No newline at end of file
+INSERT INTO `cspace`.`tenants` (`id`, `name`, `created_at`) VALUES ('1','movingimages.us', '2010-02-17 16:31:48');
+INSERT INTO `cspace`.`accounts_tenants` (`TENANTS_ACCOUNTSCOMMON_CSID`, `tenant_id`) VALUES ('eeca40d7-dc77-4cc5-b489-16a53c75525a', '1');
<?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.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>
+ <class>org.collectionspace.services.account.Tenant</class>
+ <class>org.collectionspace.services.account.AccountTenant</class>
+ <class>org.collectionspace.services.account.Status</class>
<properties>
<property name="hibernate.ejb.cfgfile" value="hibernate.cfg.xml"/>
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
+import org.collectionspace.services.account.AccountTenant;
import org.collectionspace.services.account.AccountsCommon;
-import org.collectionspace.services.account.AccountsCommon.Tenant;
import org.collectionspace.services.account.AccountsCommonList;
import org.collectionspace.services.account.AccountsCommonList.AccountListItem;
import org.collectionspace.services.account.Status;
+import org.collectionspace.services.common.context.ServiceContext;
import org.collectionspace.services.common.document.AbstractDocumentHandlerImpl;
import org.collectionspace.services.common.document.DocumentFilter;
import org.collectionspace.services.common.document.DocumentWrapper;
String id = UUID.randomUUID().toString();
AccountsCommon account = wrapDoc.getWrappedObject();
account.setCsid(id);
-
+ setTenant(account);
account.setStatus(Status.ACTIVE);
}
return new AccountJpaFilter();
}
+ private void setTenant(AccountsCommon account) {
+ //set tenant only if not available from input
+ ServiceContext ctx = getServiceContext();
+ if (account.getTenants() == null || account.getTenants().size() == 0) {
+ if (ctx.getTenantId() != null) {
+ AccountTenant at = new AccountTenant();
+ at.setTenantId(ctx.getTenantId());
+ List<AccountTenant> atList = new ArrayList<AccountTenant>();
+ atList.add(at);
+ account.setTenants(atList);
+ }
+ }
+ }
+
/**
* sanitize removes data not needed to be sent to the consumer
* @param account
*/
private void sanitize(AccountsCommon account) {
account.setPassword(null);
- //FIXME once auth mode is mandatory, assume tenant could be retrieved
- //from security context, remove tenant info being passed to the consumer
- //account.setTenant(new ArrayList<Tenant>(0));
+ account.setTenants(new ArrayList<AccountTenant>(0));
}
}
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import org.collectionspace.services.account.AccountTenant;
import org.collectionspace.services.account.AccountsCommon;
+import org.collectionspace.services.account.Tenant;
import org.collectionspace.services.common.context.ServiceContext;
import org.collectionspace.services.common.document.DocumentHandler.Action;
import org.collectionspace.services.common.document.InvalidDocumentException;
import org.collectionspace.services.common.document.ValidatorHandler;
+import org.collectionspace.services.common.storage.jpa.JpaStorageClientImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
StringBuilder msgBldr = new StringBuilder("validate() ");
boolean invalid = false;
- if (action.equals(Action.CREATE)) {
- //FIXME tenant would be retrieved from security context once
- //authentication is made mandatory, no need for validation
- List<AccountsCommon.Tenant> tl = account.getTenant();
- if (tl == null || tl.size() == 0) {
- msgBldr.append("\ntenant : missing information!");
+ List<AccountTenant> tl = account.getTenants();
+ if (tl != null && tl.size() > 0) {
+ if (isInvalidTenant(tl, msgBldr)) {
invalid = true;
}
+ }
+
+ if (action.equals(Action.CREATE)) {
+
//create specific validation here
if (account.getScreenName() == null || account.getScreenName().isEmpty()) {
invalid = true;
invalid = true;
msgBldr.append("\nemail : missing");
} else {
- if (invalidEmail(account.getEmail(), msgBldr)) {
+ if (isInvalidEmail(account.getEmail(), msgBldr)) {
invalid = true;
}
}
msgBldr.append("\npassword : userId is needed");
}
if (account.getEmail() != null) {
- if (invalidEmail(account.getEmail(), msgBldr)) {
+ if (isInvalidEmail(account.getEmail(), msgBldr)) {
invalid = true;
}
}
}
}
- private boolean invalidEmail(String email, StringBuilder msgBldr) {
+ private boolean isInvalidEmail(String email, StringBuilder msgBldr) {
boolean invalid = false;
Pattern p = Pattern.compile("^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[_A-Za-z0-9-]+)");
Matcher m = p.matcher(email);
}
return invalid;
}
+
+ private boolean isInvalidTenant(List<AccountTenant> atList, StringBuilder msgBldr) {
+ boolean invalid = false;
+ JpaStorageClientImpl store = new JpaStorageClientImpl();
+ EntityManagerFactory emf = store.getEntityManagerFactory();
+ EntityManager em = emf.createEntityManager();
+ try {
+ for (AccountTenant at : atList) {
+ String tid = at.getTenantId();
+ if (tid == null || tid.isEmpty()) {
+ invalid = true;
+ msgBldr.append("\n tenant : tenantId is missing");
+ break;
+ }
+ Tenant tenantFound = em.find(Tenant.class, tid);
+ if (tenantFound == null) {
+ invalid = true;
+ msgBldr.append("\n tenant : tenantId=" + tid
+ + " not found");
+ break;
+ }
+ }
+ } finally {
+ if (em != null) {
+ store.releaseEntityManagerFactory(emf);
+ }
+ }
+ return invalid;
+ }
}
<description>\r
collectionspace authentication 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
</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
<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
<arg value="${mvn.opts}" />\r
</exec>\r
</target>\r
- \r
+\r
<target name="setup_hibernate.cfg" description="replace property keywords in hibernate.cfg.xml">\r
<property name="src.hibernate.cfg" value="${basedir}/src/test/resources/hibernate.cfg.xml"/>\r
<property name="dest.hibernate.cfg" value="${basedir}/target/test-classes/hibernate.cfg.xml"/>\r
\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 authentication service">\r
+ description="create tables(s), indices for authentication service">\r
+ <sql driver="com.mysql.jdbc.Driver"\r
+ url="jdbc:mysql://${db.host}:${db.port}/cspace"\r
+ userid="${db.user}"\r
+ password="${db.user.password}"\r
+ src="${db.script.dir}/authentication.sql"\r
+ >\r
+ <classpath>\r
+ <pathelement path="${db.driver.jar}"/>\r
+ </classpath>\r
+ </sql>\r
<sql driver="com.mysql.jdbc.Driver"\r
- url="jdbc:mysql://${db.host}:${db.port}/cspace"\r
- userid="${db.user}"\r
- password="${db.user.password}"\r
- src="${db.script.dir}/authentication.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}/authentication_index.sql"\r
+ >\r
<classpath>\r
<pathelement path="${db.driver.jar}"/>\r
</classpath>\r
</sql>\r
<sql driver="com.mysql.jdbc.Driver"\r
- url="jdbc:mysql://${db.host}:${db.port}/cspace"\r
- userid="${db.user}"\r
- password="${db.user.password}"\r
- src="${db.script.dir}/test_authn.sql"\r
- >\r
+ url="jdbc:mysql://${db.host}:${db.port}/cspace"\r
+ userid="${db.user}"\r
+ password="${db.user.password}"\r
+ src="${db.script.dir}/test_authn.sql"\r
+ >\r
<classpath>\r
<pathelement path="${db.driver.jar}"/>\r
</classpath>\r
</sql>\r
</target>\r
- \r
+\r
<target name="deploy" depends="install"\r
- description="deploy authentication service in ${jboss.server.cspace}">\r
+ description="deploy authentication service in ${jboss.server.cspace}">\r
<copy todir="${jboss.server.cspace}/cspace/services">\r
<fileset dir="${src}/main/resources/"/>\r
</copy>\r
</target>\r
\r
<target name="undeploy"\r
- description="undeploy authentication service from ${jboss.server.cspace}">\r
+ description="undeploy authentication service from ${jboss.server.cspace}">\r
</target>\r
\r
<target name="dist"\r
- description="generate distribution for authentication service" depends="package">\r
+ description="generate distribution for authentication service" depends="package">\r
<!-- copy db scripts, etc. -->\r
<copy todir="${services.trunk}/${dist.server.cspace}/cspace/services">\r
<fileset dir="${src}/main/resources/"/>\r
--- /dev/null
+--
+-- Copyright 20010 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;
+CREATE INDEX index_rolename ON roles (rolegroup);
+CREATE INDEX index_username ON users_roles (username);
+CREATE INDEX index_rolename ON users_roles (rolename);
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
+ select t.id, t.name, 'Tenants' from accounts_common as a, accounts_tenants as at, tenants as t where a.userid=? and a.csid = at.TENANTS_ACCOUNTSCOMMON_CSID and at.tenant_id = t.id
</module-option>
</login-module>
</authentication>
private final Logger logger = LoggerFactory.getLogger(JpaStorageClientImpl.class);
/** The Constant CS_PERSISTENCE_UNIT. */
- protected final static String CS_PERSISTENCE_UNIT = "org.collectionspace.services";
+ public final static String CS_PERSISTENCE_UNIT = "org.collectionspace.services";
/**
* Instantiates a new jpa storage client.
*
* @return the entity manager factory
*/
- protected EntityManagerFactory getEntityManagerFactory() {
+ public EntityManagerFactory getEntityManagerFactory() {
return getEntityManagerFactory(CS_PERSISTENCE_UNIT);
}
*
* @return the entity manager factory
*/
- protected EntityManagerFactory getEntityManagerFactory(
+ public EntityManagerFactory getEntityManagerFactory(
String persistenceUnit) {
return Persistence.createEntityManagerFactory(persistenceUnit);
*
* @param emf the emf
*/
- protected void releaseEntityManagerFactory(EntityManagerFactory emf) {
+ public void releaseEntityManagerFactory(EntityManagerFactory emf) {
if (emf != null) {
emf.close();
}
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.account.AccountTenant;
import org.collectionspace.services.client.AccountClient;
import org.collectionspace.services.account.AccountsCommon;
import org.jboss.resteasy.client.ClientResponse;
/** 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);
}
Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
// Store the ID returned from this create operation
// for additional tests below.
barneyAccountId = extractId(res);
}
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);
- }
+ Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
}
}
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));
}
// ---------------------------------------------------------------
account.setPassword(Base64.encodeBase64(passwd.getBytes()));
account.setEmail(email);
account.setPhone("1234567890");
- List<AccountsCommon.Tenant> atl = new ArrayList<AccountsCommon.Tenant>();
+ List<AccountTenant> atl = new ArrayList<AccountTenant>();
- AccountsCommon.Tenant at = new AccountsCommon.Tenant();
- at.setId(tenantId);//for testing purposes
- at.setName("movingimages.us");
+ AccountTenant at = new AccountTenant();
+ at.setTenantId(tenantId);//for testing purposes
atl.add(at);
//disable 2nd tenant till tenant identification is in effect
//on the service side for 1-n user-tenants
// at2.setId(UUID.randomUUID().toString());
// at2.setName("collectionspace.org");
// atl.add(at2);
- account.setTenant(atl);
+ account.setTenants(atl);
if (logger.isDebugEnabled()) {
logger.debug("to be created, account common");