public static final String SERVICE_NAME = "accounts";
public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME;
public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT;
+ public final static String IMMUTABLE = "immutable";
@Override
public String getServiceName() {
//import org.collectionspace.services.authorization.AccountRolesList;
import org.collectionspace.services.account.AccountsCommon;
+import org.collectionspace.services.account.AccountsCommonList;
import org.collectionspace.services.authorization.AccountRole;
import org.collectionspace.services.authorization.AccountValue;
import org.collectionspace.services.authorization.Role;
// Instance variables specific to this test.
/** The known resource id. */
private String knownResourceId = null;
+ private String prebuiltAdminCSID = null;
+ private String prebuiltAdminUserId = "admin@core.collectionspace.org";
/** The all resource ids created. */
private List<String> allResourceIdsCreated = new ArrayList<String>();
/** The acc values. */
}
+ @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+ dependsOnMethods = {"read"})
+ public void deleteLockedAccount(String testName) throws Exception {
+
+ if (logger.isDebugEnabled()) {
+ testBanner(testName, CLASS_NAME);
+ }
+
+ findPrebuiltAdminAccount();
+
+ // Perform setup.
+ EXPECTED_STATUS_CODE = Response.Status.FORBIDDEN.getStatusCode();
+ REQUEST_TYPE = ServiceRequestType.DELETE;
+ testSetup(EXPECTED_STATUS_CODE, REQUEST_TYPE);
+
+ AccountRoleClient client = new AccountRoleClient();
+ ClientResponse<Response> res = client.delete(prebuiltAdminCSID);
+ try {
+ int statusCode = res.getStatus();
+ Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+ } finally {
+ res.releaseConnection();
+ }
+ }
+
// Failure outcomes
/* (non-Javadoc)
* @see org.collectionspace.services.client.test.AbstractServiceTestImpl#deleteNonExistent(java.lang.String)
return extractId(res);
}
+ private void findPrebuiltAdminAccount() {
+ // Search for the prebuilt admin user and then hold its CSID
+ if(prebuiltAdminCSID == null) {
+ setupReadList();
+ AccountClient client = new AccountClient();
+ ClientResponse<AccountsCommonList> res =
+ client.readSearchList(null, this.prebuiltAdminUserId, null);
+ AccountsCommonList list = res.getEntity();
+ int statusCode = res.getStatus();
+
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+ List<AccountsCommonList.AccountListItem> items = list.getAccountListItem();
+ Assert.assertEquals(1, items.size(), "Found more than one Admin account!");
+ AccountsCommonList.AccountListItem item = items.get(0);
+ prebuiltAdminCSID = item.getCsid();
+ if (logger.isDebugEnabled()) {
+ logger.debug("Found Admin Account with ID: " + prebuiltAdminCSID);
+ }
+ }
+ }
+
/**
* Delete account.
*
// Instance variables specific to this test.
/** The known resource id. */
private String knownResourceId = null;
+ private String prebuiltAdminCSID = null;
+ private String prebuiltAdminUserId = "admin@core.collectionspace.org";
private String knownUserId = "barney";
private String knownUserPassword = "hithere08";
/** The add tenant. */
Assert.assertEquals(statusCode, Response.Status.BAD_REQUEST.getStatusCode());
}
+
+ private void findPrebuiltAdminAccount() {
+ // Search for the prebuilt admin user and then hold its CSID
+ if(prebuiltAdminCSID == null) {
+ setupReadList();
+ AccountClient client = new AccountClient();
+ ClientResponse<AccountsCommonList> res =
+ client.readSearchList(null, this.prebuiltAdminUserId, null);
+ AccountsCommonList list = res.getEntity();
+ int statusCode = res.getStatus();
+
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+ List<AccountsCommonList.AccountListItem> items = list.getAccountListItem();
+ Assert.assertEquals(1, items.size(), "Found more than one Admin account!");
+ AccountsCommonList.AccountListItem item = items.get(0);
+ prebuiltAdminCSID = item.getCsid();
+ if (logger.isDebugEnabled()) {
+ logger.debug("Found Admin Account with ID: " + prebuiltAdminCSID);
+ }
+ }
+ }
+
+ @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+ dependsOnMethods = {"read", "readList", "readNonExistent"})
+ public void verifyMetadataProtection(String testName) throws Exception {
+ findPrebuiltAdminAccount();
+ // Try to update the metadata - it should just get ignored
+ if (logger.isDebugEnabled()) {
+ logger.debug(testBanner(testName, CLASS_NAME));
+ }
+ // Perform setup.
+ setupUpdate();
+
+ AccountClient client = new AccountClient();
+ ClientResponse<AccountsCommon> res = client.read(prebuiltAdminCSID);
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": read status = " + res.getStatus());
+ }
+ Assert.assertEquals(res.getStatus(), EXPECTED_STATUS_CODE);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Did get on Admin Account to update with ID: " + prebuiltAdminCSID);
+ }
+ AccountsCommon accountFound = (AccountsCommon) res.getEntity();
+ Assert.assertNotNull(accountFound);
+
+ //create a new account object to test partial updates
+ AccountsCommon accountToUpdate = new AccountsCommon();
+ accountToUpdate.setCsid(prebuiltAdminCSID);
+ accountToUpdate.setUserId(accountFound.getUserId());
+ // Update the content of this resource.
+ accountToUpdate.setEmail("updated-" + accountFound.getEmail());
+ if (logger.isDebugEnabled()) {
+ logger.debug("updated object");
+ logger.debug(objectAsXmlString(accountFound,
+ AccountsCommon.class));
+ }
+
+ // Submit the request to the service and store the response.
+ res = client.update(prebuiltAdminCSID, accountToUpdate);
+ 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));
+ // Note that the error is not returned, it is just ignored
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
+ AccountsCommon accountUpdated = (AccountsCommon) res.getEntity();
+ Assert.assertNotNull(accountUpdated);
+
+ Assert.assertFalse(accountUpdated.getEmail().equals(accountToUpdate.getEmail()),
+ "Admin Account (with metadata lock) allowed update to change the email!");
+ }
+
+
+ @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+ dependsOnMethods = {"read", "readList", "readNonExistent"})
+ public void verifyProtectionReadOnly(String testName) throws Exception {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(testBanner(testName, CLASS_NAME));
+ }
+
+ setupCreate();
+
+ // Submit the request to the service and store the response.
+ AccountClient client = new AccountClient();
+ AccountsCommon account =
+ createAccountInstance("mdTest", "mdTest", "mdTestPW", "md@test.com",
+ client.getTenantId(), true, false, true, true);
+ account.setMetadataProtection(AccountClient.IMMUTABLE);
+ account.setRolesProtection(AccountClient.IMMUTABLE);
+ ClientResponse<Response> res = client.create(account);
+ int statusCode = res.getStatus();
+ 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.
+ String testResourceId = extractId(res);
+ allResourceIdsCreated.add(testResourceId);
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": testResourceId=" + testResourceId);
+ }
+ setupRead();
+
+ // Submit the request to the service and store the response.
+ ClientResponse<AccountsCommon> accountRes = client.read(testResourceId);
+ statusCode = accountRes.getStatus();
+
+ Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
+ AccountsCommon accountRead = (AccountsCommon) accountRes.getEntity();
+ Assert.assertNotNull(accountRead);
+ String mdProtection = accountRead.getMetadataProtection();
+ String rolesProtection = accountRead.getRolesProtection();
+ if (logger.isTraceEnabled()) {
+ logger.trace(testName + ": metadataProtection=" + mdProtection);
+ logger.trace(testName + ": rolesProtection=" + rolesProtection);
+ }
+ Assert.assertFalse(account.getMetadataProtection().equals(mdProtection),
+ "Account allowed create to set the metadata protection flag.");
+ Assert.assertFalse(account.getRolesProtection().equals(rolesProtection),
+ "Account allowed create to set the perms protection flag.");
+
+ setupUpdate();
+
+ AccountsCommon accountToUpdate =
+ createAccountInstance("mdTest", "mdTest", "mdTestPW", "md@test.com",
+ client.getTenantId(), true, false, true, true);
+ accountToUpdate.setMetadataProtection(AccountClient.IMMUTABLE);
+ accountToUpdate.setRolesProtection(AccountClient.IMMUTABLE);
+
+ // Submit the request to the service and store the response.
+ accountRes = client.update(testResourceId, accountToUpdate);
+ statusCode = accountRes.getStatus();
+ // Check the status code of the response: does it match the expected response(s)?
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": status = " + statusCode);
+ }
+ Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
+
+ AccountsCommon accountUpdated = (AccountsCommon) accountRes.getEntity();
+ Assert.assertNotNull(accountUpdated);
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + "Updated account: ");
+ logger.debug(objectAsXmlString(accountUpdated,AccountsCommon.class));
+ }
+
+ Assert.assertFalse(
+ AccountClient.IMMUTABLE.equalsIgnoreCase(accountUpdated.getMetadataProtection()),
+ "Account allowed update of the metadata protection flag.");
+ Assert.assertFalse(
+ AccountClient.IMMUTABLE.equalsIgnoreCase(accountUpdated.getRolesProtection()),
+ "Account allowed update of the roles protection flag.");
+ }
+
+
/**
* Deactivate.
</xs:appinfo>
</xs:annotation>
</xs:element>
- <xs:element name="createdAt" type="xs:dateTime">
+ <xs:element name="metadataProtection" type="xs:string" minOccurs="0" maxOccurs="1">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="metadata_protection" nullable="true"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rolesProtection" type="xs:string" minOccurs="0" maxOccurs="1">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="roles_protection" nullable="true"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="createdAt" type="xs:dateTime">
<xs:annotation>
<xs:appinfo>
<hj:basic>
drop table if exists accounts_common;
drop table if exists accounts_tenants;
drop table if exists tenants;
-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));
+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, metadata_protection varchar(255), roles_protection varchar(255), primary key (csid));
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);
DROP TABLE IF EXISTS accounts_tenants CASCADE;
DROP TABLE IF EXISTS tenants CASCADE;
DROP SEQUENCE IF EXISTS hibernate_sequence;
-create table accounts_common (csid varchar(128) not null, created_at timestamp 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 timestamp, userid varchar(128) not null, primary key (csid));
+create table accounts_common (csid varchar(128) not null, created_at timestamp 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 timestamp, userid varchar(128) not null, metadata_protection varchar(255), roles_protection varchar(255), primary key (csid));
create table accounts_tenants (HJID int8 not null, tenant_id varchar(128) not null, TENANTS_ACCOUNTSCOMMON_CSID varchar(128), primary key (HJID));
create table tenants (id varchar(128) not null, created_at timestamp not null, name varchar(255) not null, updated_at timestamp, primary key (id));
alter table accounts_tenants add constraint FKFDA649B05A9CEEB5 foreign key (TENANTS_ACCOUNTSCOMMON_CSID) references accounts_common;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
logger.debug("deleteAccount with csid=" + csid);
ensureCSID(csid, ServiceMessages.DELETE_FAILED);
try {
- //FIXME ideally the following two ops shoudl be in the same tx CSPACE-658
+ AccountsCommon account = (AccountsCommon)get(csid, AccountsCommon.class);
+ // If marked as metadata immutable, do not delete
+ if(AccountClient.IMMUTABLE.equals(account.getMetadataProtection())) {
+ Response response =
+ Response.status(Response.Status.FORBIDDEN).entity("Account: "+csid+" is immutable.").type("text/plain").build();
+ return response;
+ }
+ //FIXME ideally the following two ops should be in the same tx CSPACE-658
//delete all relationships
AccountRoleSubResource subResource = new AccountRoleSubResource("accounts/accountroles");
subResource.deleteAccountRole(csid, SubjectType.ROLE);
logger.debug("createAccountRole with accCsid=" + accCsid);
ensureCSID(accCsid, ServiceMessages.POST_FAILED+ "accountroles account ");
try {
+ AccountsCommon account = (AccountsCommon)get(accCsid, AccountsCommon.class);
+ // If marked as roles immutable, do not create
+ if(AccountClient.IMMUTABLE.equals(account.getRolesProtection())) {
+ Response response =
+ Response.status(Response.Status.FORBIDDEN).entity("Roles for Account: "+accCsid+" are immutable.").type("text/plain").build();
+ return response;
+ }
AccountRoleSubResource subResource =
new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
String accrolecsid = subResource.createAccountRole(input, SubjectType.ROLE);
logger.debug("deleteAccountRole with accCsid=" + accCsid);
ensureCSID(accCsid, ServiceMessages.DELETE_FAILED+ "accountroles account ");
try {
+ AccountsCommon account = (AccountsCommon)get(accCsid, AccountsCommon.class);
+ // If marked as roles immutable, do not delete
+ if(AccountClient.IMMUTABLE.equals(account.getRolesProtection())) {
+ Response response =
+ Response.status(Response.Status.FORBIDDEN).entity("Roles for Account: "+accCsid+" are immutable.").type("text/plain").build();
+ return response;
+ }
AccountRoleSubResource subResource =
new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
//delete all relationships for an account
logger.debug("deleteAccountRole: All roles related to account with accCsid=" + accCsid);
ensureCSID(accCsid, ServiceMessages.DELETE_FAILED+ "accountroles account ");
try {
+ // If marked as roles immutable, do not delete
+ AccountsCommon account = (AccountsCommon)get(accCsid, AccountsCommon.class);
+ if(AccountClient.IMMUTABLE.equals(account.getRolesProtection())) {
+ Response response =
+ Response.status(Response.Status.FORBIDDEN).entity("Roles for Account: "+accCsid+" are immutable.").type("text/plain").build();
+ return response;
+ }
AccountRoleSubResource subResource =
new AccountRoleSubResource(AccountRoleSubResource.ACCOUNT_ACCOUNTROLE_SERVICE);
//delete all relationships for an account
import org.collectionspace.services.account.AccountsCommonList.AccountListItem;
import org.collectionspace.services.account.Status;
+import org.collectionspace.services.client.AccountClient;
import org.collectionspace.services.common.storage.jpa.JpaDocumentHandler;
import org.collectionspace.services.common.context.ServiceContext;
import org.collectionspace.services.common.document.DocumentFilter;
account.setCsid(id);
setTenant(account);
account.setStatus(Status.ACTIVE);
+ // We do not allow creation of locked accounts through the services.
+ account.setMetadataProtection(null);
+ account.setRolesProtection(null);
}
@Override
public void handleUpdate(DocumentWrapper<AccountsCommon> wrapDoc) throws Exception {
AccountsCommon accountFound = wrapDoc.getWrappedObject();
AccountsCommon accountReceived = getCommonPart();
- merge(accountReceived, accountFound);
+ // If marked as metadata immutable, do not do update
+ if(!AccountClient.IMMUTABLE.equals(accountFound.getMetadataProtection())) {
+ merge(accountReceived, accountFound);
+ }
}
/**
if (from.getPersonRefName() != null) {
to.setPersonRefName(from.getPersonRefName());
}
+ // Note that we do not allow update of locks
//fixme update for tenant association
if (logger.isDebugEnabled()) {
@Override
public void completeUpdate(DocumentWrapper<AccountsCommon> wrapDoc) throws Exception {
AccountsCommon upAcc = wrapDoc.getWrappedObject();
- getServiceContext().setOutput(account);
+ getServiceContext().setOutput(upAcc);
sanitize(upAcc);
}
AccountsCommon accountFound = getAccount(em, id);
checkAllowedUpdates(accountReceived, accountFound);
//if userid and password are given, add to default id provider
+ // Note that this ignores the immutable flag, as we allow
+ // password changes.
if (accountReceived.getUserId() != null
&& isForCSIdP(accountReceived.getPassword())) {
userStorageClient.update(em,
public static final String SERVICE_PATH_COMPONENT = SERVICE_NAME;
public static final String SERVICE_PATH = "/" + SERVICE_PATH_COMPONENT;
public static final String SERVICE_PATH_PROXY = SERVICE_PATH + "/";
+ public final static String IMMUTABLE = "immutable";
@Override
public String getServiceName() {
}
// Optionally output additional data about list members for debugging.
boolean iterateThroughList = true;
- if (iterateThroughList && logger.isDebugEnabled()) {
+ if ((iterateThroughList || (EXPECTED_ITEMS != list.getPermissions().size()))
+ && logger.isDebugEnabled()) {
printList(testName, list);
}
- Assert.assertEquals(EXPECTED_ITEMS, list.getPermissions().size());
+ Assert.assertEquals(list.getPermissions().size(), EXPECTED_ITEMS);
}
roleToUpdate.getDescription(),
"Data in updated object did not match submitted data.");
}
+
+ @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
+ dependsOnMethods = {"read", "readList", "readNonExistent"})
+ public void verifyProtectionReadOnly(String testName) throws Exception {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(testBanner(testName, CLASS_NAME));
+ }
+
+ setupCreate();
+
+ // Submit the request to the service and store the response.
+ RoleClient client = new RoleClient();
+ Role role = createRoleInstance(knownRoleName+"_PT", "Just a temp", true);
+ role.setMetadataProtection(RoleClient.IMMUTABLE);
+ role.setPermsProtection(RoleClient.IMMUTABLE);
+ ClientResponse<Response> res = client.create(role);
+ int statusCode = res.getStatus();
+ 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.
+ String testResourceId = extractId(res);
+ allResourceIdsCreated.add(testResourceId);
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": testResourceId=" + testResourceId);
+ }
+ setupRead();
+
+ // Submit the request to the service and store the response.
+ ClientResponse<Role> roleRes = client.read(testResourceId);
+ statusCode = roleRes.getStatus();
+
+ Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
+ Role roleRead = (Role) roleRes.getEntity();
+ Assert.assertNotNull(roleRead);
+ String mdProtection = roleRead.getMetadataProtection();
+ String permsProtection = roleRead.getPermsProtection();
+ if (logger.isTraceEnabled()) {
+ logger.trace(testName + ": metadataProtection=" + mdProtection);
+ logger.trace(testName + ": permsProtection=" + permsProtection);
+ }
+ Assert.assertFalse(role.getMetadataProtection().equals(mdProtection),
+ "Role allowed create to set the metadata protection flag.");
+ Assert.assertFalse(role.getPermsProtection().equals(permsProtection),
+ "Role allowed create to set the perms protection flag.");
+
+ setupUpdate();
+
+ Role roleToUpdate = createRoleInstance(knownRoleName+"_PT", "Just a temp", true);
+ roleToUpdate.setMetadataProtection(RoleClient.IMMUTABLE);
+ roleToUpdate.setPermsProtection(RoleClient.IMMUTABLE);
+
+ // Submit the request to the service and store the response.
+ roleRes = client.update(testResourceId, roleToUpdate);
+ statusCode = roleRes.getStatus();
+ // Check the status code of the response: does it match the expected response(s)?
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + ": status = " + statusCode);
+ }
+ Assert.assertTrue(REQUEST_TYPE.isValidStatusCode(statusCode),
+ invalidStatusCodeMessage(REQUEST_TYPE, statusCode));
+ Assert.assertEquals(statusCode, EXPECTED_STATUS_CODE);
+
+
+ Role roleUpdated = (Role) roleRes.getEntity();
+ Assert.assertNotNull(roleUpdated);
+ if (logger.isDebugEnabled()) {
+ logger.debug(testName + "Updated role: ");
+ logger.debug(objectAsXmlString(roleUpdated,Role.class));
+ }
+
+ Assert.assertFalse(
+ RoleClient.IMMUTABLE.equalsIgnoreCase(roleUpdated.getMetadataProtection()),
+ "Role allowed update of the metadata protection flag.");
+ Assert.assertFalse(
+ RoleClient.IMMUTABLE.equalsIgnoreCase(roleUpdated.getPermsProtection()),
+ "Role allowed update of the perms protection flag.");
+ }
+
+
@Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
dependsOnMethods = {"read", "readList", "readNonExistent"})
*/
@Override
@Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class,
- dependsOnMethods = {"updateNotAllowed", "testSubmitRequest"})
+ dependsOnMethods = {"updateNotAllowed", "testSubmitRequest", "verifyProtectionReadOnly"})
public void delete(String testName) throws Exception {
if (logger.isDebugEnabled()) {
<version>${project.version}</version>\r
<scope>provided</scope>\r
</dependency>\r
+ <dependency>\r
+ <groupId>org.collectionspace.services</groupId>\r
+ <artifactId>org.collectionspace.services.authorization-mgt.client</artifactId>\r
+ <version>${project.version}</version>\r
+ </dependency>\r
<dependency>\r
<groupId>org.testng</groupId>\r
<artifactId>testng</artifactId>\r
import org.collectionspace.services.authorization.PermissionValue;
import org.collectionspace.services.authorization.PermissionsList;
import org.collectionspace.services.authorization.PermissionsRolesList;
+import org.collectionspace.services.client.RoleClient;
import org.collectionspace.services.authorization.Role;
import org.collectionspace.services.authorization.RoleValue;
import org.collectionspace.services.authorization.RolesList;
}
private Role buildTenantAdminRole(String tenantId) {
- Role role = new Role();
- role.setCreatedAtItem(new Date());
- role.setDisplayName(ROLE_TENANT_ADMINISTRATOR);
- role.setRoleName(ROLE_PREFIX +
- tenantId + "_" +
- role.getDisplayName());
-
- String id = UUID.randomUUID().toString();
- role.setCsid(id);
- role.setDescription("generated tenant admin role");
- role.setTenantId(tenantId);
- return role;
+ return buildTenantRole(tenantId, ROLE_TENANT_ADMINISTRATOR, "admin");
}
private Role buildTenantReaderRole(String tenantId) {
+ return buildTenantRole(tenantId, ROLE_TENANT_READER, "read only");
+ }
+
+ private Role buildTenantRole(String tenantId, String name, String type) {
Role role = new Role();
role.setCreatedAtItem(new Date());
- role.setDisplayName(ROLE_TENANT_READER);
+ role.setDisplayName(name);
role.setRoleName(ROLE_PREFIX +
tenantId + "_" +
role.getDisplayName());
String id = UUID.randomUUID().toString();
role.setCsid(id);
- role.setDescription("generated tenant read only role");
+ role.setDescription("generated tenant "+type+" role");
role.setTenantId(tenantId);
+ role.setMetadataProtection(RoleClient.IMMUTABLE);
+ role.setPermsProtection(RoleClient.IMMUTABLE);
return role;
}
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
@PUT
@Path("{csid}")
public Role updateRole(@PathParam("csid") String csid, Role theUpdate) {
- return (Role)update(csid, theUpdate, Role.class);
+ try {
+ Role role = (Role)get(csid, Role.class);
+ // If marked as metadata immutable, do not update
+ if(RoleClient.IMMUTABLE.equals(role.getMetadataProtection())) {
+ Response response =
+ Response.status(Response.Status.FORBIDDEN).entity("Role: "+csid+" is immutable.").type("text/plain").build();
+ throw new WebApplicationException(response);
+ }
+ return (Role)update(csid, theUpdate, Role.class);
+ } catch (Exception e) {
+ throw bigReThrow(e, ServiceMessages.UPDATE_FAILED, csid);
+ }
}
@DELETE
ensureCSID(csid, ServiceMessages.DELETE_FAILED + "deleteRole ");
try {
+ Role role = (Role)get(csid, Role.class);
+ // If marked as metadata immutable, do not delete
+ if(RoleClient.IMMUTABLE.equals(role.getMetadataProtection())) {
+ Response response =
+ Response.status(Response.Status.FORBIDDEN).entity("Role: "+csid+" is immutable.").type("text/plain").build();
+ return response;
+ }
//FIXME ideally the following three operations should be in the same tx CSPACE-658
//delete all relationships for this permission
PermissionRoleSubResource permRoleResource =
logger.debug("createRolePermission with roleCsid=" + roleCsid);
ensureCSID(roleCsid, ServiceMessages.PUT_FAILED + "permroles role ");
try {
+ Role role = (Role)get(roleCsid, Role.class);
+ // If marked as metadata immutable, do not delete
+ if(RoleClient.IMMUTABLE.equals(role.getPermsProtection())) {
+ Response response =
+ Response.status(Response.Status.FORBIDDEN).entity("Role: "+roleCsid+" is immutable.").type("text/plain").build();
+ return response;
+ }
PermissionRoleSubResource subResource =
new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
String permrolecsid = subResource.createPermissionRole(input, SubjectType.PERMISSION);
logger.debug("deleteRolePermission with roleCsid=" + roleCsid);
ensureCSID(roleCsid, ServiceMessages.DELETE_FAILED + "permroles role ");
try {
+ Role role = (Role)get(roleCsid, Role.class);
+ // If marked as metadata immutable, do not delete
+ if(RoleClient.IMMUTABLE.equals(role.getPermsProtection())) {
+ Response response =
+ Response.status(Response.Status.FORBIDDEN).entity("Role: "+roleCsid+" is immutable.").type("text/plain").build();
+ return response;
+ }
PermissionRoleSubResource subResource =
new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
//delete all relationships for a permission
logger.debug("deleteRolePermission with roleCsid=" + roleCsid);
ensureCSID(roleCsid, ServiceMessages.DELETE_FAILED + "permroles role ");
try {
+ Role role = (Role)get(roleCsid, Role.class);
+ // If marked as metadata immutable, do not delete
+ if(RoleClient.IMMUTABLE.equals(role.getPermsProtection())) {
+ Response response =
+ Response.status(Response.Status.FORBIDDEN).entity("Role: "+roleCsid+" is immutable.").type("text/plain").build();
+ return response;
+ }
PermissionRoleSubResource subResource =
new PermissionRoleSubResource(PermissionRoleSubResource.ROLE_PERMROLE_SERVICE);
//delete all relationships for a permission
@Override
public void completeUpdate(DocumentWrapper<Permission> wrapDoc) throws Exception {
Permission upAcc = wrapDoc.getWrappedObject();
- getServiceContext().setOutput(permission);
+ getServiceContext().setOutput(upAcc);
sanitize(upAcc);
//FIXME update lower-layer authorization (acls)
//will require deleting old permissions for this resource and adding
import org.collectionspace.services.authorization.Role;
import org.collectionspace.services.authorization.RolesList;
+import org.collectionspace.services.client.RoleClient;
import org.collectionspace.services.common.document.BadRequestException;
import org.collectionspace.services.common.document.DocumentFilter;
import org.collectionspace.services.common.document.DocumentWrapper;
role.setRoleName(fixRoleName(role.getRoleName(),
role.getTenantId()));
role.setCsid(id);
+ // We do not allow creation of locked roles through the services.
+ role.setMetadataProtection(null);
+ role.setPermsProtection(null);
}
@Override
public void handleUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
Role roleFound = wrapDoc.getWrappedObject();
Role roleReceived = getCommonPart();
- roleReceived.setRoleName(fixRoleName(roleReceived.getRoleName(),
- roleFound.getTenantId()));
- merge(roleReceived, roleFound);
+ // If marked as metadata immutable, do not do update
+ if(!RoleClient.IMMUTABLE.equals(roleFound.getMetadataProtection())) {
+ roleReceived.setRoleName(fixRoleName(roleReceived.getRoleName(),
+ roleFound.getTenantId()));
+ merge(roleReceived, roleFound);
+ }
}
/**
if (from.getDescription() != null) {
to.setDescription(from.getDescription());
}
+ // Note that we do not allow update of locks
if (logger.isDebugEnabled()) {
logger.debug("merged role=" + JaxbUtils.toString(to, Role.class));
}
@Override
public void completeUpdate(DocumentWrapper<Role> wrapDoc) throws Exception {
Role upAcc = wrapDoc.getWrappedObject();
- getServiceContext().setOutput(role);
+ getServiceContext().setOutput(upAcc);
sanitize(upAcc);
}
</xs:appinfo>
</xs:annotation>
</xs:element>
+ <xs:element name="metadataProtection" type="xs:string" minOccurs="0" maxOccurs="1">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="metadata_protection" nullable="true"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="permsProtection" type="xs:string" minOccurs="0" maxOccurs="1">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="perms_protection" nullable="true"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
<xs:element name="createdAt" type="xs:dateTime">
<xs:annotation>
<xs:appinfo>
create table permissions (csid varchar(128) not null, action_group varchar(128), attribute_name varchar(128), created_at datetime not null, description varchar(255), effect varchar(32) not null, resource_name varchar(128) not null, tenant_id varchar(128) not null, updated_at datetime, primary key (csid));
create table permissions_actions (HJID bigint not null auto_increment, name varchar(128) not null, objectIdentity varchar(128) not null, objectIdentityResource varchar(128) not null, ACTIONS_PERMISSION_CSID varchar(128), primary key (HJID));
create table permissions_roles (HJID bigint not null auto_increment, actionGroup varchar(255), created_at datetime not null, permission_id varchar(128) not null, permission_resource varchar(255), role_id varchar(128) not null, role_name varchar(255), primary key (HJID), unique (permission_id, role_id));
-create table roles (csid varchar(128) not null, created_at datetime not null, description varchar(255), displayname varchar(200) not null, rolegroup varchar(255), rolename varchar(200) not null, tenant_id varchar(128) not null, updated_at datetime, primary key (csid), unique (rolename, tenant_id), unique (displayname, tenant_id));
+create table roles (csid varchar(128) not null, created_at datetime not null, description varchar(255), displayname varchar(200) not null, rolegroup varchar(255), rolename varchar(200) not null, tenant_id varchar(128) not null, metadata_protection varchar(255), perms_protection varchar(255), updated_at datetime, primary key (csid), unique (rolename, tenant_id), unique (displayname, tenant_id));
alter table permissions_actions add index FK85F82042E2DC84FD (ACTIONS_PERMISSION_CSID), add constraint FK85F82042E2DC84FD foreign key (ACTIONS_PERMISSION_CSID) references permissions (csid);
create table permissions (csid varchar(128) not null, action_group varchar(128), attribute_name varchar(128), created_at timestamp not null, description varchar(255), effect varchar(32) not null, resource_name varchar(128) not null, tenant_id varchar(128) not null, updated_at timestamp, primary key (csid));
create table permissions_actions (HJID int8 not null, name varchar(128) not null, objectIdentity varchar(128) not null, objectIdentityResource varchar(128) not null, ACTIONS_PERMISSION_CSID varchar(128), primary key (HJID));
create table permissions_roles (HJID int8 not null, actionGroup varchar(255), created_at timestamp not null, permission_id varchar(128) not null, permission_resource varchar(255), role_id varchar(128) not null, role_name varchar(255), primary key (HJID), unique (permission_id, role_id));
-create table roles (csid varchar(128) not null, created_at timestamp not null, description varchar(255), displayname varchar(200) not null, rolegroup varchar(255), rolename varchar(200) not null, tenant_id varchar(128) not null, updated_at timestamp, primary key (csid), unique (rolename, tenant_id), unique (displayname, tenant_id));
+create table roles (csid varchar(128) not null, created_at timestamp not null, description varchar(255), displayname varchar(200) not null, rolegroup varchar(255), rolename varchar(200) not null, tenant_id varchar(128) not null, metadata_protection varchar(255), perms_protection varchar(255), updated_at timestamp, primary key (csid), unique (rolename, tenant_id), unique (displayname, tenant_id));
alter table permissions_actions add constraint FK85F82042E2DC84FD foreign key (ACTIONS_PERMISSION_CSID) references permissions;
create sequence hibernate_sequence;
// then the accounts were as well\r
String insertAccountSQL = \r
"INSERT INTO accounts_common "\r
- + "(csid, email, userid, status, screen_name, created_at) "\r
- + "VALUES (?,?,?,'ACTIVE',?, now())";\r
+ + "(csid, email, userid, status, screen_name, metadata_protection, roles_protection, created_at) "\r
+ + "VALUES (?,?,?,'ACTIVE',?, 'immutable', 'immutable', now())";\r
Hashtable<String, String> tenantAdminAcctCSIDs = new Hashtable<String, String>();\r
Hashtable<String, String> tenantReaderAcctCSIDs = new Hashtable<String, String>();\r
pstmt = conn.prepareStatement(insertAccountSQL); // create a statement\r