+/**\r
+ * Copyright (C) 2011 EDIT\r
+ * European Distributed Institute of Taxonomy\r
+ * http://www.e-taxonomy.eu\r
+ *\r
+ * The contents of this file are subject to the Mozilla Public License Version 1.1\r
+ * See LICENSE.TXT at the top of this package for the full license terms.\r
+ */\r
package eu.etaxonomy.cdm.api.service;\r
\r
import static org.junit.Assert.assertEquals;\r
import static org.junit.Assert.assertFalse;\r
import static org.junit.Assert.assertTrue;\r
\r
-\r
-import java.util.ArrayList;\r
+import java.io.FileNotFoundException;\r
import java.util.Collection;\r
-import java.util.Iterator;\r
+import java.util.EnumSet;\r
+import java.util.HashSet;\r
import java.util.List;\r
import java.util.Set;\r
import java.util.UUID;\r
import javax.sql.DataSource;\r
\r
import org.apache.log4j.Logger;\r
-\r
import org.junit.Assert;\r
-import org.junit.Before;\r
import org.junit.Ignore;\r
import org.junit.Test;\r
-import org.junit.runner.RunWith;\r
-\r
-import org.springframework.beans.factory.annotation.Autowired;\r
-import org.springframework.security.access.vote.RoleVoter;\r
+import org.springframework.security.access.AccessDeniedException;\r
import org.springframework.security.authentication.AuthenticationManager;\r
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\r
-import org.springframework.security.authentication.dao.ReflectionSaltSource;\r
-import org.springframework.security.authentication.encoding.Md5PasswordEncoder;\r
+import org.springframework.security.authentication.dao.SaltSource;\r
+import org.springframework.security.authentication.encoding.PasswordEncoder;\r
import org.springframework.security.core.Authentication;\r
import org.springframework.security.core.GrantedAuthority;\r
import org.springframework.security.core.context.SecurityContext;\r
import org.springframework.security.core.context.SecurityContextHolder;\r
-import org.springframework.test.annotation.ExpectedException;\r
-import org.springframework.transaction.PlatformTransactionManager;\r
-\r
-\r
-import org.unitils.database.annotations.Transactional;\r
-import org.unitils.UnitilsJUnit4TestClassRunner;\r
import org.unitils.database.annotations.TestDataSource;\r
-import org.unitils.database.util.TransactionMode;\r
import org.unitils.dbunit.annotation.DataSet;\r
-import org.unitils.spring.annotation.SpringApplicationContext;\r
-import org.unitils.spring.annotation.SpringBeanByName;\r
+import org.unitils.spring.annotation.SpringBean;\r
import org.unitils.spring.annotation.SpringBeanByType;\r
\r
+import com.mchange.util.AssertException;\r
\r
-import eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator;\r
-import eu.etaxonomy.cdm.api.service.config.TaxonServiceConfiguratorImpl;\r
-import eu.etaxonomy.cdm.api.service.pager.Pager;\r
-import eu.etaxonomy.cdm.database.EvaluationFailedException;\r
-import eu.etaxonomy.cdm.model.common.Language;\r
+import sun.security.provider.PolicyParser.ParsingException;\r
+import eu.etaxonomy.cdm.database.PermissionDeniedException;\r
+import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;\r
import eu.etaxonomy.cdm.model.common.User;\r
-\r
-\r
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\r
-import eu.etaxonomy.cdm.model.description.Distribution;\r
import eu.etaxonomy.cdm.model.description.Feature;\r
import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
import eu.etaxonomy.cdm.model.description.TextData;\r
-\r
-import eu.etaxonomy.cdm.model.media.Media;\r
import eu.etaxonomy.cdm.model.name.BotanicalName;\r
import eu.etaxonomy.cdm.model.name.Rank;\r
+import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
+import eu.etaxonomy.cdm.model.name.ZoologicalName;\r
+import eu.etaxonomy.cdm.model.reference.Reference;\r
+import eu.etaxonomy.cdm.model.reference.ReferenceFactory;\r
+import eu.etaxonomy.cdm.model.taxon.Classification;\r
import eu.etaxonomy.cdm.model.taxon.Synonym;\r
-\r
import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;\r
import eu.etaxonomy.cdm.model.taxon.Taxon;\r
import eu.etaxonomy.cdm.model.taxon.TaxonBase;\r
import eu.etaxonomy.cdm.model.taxon.TaxonNode;\r
-import eu.etaxonomy.cdm.persistence.dao.BeanInitializer;\r
+import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;\r
+import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmAuthority;\r
+import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionClass;\r
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionEvaluator;\r
-import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTest;\r
-import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTestWithSecurity;\r
+import eu.etaxonomy.cdm.persistence.hibernate.permission.Operation;\r
+import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
\r
\r
+@DataSet\r
+public class SecurityTest extends AbstractSecurityTestBase{\r
\r
\r
-@RunWith(UnitilsJUnit4TestClassRunner.class)\r
-@Transactional(TransactionMode.DISABLED)\r
-@SpringApplicationContext({"/eu/etaxonomy/cdm/applicationContext-securityTest.xml"})\r
-@DataSet\r
-public class SecurityTest extends CdmTransactionalIntegrationTestWithSecurity{\r
-private static final Logger logger = Logger.getLogger(TaxonServiceImplTest.class);\r
+ private static final Logger logger = Logger.getLogger(SecurityTest.class);\r
+\r
+ @SpringBeanByType\r
+ private ITaxonService taxonService;\r
+\r
+ @SpringBeanByType\r
+ private INameService nameService;\r
+\r
+ @SpringBeanByType\r
+ private IReferenceService referenceService;\r
+\r
+ @SpringBeanByType\r
+ private ITaxonNodeService taxonNodeService;\r
+\r
+ @SpringBeanByType\r
+ private IDescriptionService descriptionService;\r
+\r
+ @SpringBeanByType\r
+ private IUserService userService;\r
+\r
+ @SpringBeanByType\r
+ private IClassificationService classificationService;\r
+\r
+ @SpringBeanByType\r
+ private AuthenticationManager authenticationManager;\r
+\r
+ @SpringBeanByType\r
+ private SaltSource saltSource;\r
+\r
+ @SpringBeanByType\r
+ private PasswordEncoder passwordEncoder;\r
+\r
+ @SpringBean("cdmPermissionEvaluator")\r
+ private CdmPermissionEvaluator permissionEvaluator;\r
+\r
+ @TestDataSource\r
+ protected DataSource dataSource;\r
+\r
+ private Authentication authentication;\r
+\r
+\r
+ /**\r
+ * no assertions in this test, since it is only used to create password hashes for test data\r
+ */\r
+ @Test\r
+ public void testEncryptPassword(){\r
+\r
+ String password = PASSWORD_ADMIN;\r
+ User user = User.NewInstance("userManager", "");\r
+\r
+ Object salt = this.saltSource.getSalt(user);\r
+ String passwordEncrypted = passwordEncoder.encodePassword(password, salt);\r
+ logger.info("encrypted password: " + passwordEncrypted );\r
+ }\r
+\r
+ @Test\r
+ @DataSet\r
+ public void testHasPermission(){\r
+\r
+ Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()),null);\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonomist);\r
+ boolean hasPermission = permissionEvaluator.hasPermission(authentication, taxon, Operation.UPDATE);\r
+ assertTrue(hasPermission);\r
+\r
+ authentication = authenticationManager.authenticate(tokenForDescriptionEditor);\r
+ hasPermission = permissionEvaluator.hasPermission(authentication, taxon, Operation.UPDATE);\r
+ assertFalse(hasPermission);\r
+ }\r
+\r
+ @Test\r
+ @DataSet\r
+ public void testListByUsernameAllow(){\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonomist);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ List<User> userList = userService.listByUsername("Editor", MatchMode.ANYWHERE, null, null, 0, null, null);\r
+ Assert.assertTrue("The user list must have elements", userList.size() > 0 );\r
+ }\r
+\r
+ @Test\r
+ @DataSet\r
+ public void testUserService_CreateDeny(){\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonomist);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ RuntimeException exception = null;\r
+ try {\r
+ userService.createUser(User.NewInstance("new guy", "alkjdsfalkj"));\r
+ commitAndStartNewTransaction(null);\r
+ } catch (AccessDeniedException e){\r
+ logger.debug("Expected failure of evaluation.", e);\r
+ exception = e;\r
+ } catch (RuntimeException e){\r
+ exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+ logger.debug("Expected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNotNull("Must fail here!", exception);\r
+\r
+ }\r
+\r
+ @Test\r
+ @DataSet\r
+ public void testUserService_CreateAllow(){\r
+\r
+ authentication = authenticationManager.authenticate(tokenForUserManager);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ RuntimeException exception = null;\r
+ try {\r
+ userService.createUser(User.NewInstance("new guy", "alkjdsfalkj"));\r
+ commitAndStartNewTransaction(null);\r
+ } catch (AccessDeniedException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = e;\r
+ } catch (RuntimeException e){\r
+ exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+ logger.error("unexpected failure of evaluation.", exception);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("Must not fail here!", exception);\r
+\r
+ }\r
+\r
+\r
+ @Test\r
+ @DataSet\r
+ @Ignore // FIXME http://dev.e-taxonomy.eu/trac/ticket/3098\r
+ public void testHasPermissions(){\r
+\r
+ Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()),null);\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonomist);\r
+ boolean hasPermission = permissionEvaluator.hasPermission(authentication, taxon, Operation.ALL);\r
+ assertTrue(hasPermission);\r
+ }\r
+\r
+\r
+ /**\r
+ * Test method for {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#saveTaxon(eu.etaxonomy.cdm.model.taxon.TaxonBase)}.\r
+ */\r
+ @Test\r
+ public final void testSaveTaxon() {\r
+\r
+ authentication = authenticationManager.authenticate(tokenForAdmin);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ Taxon expectedTaxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null);\r
+ expectedTaxon.getName().setTitleCache("Newby admin", true);\r
+ UUID uuid = taxonService.save(expectedTaxon);\r
+ commitAndStartNewTransaction(null);\r
+ TaxonBase<?> actualTaxon = taxonService.load(uuid);\r
+ assertEquals(expectedTaxon, actualTaxon);\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+ context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+ expectedTaxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()), null);\r
+ expectedTaxon.getName().setTitleCache("Newby taxonEditor", true);\r
+ uuid = taxonService.saveOrUpdate(expectedTaxon);\r
+ commitAndStartNewTransaction(null);\r
+ actualTaxon = taxonService.load(uuid);\r
+ assertEquals(expectedTaxon, actualTaxon);\r
+\r
+ }\r
+\r
+ @Test\r
+ public final void testSaveNameAllow() {\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ ZoologicalName newName = ZoologicalName.NewInstance(Rank.SPECIES());\r
+ newName.setTitleCache("Newby taxonEditor", true);\r
+ UUID uuid = nameService.saveOrUpdate(newName);\r
+ commitAndStartNewTransaction(null);\r
+ TaxonNameBase savedName = nameService.load(uuid);\r
+ assertEquals(newName, savedName);\r
+ }\r
+\r
+\r
+ @Test\r
+ public final void testReuseNameAllow() {\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ TaxonBase taxon = taxonService.find(UUID_ACHERONTIA_STYX);\r
+ TaxonNameBase n_acherontia_thetis = taxon.getName();\r
+\r
+ Taxon newTaxon = Taxon.NewInstance(n_acherontia_thetis, ReferenceFactory.newGeneric());\r
+ Exception exception = null;\r
+ try {\r
+ UUID uuid = taxonService.save(newTaxon);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (AccessDeniedException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = e;\r
+ } catch (RuntimeException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("must not fail here!", exception);\r
+ }\r
+\r
+ @Test\r
+ public final void testMakeTaxonNodeASynonymOfAnotherTaxonNodeAllow_1() {\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ Reference book = referenceService.load(BOOK1_UUID);\r
+\r
+ TaxonNode n_acherontia_styx = taxonNodeService.find(ACHERONTIA_STYX_NODE_UUID);\r
+ TaxonNode n_acherontia_lachersis = taxonNodeService.find(ACHERONTIA_LACHESIS_NODE_UUID);\r
+\r
+ Exception exception = null;\r
+ try {\r
+ taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_styx, n_acherontia_lachersis, SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF(), book , "33");\r
+ commitAndStartNewTransaction(null);\r
+ } catch (AccessDeniedException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = e;\r
+ } catch (RuntimeException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+ }finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("must not fail here!", exception);\r
+ }\r
+\r
+ @Test\r
+ public final void testMakeTaxonNodeASynonymOfAnotherTaxonNodeAllow_2() {\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ Reference book = referenceService.load(BOOK1_UUID);\r
+\r
+ TaxonNode n_acherontia_styx = taxonNodeService.find(ACHERONTIA_STYX_NODE_UUID);\r
+ TaxonNode n_acherontia_lachersis = taxonNodeService.find(ACHERONTIA_LACHESIS_NODE_UUID);\r
+\r
+ Exception exception = null;\r
+ try {\r
+ taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_lachersis, n_acherontia_styx, SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF(), book , "33");\r
+ commitAndStartNewTransaction(null);\r
+ } catch (AccessDeniedException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = e;\r
+ } catch (RuntimeException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("must not fail here!", exception);\r
+ }\r
+\r
+ @Test\r
+ public final void testUpdateReferenceAllow() throws ParsingException {\r
+\r
+\r
+ authentication = authenticationManager.authenticate(tokenForUserManager);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ // add REFERENCE[UPDATE] to taxonEditor\r
+ User taxonEditor = userService.load(TAXON_EDITOR_UUID);\r
+ Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();\r
+ grantedAuthorities.addAll(taxonEditor.getGrantedAuthorities());\r
+ GrantedAuthorityImpl referenceUpdate_ga = new CdmAuthority(CdmPermissionClass.REFERENCE, null, EnumSet.of(CRUD.UPDATE), null).asNewGrantedAuthority();\r
+ grantedAuthorities.add(referenceUpdate_ga);\r
+ taxonEditor.setGrantedAuthorities(grantedAuthorities);\r
+ userService.saveOrUpdate(taxonEditor);\r
+ commitAndStartNewTransaction(null);\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+ context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ Reference book = referenceService.load(BOOK1_UUID);\r
+ book.setTitleCache("Mobydick", true);\r
+ Exception exception = null;\r
+ try {\r
+ referenceService.saveOrUpdate(book);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (AccessDeniedException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = e;\r
+ } catch (RuntimeException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("must not fail here!", exception);\r
+ book = referenceService.load(BOOK1_UUID);\r
+ Assert.assertEquals("Mobydick", book.getTitleCache());\r
+ }\r
+\r
+ @Test\r
+ public final void testUpateReferenceDeny() {\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+\r
+ TaxonBase taxon = taxonService.find(UUID_ACHERONTIA_STYX);\r
+ taxon.getName().getNomenclaturalReference().setTitleCache("Mobydick", true);\r
+ Exception exception = null;\r
+ try {\r
+ UUID uuid = taxonService.saveOrUpdate(taxon);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (AccessDeniedException e){\r
+ logger.debug("Expected failure of evaluation.", e);\r
+ exception = e;\r
+ } catch (RuntimeException e){\r
+ exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+ logger.debug("Expected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNotNull("must fail here!", exception);\r
+ }\r
+\r
+ @Test\r
+ public void testChangeOwnPassword(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ // authenticate as admin\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+ context.setAuthentication(authentication);\r
+\r
+// User currentUser = (User) context.getAuthentication().getPrincipal();\r
+\r
+ String newPass = "poiweorijo";\r
+ userService.changePassword(PASSWORD_TAXON_EDITOR, newPass);\r
+ commitAndStartNewTransaction(null);\r
+\r
+ // try to re-authenticate user with changed password\r
+ UsernamePasswordAuthenticationToken newTokenForTaxonEditor = new UsernamePasswordAuthenticationToken("taxonEditor", newPass);\r
+ authentication = authenticationManager.authenticate(newTokenForTaxonEditor);\r
+ }\r
+\r
+ @Test\r
+ public void testChangeOthersPasswordAllow(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ RuntimeException exception = null;\r
+\r
+ // (1) authenticate as admin\r
+ authentication = authenticationManager.authenticate(tokenForAdmin);\r
+ context.setAuthentication(authentication);\r
+\r
+\r
+ try{\r
+ userService.changePasswordForUser("taxonomist", "zuaisd");\r
+ commitAndStartNewTransaction(null);\r
+ } catch (AccessDeniedException e){\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ exception = e;\r
+ } catch (RuntimeException e){\r
+ exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+ logger.error("Unexpected failure of evaluation.", exception);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("must not fail here!", exception);\r
+\r
+ // ok, now try authenticating taxonomist with new password\r
+ UsernamePasswordAuthenticationToken newToken = new UsernamePasswordAuthenticationToken("taxonomist", "zuaisd");\r
+ authentication = authenticationManager.authenticate(newToken);\r
+ }\r
+\r
+ @Test\r
+ public void testChangeOthersPasswordDeny(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ RuntimeException exception = null;\r
+\r
+ // (2) authenticate as under privileged user - not an admin !!!\r
+ authentication = authenticationManager.authenticate(tokenForDescriptionEditor);\r
+ context.setAuthentication(authentication);\r
+\r
+ // check test preconditions user name and authorities\r
+ Assert.assertEquals("descriptionEditor", context.getAuthentication().getName());\r
+ Collection<? extends GrantedAuthority> authorities = context.getAuthentication().getAuthorities();\r
+ for(GrantedAuthority authority: authorities){\r
+ // role prefix 'ROLE_' is defined in org.springframework.security.access.vote.RoleVoter !!!\r
+ Assert.assertNotSame("user must not have authority 'ROLE_ADMIN'", "ROLE_ADMIN", authority.getAuthority());\r
+ }\r
+ // finally perform the test :\r
+ try{\r
+ userService.changePasswordForUser("partEditor", "poiweorijo");\r
+ commitAndStartNewTransaction(null);\r
+ } catch (AccessDeniedException e){\r
+ logger.debug("Expected failure of evaluation.", e);\r
+ exception = e;\r
+ } catch (RuntimeException e){\r
+ exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+ logger.debug("Expected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNotNull("must fail here!", exception);\r
+ }\r
+\r
+ @Test\r
+ public void testUpdateUser(){\r
+\r
+ authentication = authenticationManager.authenticate(tokenForAdmin);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+ String username = "standardUser";\r
+ String password = "pw";\r
+ User user = User.NewInstance(username, password);\r
+\r
+ userService.createUser(user);\r
+ user.setEmailAddress("test@bgbm.org");\r
+\r
+ userService.updateUser(user);\r
+ userService.update(user);\r
+ userService.saveOrUpdate(user);\r
+ commitAndStartNewTransaction(null);\r
+\r
+ }\r
+\r
+ /**\r
+ * test with admin account - should succeed\r
+ */\r
+ @Test\r
+ public final void testTaxonSaveOrUpdateAllow_1() {\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+\r
+ authentication = authenticationManager.authenticate(tokenForAdmin);\r
+ context.setAuthentication(authentication);\r
+ RuntimeException securityException= null;\r
+\r
+ TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);\r
+ Assert.assertFalse(taxon.isDoubtful());\r
+ taxon.setDoubtful(true);\r
+ try{\r
+ taxonService.saveOrUpdate(taxon);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);\r
+ // reload taxon\r
+ taxon = taxonService.find(UUID_ACHERONTIA_STYX);\r
+ Assert.assertTrue("The change must be persisted", taxon.isDoubtful());\r
+ }\r
+\r
+ /**\r
+ * test with taxonEditor account - should succeed\r
+ */\r
+ @Test\r
+ public final void testTaxonSaveOrUpdateAllow_2() {\r
+\r
+\r
+ RuntimeException securityException= null;\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+\r
+ // taxonEditor account - should succeed\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+\r
+ context.setAuthentication(authentication);\r
+\r
+ TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);\r
+ Assert.assertFalse(taxon.isDoubtful());\r
+ taxon.setDoubtful(true);\r
+ try{\r
+ taxonService.saveOrUpdate(taxon);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);\r
+ // reload taxon\r
+ taxon = taxonService.find(UUID_ACHERONTIA_STYX);\r
+ Assert.assertTrue("The change must be persited", taxon.isDoubtful());\r
+ }\r
+\r
+ /**\r
+ * test with tokenForDescriptionEditor account - should fail\r
+ */\r
+ @Test\r
+ public final void testTaxonSaveOrUpdateDeny_2() {\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ RuntimeException securityException = null;\r
+\r
+ authentication = authenticationManager.authenticate(tokenForDescriptionEditor);\r
+ context.setAuthentication(authentication);\r
+\r
+ TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);\r
+\r
+ Assert.assertFalse(taxon.isDoubtful());\r
+ taxon.setDoubtful(true);\r
+ try {\r
+ taxonService.saveOrUpdate(taxon);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.debug("Expected failure of evaluation.", securityException);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+\r
+ Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);\r
+ // reload taxon\r
+ taxon = taxonService.find(UUID_ACHERONTIA_STYX);\r
+ Assert.assertFalse("The change must not be persited", taxon.isDoubtful());\r
+ }\r
+\r
+ @Test\r
+ public final void testTaxonPublishAllow_ROLE_ADMIN() {\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+\r
+ authentication = authenticationManager.authenticate(tokenForAdmin);\r
+ context.setAuthentication(authentication);\r
+ RuntimeException securityException= null;\r
+\r
+ Taxon taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);\r
+\r
+ boolean lastIsPublish = taxon.isPublish();\r
+ taxon.setPublish(!lastIsPublish);\r
+ try{\r
+ taxonService.saveOrUpdate(taxon);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("evaluation must not fail since the user has ROLE_ADMIN, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);\r
+ // reload taxon\r
+ taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);\r
+ Assert.assertTrue("The change must be persisted", taxon.isPublish() != lastIsPublish);\r
+ }\r
+\r
+\r
+ /**\r
+ * test with Taxonomist account which has the ROLE_PUBLISH\r
+ */\r
+ @Test\r
+ public final void testTaxonPublishAllow_ROLE_PUBLISH() {\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonomist);\r
+ context.setAuthentication(authentication);\r
+ RuntimeException securityException= null;\r
+\r
+ Taxon taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);\r
+\r
+ boolean lastIsPublish = taxon.isPublish();\r
+ taxon.setPublish(!lastIsPublish);\r
+ try{\r
+ taxonService.saveOrUpdate(taxon);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("evaluation must not fail since the user has ROLE_ADMIN, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);\r
+ // reload taxon\r
+ taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);\r
+ Assert.assertTrue("The change must be persisted", taxon.isPublish() != lastIsPublish);\r
+ }\r
+\r
+ /**\r
+ * test with TaxonEditor account which has not the ROLE_PUBLISH\r
+ */\r
+ @Test\r
+ public final void testTaxonPublishDeny() {\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+\r
+ authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+ context.setAuthentication(authentication);\r
+ RuntimeException securityException= null;\r
+\r
+ Taxon taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);\r
+\r
+ boolean lastIsPublish = taxon.isPublish();\r
+ taxon.setPublish(!lastIsPublish);\r
+ try {\r
+ taxonService.saveOrUpdate(taxon);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.debug("Expected failure of evaluation.", securityException);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+\r
+ Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);\r
+ // reload taxon\r
+ taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);\r
+ Assert.assertTrue("The taxon must be unchanged", taxon.isPublish() == lastIsPublish);\r
+ }\r
+\r
+ /**\r
+ * test with admin account - should succeed\r
+ */\r
+ @Test\r
+ public final void testTaxonDeleteAllow_1() {\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+\r
+ authentication = authenticationManager.authenticate(tokenForAdmin);\r
+ context.setAuthentication(authentication);\r
+ RuntimeException securityException= null;\r
+\r
+ TaxonBase<?> taxon = taxonService.load(UUID_LACTUCA);\r
+ taxonService.delete(taxon);\r
+ commitAndStartNewTransaction(null);\r
+ \r
+ \r
+ \r
+ \r
+ Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);\r
+ // reload taxon\r
+ taxon = taxonService.load(UUID_LACTUCA);\r
+ Assert.assertNull("The taxon must be deleted", taxon);\r
+ }\r
+\r
+ /**\r
+ * test with admin account - should succeed\r
+ */\r
+ @Test\r
+ public final void testTaxonDeleteAllow_2() {\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+\r
+ authentication = authenticationManager.authenticate(tokenForAdmin);\r
+ context.setAuthentication(authentication);\r
+ RuntimeException securityException= null;\r
+\r
+ Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);\r
+ try{\r
+ // try {\r
+ DeleteResult result = taxonService.deleteTaxon(taxon.getUuid(), null, null);\r
+ /*} catch (DataChangeNoRollbackException e) {\r
+ Assert.fail();\r
+ }*/\r
+ if (!result.isOk()){\r
+ Assert.fail();\r
+ }\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);\r
+ // reload taxon\r
+\r
+ taxon = (Taxon)taxonService.find(UUID_ACHERONTINII);\r
+ Assert.assertNull("The taxon must be deleted", taxon);\r
+ }\r
+\r
+\r
+ /**\r
+ * test with tokenForDescriptionEditor account - should fail\r
+ */\r
+ @Test\r
+ public final void testTaxonDeleteDeny() {\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ RuntimeException securityException = null;\r
+\r
+ authentication = authenticationManager.authenticate(tokenForDescriptionEditor);\r
+ context.setAuthentication(authentication);\r
+\r
+ Taxon taxon = (Taxon)taxonService.load(UUID_LACTUCA);\r
+ try{\r
+ DeleteResult result = taxonService.deleteTaxon(taxon.getUuid(), null, null);\r
+ Assert.fail();\r
+ }catch(PermissionDeniedException e){\r
+ \r
+ }\r
+ endTransaction();\r
+ startNewTransaction();\r
+ \r
+\r
+ //Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);\r
+ // reload taxon\r
+ taxon = (Taxon)taxonService.load(UUID_LACTUCA);\r
+ \r
+ Assert.assertNotNull("The change must still exist", taxon);\r
+ Assert.assertNotNull("The name must still exist",taxon.getName());\r
+ }\r
+\r
+\r
+ @Test\r
+ @Ignore //FIXME: adding taxa to a description must be protected at the side of the Description itself!!\r
+ // => protecting method TaxonDescription.setTaxon() ?\r
+ public void testAddDescriptionToTaxon(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ authentication = authenticationManager.authenticate(tokenForDescriptionEditor);\r
+ context.setAuthentication(authentication);\r
+\r
+ RuntimeException securityException = null;\r
+\r
+ Taxon taxon = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);\r
+\r
+ TaxonDescription description = TaxonDescription.NewInstance(taxon);\r
+ description.setTitleCache("test");\r
+ try {\r
+ descriptionService.saveOrUpdate(description);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.debug("Expected failure of evaluation.", securityException);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ /*\r
+ * Expectation:\r
+ * The user should not be granted to add the Description to a taxon\r
+ */\r
+ Assert.assertNotNull("evaluation should fail since the user is not permitted to edit Taxa", securityException);\r
+ taxon = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);\r
+ assertTrue(taxon.getDescriptions().contains(description));\r
+ }\r
+\r
+ @Test\r
+ public void testMoveDescriptionElement(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ authentication = authenticationManager.authenticate(tokenForTaxonomist);\r
+ context.setAuthentication(authentication);\r
+\r
+ RuntimeException securityException = null;\r
+\r
+ Taxon t_acherontia_lachesis = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);\r
+ Taxon t_acherontia_styx = (Taxon)taxonService.load(UUID_ACHERONTIA_STYX);\r
+\r
+ TaxonDescription description_acherontia_styx = t_acherontia_styx.getDescriptions().iterator().next();\r
+ TaxonDescription description_acherontia_lachesis = t_acherontia_lachesis.getDescriptions().iterator().next();\r
+\r
+ try {\r
+ descriptionService.moveDescriptionElementsToDescription(description_acherontia_styx.getElements(), description_acherontia_lachesis, false);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.debug("Unexpected failure of evaluation.", securityException);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ /*\r
+ * Expectation:\r
+ */\r
+ Assert.assertNull("evaluation should not fail since the user has sufficient permissions", securityException);\r
+\r
+ }\r
+\r
+// @Ignore // FIXME http://dev.e-taxonomy.eu/trac/ticket/4081 : #4081 (TaxonNodeServiceImpl.makeTaxonNodeASynonymOfAnotherTaxonNode() requires TAXONNAMEBASE.[UPDATE])\r
+ @Test\r
+ public void testAcceptedTaxonToSynomym(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ authentication = authenticationManager.authenticate(tokenForPartEditor);\r
+ context.setAuthentication(authentication);\r
+\r
+ RuntimeException securityException = null;\r
+\r
+ Taxon t_acherontia_lachesis = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);\r
+ UUID name_acherontia_lachesis_uuid = t_acherontia_lachesis.getName().getUuid();\r
+ Taxon t_acherontia_styx = (Taxon)taxonService.load(UUID_ACHERONTIA_STYX);\r
+ int countSynsBefore = t_acherontia_styx.getSynonyms().size();\r
+\r
+ TaxonNode n_acherontia_lachesis = t_acherontia_lachesis.getTaxonNodes().iterator().next();\r
+ TaxonNode n_acherontia_styx = t_acherontia_styx.getTaxonNodes().iterator().next();\r
+\r
+ int numOfSynonymsBefore_styx = t_acherontia_styx.getSynonyms().size();\r
+ int numOfSynonymsBefore_lachesis = t_acherontia_lachesis.getSynonyms().size();\r
+\r
+ \r
+ try {\r
+ DeleteResult result = taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_lachesis, n_acherontia_styx, SynonymRelationshipType.SYNONYM_OF(), null, null);\r
+// synonymUuid = synonym.getUuid();\r
+// taxonService.saveOrUpdate(synonym);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("Unexpected Exception ", e);\r
+ Assert.fail("Unexpected Exception: " + e.getMessage());\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ /*\r
+ * Expectation:\r
+ */\r
+ Assert.assertNull("evaluation should not fail since the user has sufficient permissions", securityException);\r
+\r
+ // reload from db and check assertions\r
+ t_acherontia_styx = (Taxon)taxonService.load(UUID_ACHERONTIA_STYX);\r
+ Assert.assertEquals(numOfSynonymsBefore_styx +1 + numOfSynonymsBefore_lachesis, t_acherontia_styx.getSynonyms().size());\r
+ \r
+ Assert.assertNotNull(nameService.load(name_acherontia_lachesis_uuid) );\r
+ Assert.assertNull("The old TaxonNode should no longer exist", taxonNodeService.find(n_acherontia_lachesis.getUuid()));\r
+ }\r
+\r
+ @Test\r
+ public void testCreateDescriptionWithElement(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ authentication = authenticationManager.authenticate(tokenForDescriptionEditor);\r
+ context.setAuthentication(authentication);\r
+\r
+ TaxonDescription description = null;\r
+ RuntimeException securityException = null;\r
+ Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);\r
+ Assert.assertTrue("taxon must not yet have descriptions", taxon.getDescriptions().size() == 0);\r
+\r
+\r
+ // 1) test for failure - description element but no feature\r
+ description = TaxonDescription.NewInstance(taxon);\r
+ DescriptionElementBase textdataNoFeature = TextData.NewInstance();\r
+ description.addElement(textdataNoFeature);\r
+\r
+ assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));\r
+ try{\r
+ descriptionService.saveOrUpdate(description);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("RuntimeException caught");\r
+ logger.debug("Expected failure of evaluation.", securityException);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+\r
+ Assert.assertNotNull("evaluation should fail", securityException);\r
+ taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);\r
+ Set<TaxonDescription> descriptions = taxon.getDescriptions();\r
+ assertTrue("taxon must not have any description", descriptions.size() == 0);\r
+\r
+ }\r
+\r
+ @Test\r
+ public void testCreateDescriptionWithElementDeny_1(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ authentication = authenticationManager.authenticate(tokenForDescriptionEditor);\r
+ context.setAuthentication(authentication);\r
+\r
+ TaxonDescription description = null;\r
+ RuntimeException securityException = null;\r
+ Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);\r
+ Assert.assertTrue("taxon must not yet have descriptions", taxon.getDescriptions().size() == 0);\r
+\r
+ // 2) test for failure - description element but not granted feature\r
+ description = TaxonDescription.NewInstance(taxon);\r
+ DescriptionElementBase descriptionText = TextData.NewInstance(Feature.DESCRIPTION());\r
+ description.addElement(descriptionText);\r
+\r
+ securityException = null;\r
+ assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));\r
+ try{\r
+ descriptionService.saveOrUpdate(description);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.debug("Expected failure of evaluation.", securityException);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+\r
+ Assert.assertNotNull("evaluation should fail", securityException);\r
+ taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);\r
+ Set<TaxonDescription> descriptions = taxon.getDescriptions();\r
+ assertTrue("taxon must not have any description", descriptions.size() == 0);\r
+\r
+ }\r
+\r
+ @Test\r
+ public void testCreateDescriptionWithElementDeny_2(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ authentication = authenticationManager.authenticate(tokenForDescriptionEditor);\r
+ context.setAuthentication(authentication);\r
+\r
+ TaxonDescription description = null;\r
+ RuntimeException securityException = null;\r
+ Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);\r
+ Assert.assertTrue("taxon must not yet have descriptions", taxon.getDescriptions().size() == 0);\r
+\r
+ // 3) test for failure\r
+ description = TaxonDescription.NewInstance(taxon);\r
+ DescriptionElementBase ecologyText = TextData.NewInstance(Feature.ECOLOGY());\r
+ description.addElement(ecologyText);\r
+\r
+ securityException = null;\r
+ assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));\r
+ try{\r
+ descriptionService.saveOrUpdate(description);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+\r
+ Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);\r
+ taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);\r
+ Set<TaxonDescription> descriptions = taxon.getDescriptions();\r
+ assertTrue("taxon must now have one description", descriptions.size() == 1);\r
+ assertTrue("description should have one description element", descriptions.iterator().next().getElements().size() == 1);\r
+ }\r
+\r
+ @Test\r
+ public void testSaveSynonymAllow(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ RuntimeException securityException = null;\r
+\r
+ // 1) test for success\r
+ authentication = authenticationManager.authenticate(tokenForTaxonomist);\r
+ context.setAuthentication(authentication);\r
+\r
+ Synonym syn = Synonym.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null);\r
+ UUID synUuid = UUID.randomUUID();\r
+ syn.setUuid(synUuid);\r
+ try{\r
+ taxonService.saveOrUpdate(syn);\r
+ logger.debug("will commit ...");\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("Unexpected failure of evaluation.", e);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+ Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);\r
+ Assert.assertNotNull("The new Synonym must be persited", taxonService.find(synUuid));\r
+ }\r
+\r
+ @Test\r
+ public void testSaveSynonymDenial(){\r
+\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ RuntimeException securityException = null;\r
+ // 2) test for denial\r
+ authentication = authenticationManager.authenticate(tokenForDescriptionEditor);\r
+ context.setAuthentication(authentication);\r
+ securityException = null;\r
+ Synonym syn = Synonym.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null);\r
+ UUID synUuid = syn.getUuid();\r
+ try{\r
+ taxonService.saveOrUpdate(syn);\r
+ logger.debug("will commit ...");\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.debug("Expected failure of evaluation: " + securityException.getClass());\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+\r
+ Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);\r
+ Assert.assertNull("The Synonym must not be persited", taxonService.find(synUuid));\r
+ }\r
+\r
+ @Test\r
+ public void testEditPartOfClassificationAllow(){\r
+\r
+ authentication = authenticationManager.authenticate(tokenForPartEditor);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+ RuntimeException securityException = null;\r
+ Classification classification = classificationService.load(UUID.fromString("aeee7448-5298-4991-b724-8d5b75a0a7a9"));\r
+ // test for success\r
+ TaxonNode acherontia_node = taxonNodeService.load(ACHERONTIA_NODE_UUID);\r
+ long numOfChildNodes = acherontia_node.getChildNodes().size();\r
+ TaxonNode childNode = acherontia_node.addChildTaxon(Taxon.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null), null, null);\r
+\r
+ try{\r
+ taxonNodeService.saveOrUpdate(acherontia_node);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.error("Unexpected failure of evaluation.", securityException);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+\r
+ acherontia_node = taxonNodeService.load(ACHERONTIA_NODE_UUID);\r
+ Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);\r
+ Assert.assertEquals("the acherontia_node must now have one more child node ", numOfChildNodes + 1 , acherontia_node.getChildNodes().size());\r
+ }\r
+\r
+ @Test\r
+ public void testEditPartOfClassificationDeny(){\r
+\r
+ authentication = authenticationManager.authenticate(tokenForPartEditor);\r
+ SecurityContext context = SecurityContextHolder.getContext();\r
+ context.setAuthentication(authentication);\r
+ RuntimeException securityException = null;\r
+\r
+ // test for denial\r
+ securityException = null;\r
+ TaxonNode acherontiini_node = taxonNodeService.load(ACHERONTIINI_NODE_UUID);\r
+ int numOfChildNodes = acherontiini_node.getCountChildren();\r
+ acherontiini_node.addChildTaxon(Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()), null), null, null);\r
+\r
+ try{\r
+ logger.debug("==============================");\r
+ taxonNodeService.saveOrUpdate(acherontiini_node);\r
+ commitAndStartNewTransaction(null);\r
+ } catch (RuntimeException e){\r
+ securityException = findSecurityRuntimeException(e);\r
+ logger.debug("Expected failure of evaluation.", securityException);\r
+ } finally {\r
+ // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+ // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+ endTransaction();\r
+ startNewTransaction();\r
+ }\r
+\r
+ acherontiini_node = taxonNodeService.load(ACHERONTIINI_NODE_UUID);\r
+ Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);\r
+ Assert.assertEquals("the number of child nodes must be unchanged ", numOfChildNodes , acherontiini_node.getChildNodes().size());\r
+\r
+ }\r
+\r
+ /* (non-Javadoc)\r
+ * @see eu.etaxonomy.cdm.test.integration.CdmIntegrationTest#createTestData()\r
+ */\r
+ @Override\r
+ public void createTestDataSet() throws FileNotFoundException {\r
+ // TODO Auto-generated method stub\r
+ \r
+ }\r
\r
-/**\r
- * The transaction manager to use\r
- */\r
-@SpringBeanByType\r
-PlatformTransactionManager transactionManager;\r
- \r
- @SpringBeanByType\r
- private ITaxonService taxonService;\r
-\r
- @SpringBeanByType\r
- private ITaxonNodeService taxonNodeService;\r
- \r
- @SpringBeanByType\r
- private IDescriptionService descriptionService;\r
- \r
- @SpringBeanByType\r
- private IUserService userService;\r
- \r
- \r
- @TestDataSource\r
- protected DataSource dataSource;\r
- \r
- private Authentication authentication;\r
- \r
- @SpringBeanByType\r
- private AuthenticationManager authenticationManager;\r
- \r
- \r
- \r
- private UsernamePasswordAuthenticationToken token;\r
- \r
- \r
- @Before\r
- public void setUp(){\r
- token = new UsernamePasswordAuthenticationToken("ben", "sPePhAz6");\r
- }\r
- \r
- \r
- /**\r
- * Test method for {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#saveTaxon(eu.etaxonomy.cdm.model.taxon.TaxonBase)}.\r
- */\r
- @Test\r
- public final void testSaveTaxon() {\r
- /*\r
- Md5PasswordEncoder encoder =new Md5PasswordEncoder();\r
- ReflectionSaltSource saltSource = new ReflectionSaltSource();\r
- saltSource.setUserPropertyToUse("getUsername");\r
- User user = User.NewInstance("partEditor", "test4");\r
- System.err.println(encoder.encodePassword("test4", saltSource.getSalt(user)));\r
- \r
- */\r
- authentication = authenticationManager.authenticate(token);\r
- SecurityContext context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- \r
- Taxon expectedTaxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null);\r
- UUID uuid = taxonService.save(expectedTaxon);\r
- //taxonService.getSession().flush();\r
- TaxonBase<?> actualTaxon = taxonService.load(uuid);\r
- assertEquals(expectedTaxon, actualTaxon);\r
- \r
- token = new UsernamePasswordAuthenticationToken("taxonEditor", "test2");\r
- authentication = authenticationManager.authenticate(token);\r
- context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- expectedTaxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()), null);\r
- taxonService.saveOrUpdate(actualTaxon);\r
- \r
- \r
- }\r
- @Test\r
- public void testUpdateUser(){\r
- \r
- authentication = authenticationManager.authenticate(token);\r
- SecurityContext context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- String username = "standardUser";\r
- String password = "pw";\r
- User user = User.NewInstance(username, password);\r
- \r
- userService.createUser(user);\r
- user.setEmailAddress("test@bgbm.org");\r
- \r
- userService.updateUser(user);\r
- userService.update(user);\r
- userService.saveOrUpdate(user);\r
- }\r
- \r
- @Test\r
- public final void testSaveOrUpdateTaxon() {\r
- authentication = authenticationManager.authenticate(token);\r
- SecurityContext context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- Taxon expectedTaxon = Taxon.NewInstance(null, null);\r
- UUID uuid = taxonService.save(expectedTaxon);\r
- TaxonBase<?> actualTaxon = taxonService.load(uuid);\r
- assertEquals(expectedTaxon, actualTaxon);\r
- \r
- actualTaxon.setName(BotanicalName.NewInstance(Rank.SPECIES()));\r
- taxonService.saveOrUpdate(actualTaxon);\r
- \r
- token = new UsernamePasswordAuthenticationToken("taxonEditor", "test2");\r
- authentication = authenticationManager.authenticate(token);\r
- context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- actualTaxon = taxonService.load(uuid);\r
- \r
- actualTaxon.setDoubtful(true);\r
- taxonService.saveOrUpdate(actualTaxon);\r
- \r
- }\r
- \r
- \r
- \r
- @Test\r
- public void testCascadingInSpringSecurityAccesDenied(){\r
- /*authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("partEditor", "test4"));\r
- SecurityContext context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- */\r
- \r
- authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("taxonEditor", "test2"));\r
- SecurityContext context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- CdmPermissionEvaluator permissionEvaluator = new CdmPermissionEvaluator();\r
- \r
- Taxon taxon =(Taxon) taxonService.load(UUID.fromString("bc09aca6-06fd-4905-b1e7-cbf7cc65d783"));\r
- taxon.setDoubtful(false);\r
- assertTrue(permissionEvaluator.hasPermission(authentication, taxon, "UPDATE"));\r
- taxonService.save(taxon);\r
- taxon = null;\r
- commitAndStartNewTransaction(null);\r
- \r
- //during cascading the permissions are not evaluated, but with hibernate listener every database transaction can be interrupted, but how to manage it, \r
- //when someone has the rights to save descriptions, but not taxa (the editor always saves everything by saving the taxon)\r
- //taxonService.saveOrUpdate(taxon);\r
- \r
- \r
- authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("descriptionEditor", "test"));\r
- context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- \r
- //taxonService.saveOrUpdate(taxon);\r
- \r
- taxon =(Taxon) taxonService.load(UUID.fromString("bc09aca6-06fd-4905-b1e7-cbf7cc65d783")); \r
- \r
- TaxonDescription description = TaxonDescription.NewInstance(taxon);\r
- description.setTitleCache("test");\r
- descriptionService.saveOrUpdate(description);\r
- commitAndStartNewTransaction(null);\r
- taxon = (Taxon)taxonService.load(UUID.fromString("bc09aca6-06fd-4905-b1e7-cbf7cc65d783"));\r
- assertTrue(taxon.getDescriptions().contains(description));\r
- \r
- \r
- \r
- }\r
- \r
- @Test\r
- public void testCascadingInSpring(){\r
- authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("descriptionEditor", "test"));\r
- SecurityContext context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- \r
- Taxon taxon = (Taxon)taxonService.load(UUID.fromString("928a0167-98cd-4555-bf72-52116d067625"));\r
- TaxonDescription description = TaxonDescription.NewInstance(taxon);\r
- description.addElement(Distribution.NewInstance());\r
- CdmPermissionEvaluator permissionEvaluator = new CdmPermissionEvaluator();\r
- assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));\r
- \r
- descriptionService.saveOrUpdate(description);\r
- \r
- taxon = (Taxon)taxonService.load(UUID.fromString("928a0167-98cd-4555-bf72-52116d067625"));\r
- Set<TaxonDescription> descriptions = taxon.getDescriptions();\r
- assertTrue(descriptions.contains(description));\r
- \r
- \r
- }\r
- \r
- @Test\r
- public void testSaveSynonym(){\r
- authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("taxonomist", "test4"));\r
- SecurityContext context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- \r
- Synonym syn = Synonym.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null);\r
- taxonService.saveOrUpdate(syn);\r
- \r
- }\r
- \r
- @Test(expected= EvaluationFailedException.class)\r
- public void testEditPartOfClassification(){\r
- \r
- \r
- authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("partEditor", "test4"));\r
- SecurityContext context = SecurityContextHolder.getContext();\r
- context.setAuthentication(authentication);\r
- \r
- TaxonNode node = taxonNodeService.load(UUID.fromString("20c8f083-5870-4cbd-bf56-c5b2b98ab6a7"));\r
- \r
- node = node.addChildTaxon(Taxon.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null), null, null, null);\r
- taxonNodeService.saveOrUpdate(node);\r
- \r
- node = taxonNodeService.load(UUID.fromString("cecfa77f-f26a-4476-9d87-a8d993cb55d9"));\r
- node = node.addChildTaxon(Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()), null), null, null, null);\r
- taxonNodeService.saveOrUpdate(node);\r
- \r
- }\r
- \r
- public static void main(String[] args){\r
- Md5PasswordEncoder encoder =new Md5PasswordEncoder();\r
- \r
- ReflectionSaltSource saltSource = new ReflectionSaltSource();\r
- saltSource.setUserPropertyToUse("getUsername");\r
- User user = User.NewInstance("taxonomist", "test4");\r
- System.err.println(encoder.encodePassword("test4", saltSource.getSalt(user)));\r
- }\r
- \r
- \r
- \r
- \r
}\r