2 * Copyright (C) 2011 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.api
.service
;
11 import static org
.junit
.Assert
.assertEquals
;
12 import static org
.junit
.Assert
.assertFalse
;
13 import static org
.junit
.Assert
.assertTrue
;
15 import java
.util
.Collection
;
16 import java
.util
.EnumSet
;
17 import java
.util
.HashSet
;
18 import java
.util
.List
;
20 import java
.util
.UUID
;
22 import javax
.sql
.DataSource
;
24 import org
.apache
.log4j
.Logger
;
25 import org
.junit
.Assert
;
26 import org
.junit
.Ignore
;
27 import org
.junit
.Test
;
28 import org
.springframework
.security
.access
.AccessDeniedException
;
29 import org
.springframework
.security
.authentication
.AuthenticationManager
;
30 import org
.springframework
.security
.authentication
.UsernamePasswordAuthenticationToken
;
31 import org
.springframework
.security
.authentication
.dao
.SaltSource
;
32 import org
.springframework
.security
.authentication
.encoding
.PasswordEncoder
;
33 import org
.springframework
.security
.core
.Authentication
;
34 import org
.springframework
.security
.core
.GrantedAuthority
;
35 import org
.springframework
.security
.core
.context
.SecurityContext
;
36 import org
.springframework
.security
.core
.context
.SecurityContextHolder
;
37 import org
.springframework
.transaction
.PlatformTransactionManager
;
38 import org
.unitils
.database
.annotations
.TestDataSource
;
39 import org
.unitils
.dbunit
.annotation
.DataSet
;
40 import org
.unitils
.spring
.annotation
.SpringBean
;
41 import org
.unitils
.spring
.annotation
.SpringBeanByType
;
43 import sun
.security
.provider
.PolicyParser
.ParsingException
;
44 import eu
.etaxonomy
.cdm
.api
.service
.DeleteResult
.DeleteStatus
;
45 import eu
.etaxonomy
.cdm
.api
.service
.exception
.DataChangeNoRollbackException
;
46 import eu
.etaxonomy
.cdm
.api
.service
.exception
.ReferencedObjectUndeletableException
;
47 import eu
.etaxonomy
.cdm
.database
.PermissionDeniedException
;
48 import eu
.etaxonomy
.cdm
.model
.common
.GrantedAuthorityImpl
;
49 import eu
.etaxonomy
.cdm
.model
.common
.User
;
50 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
51 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
52 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
53 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
54 import eu
.etaxonomy
.cdm
.model
.name
.BotanicalName
;
55 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
56 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
57 import eu
.etaxonomy
.cdm
.model
.name
.ZoologicalName
;
58 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
59 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceFactory
;
60 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
61 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
62 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
63 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
64 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
65 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
66 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CRUD
;
67 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CdmAuthority
;
68 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CdmPermissionClass
;
69 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.CdmPermissionEvaluator
;
70 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.permission
.Operation
;
71 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
75 public class SecurityTest
extends AbstractSecurityTestBase
{
78 private static final Logger logger
= Logger
.getLogger(SecurityTest
.class);
81 private ITaxonService taxonService
;
84 private INameService nameService
;
87 private IReferenceService referenceService
;
90 private ITaxonNodeService taxonNodeService
;
93 private IDescriptionService descriptionService
;
96 private IUserService userService
;
99 private IClassificationService classificationService
;
102 private AuthenticationManager authenticationManager
;
105 private SaltSource saltSource
;
108 private PasswordEncoder passwordEncoder
;
110 @SpringBean("cdmPermissionEvaluator")
111 private CdmPermissionEvaluator permissionEvaluator
;
114 protected DataSource dataSource
;
116 private Authentication authentication
;
120 * no assertions in this test, since it is only used to create password hashes for test data
123 public void testEncryptPassword(){
125 String password
= PASSWORD_ADMIN
;
126 User user
= User
.NewInstance("userManager", "");
128 Object salt
= this.saltSource
.getSalt(user
);
129 String passwordEncrypted
= passwordEncoder
.encodePassword(password
, salt
);
130 logger
.info("encrypted password: " + passwordEncrypted
);
135 public void testHasPermission(){
137 Taxon taxon
= Taxon
.NewInstance(BotanicalName
.NewInstance(Rank
.GENUS()),null);
139 authentication
= authenticationManager
.authenticate(tokenForTaxonomist
);
140 boolean hasPermission
= permissionEvaluator
.hasPermission(authentication
, taxon
, Operation
.UPDATE
);
141 assertTrue(hasPermission
);
143 authentication
= authenticationManager
.authenticate(tokenForDescriptionEditor
);
144 hasPermission
= permissionEvaluator
.hasPermission(authentication
, taxon
, Operation
.UPDATE
);
145 assertFalse(hasPermission
);
150 public void testListByUsernameAllow(){
152 authentication
= authenticationManager
.authenticate(tokenForTaxonomist
);
153 SecurityContext context
= SecurityContextHolder
.getContext();
154 context
.setAuthentication(authentication
);
156 List
<User
> userList
= userService
.listByUsername("Editor", MatchMode
.ANYWHERE
, null, null, 0, null, null);
157 Assert
.assertTrue("The user list must have elements", userList
.size() > 0 );
162 public void testUserService_CreateDeny(){
164 authentication
= authenticationManager
.authenticate(tokenForTaxonomist
);
165 SecurityContext context
= SecurityContextHolder
.getContext();
166 context
.setAuthentication(authentication
);
168 RuntimeException exception
= null;
170 userService
.createUser(User
.NewInstance("new guy", "alkjdsfalkj"));
171 commitAndStartNewTransaction(null);
172 } catch (AccessDeniedException e
){
173 logger
.debug("Expected failure of evaluation.", e
);
175 } catch (RuntimeException e
){
176 exception
= findThrowableOfTypeIn(PermissionDeniedException
.class, e
);
177 logger
.debug("Expected failure of evaluation.", e
);
179 // needed in case saveOrUpdate was interrupted by the RuntimeException
180 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
182 startNewTransaction();
184 Assert
.assertNotNull("Must fail here!", exception
);
190 public void testUserService_CreateAllow(){
192 authentication
= authenticationManager
.authenticate(tokenForUserManager
);
193 SecurityContext context
= SecurityContextHolder
.getContext();
194 context
.setAuthentication(authentication
);
196 RuntimeException exception
= null;
198 userService
.createUser(User
.NewInstance("new guy", "alkjdsfalkj"));
199 commitAndStartNewTransaction(null);
200 } catch (AccessDeniedException e
){
201 logger
.error("Unexpected failure of evaluation.", e
);
203 } catch (RuntimeException e
){
204 exception
= findThrowableOfTypeIn(PermissionDeniedException
.class, e
);
205 logger
.error("unexpected failure of evaluation.", exception
);
207 // needed in case saveOrUpdate was interrupted by the RuntimeException
208 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
210 startNewTransaction();
212 Assert
.assertNull("Must not fail here!", exception
);
219 @Ignore // FIXME http://dev.e-taxonomy.eu/trac/ticket/3098
220 public void testHasPermissions(){
222 Taxon taxon
= Taxon
.NewInstance(BotanicalName
.NewInstance(Rank
.GENUS()),null);
224 authentication
= authenticationManager
.authenticate(tokenForTaxonomist
);
225 boolean hasPermission
= permissionEvaluator
.hasPermission(authentication
, taxon
, Operation
.ALL
);
226 assertTrue(hasPermission
);
231 * Test method for {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#saveTaxon(eu.etaxonomy.cdm.model.taxon.TaxonBase)}.
234 public final void testSaveTaxon() {
236 authentication
= authenticationManager
.authenticate(tokenForAdmin
);
237 SecurityContext context
= SecurityContextHolder
.getContext();
238 context
.setAuthentication(authentication
);
240 Taxon expectedTaxon
= Taxon
.NewInstance(BotanicalName
.NewInstance(Rank
.SPECIES()), null);
241 expectedTaxon
.getName().setTitleCache("Newby admin", true);
242 UUID uuid
= taxonService
.save(expectedTaxon
);
243 commitAndStartNewTransaction(null);
244 TaxonBase
<?
> actualTaxon
= taxonService
.load(uuid
);
245 assertEquals(expectedTaxon
, actualTaxon
);
247 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
248 context
= SecurityContextHolder
.getContext();
249 context
.setAuthentication(authentication
);
250 expectedTaxon
= Taxon
.NewInstance(BotanicalName
.NewInstance(Rank
.GENUS()), null);
251 expectedTaxon
.getName().setTitleCache("Newby taxonEditor", true);
252 uuid
= taxonService
.saveOrUpdate(expectedTaxon
);
253 commitAndStartNewTransaction(null);
254 actualTaxon
= taxonService
.load(uuid
);
255 assertEquals(expectedTaxon
, actualTaxon
);
260 public final void testSaveNameAllow() {
262 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
263 SecurityContext context
= SecurityContextHolder
.getContext();
264 context
.setAuthentication(authentication
);
266 ZoologicalName newName
= ZoologicalName
.NewInstance(Rank
.SPECIES());
267 newName
.setTitleCache("Newby taxonEditor", true);
268 UUID uuid
= nameService
.saveOrUpdate(newName
);
269 commitAndStartNewTransaction(null);
270 TaxonNameBase savedName
= nameService
.load(uuid
);
271 assertEquals(newName
, savedName
);
276 public final void testReuseNameAllow() {
278 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
279 SecurityContext context
= SecurityContextHolder
.getContext();
280 context
.setAuthentication(authentication
);
282 TaxonBase taxon
= taxonService
.find(UUID_ACHERONTIA_STYX
);
283 TaxonNameBase n_acherontia_thetis
= taxon
.getName();
285 Taxon newTaxon
= Taxon
.NewInstance(n_acherontia_thetis
, ReferenceFactory
.newGeneric());
286 Exception exception
= null;
288 UUID uuid
= taxonService
.save(newTaxon
);
289 commitAndStartNewTransaction(null);
290 } catch (AccessDeniedException e
){
291 logger
.error("Unexpected failure of evaluation.", e
);
293 } catch (RuntimeException e
){
294 logger
.error("Unexpected failure of evaluation.", e
);
295 exception
= findThrowableOfTypeIn(PermissionDeniedException
.class, e
);
297 // needed in case saveOrUpdate was interrupted by the RuntimeException
298 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
300 startNewTransaction();
302 Assert
.assertNull("must not fail here!", exception
);
306 public final void testMakeTaxonNodeASynonymOfAnotherTaxonNodeAllow_1() {
308 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
309 SecurityContext context
= SecurityContextHolder
.getContext();
310 context
.setAuthentication(authentication
);
312 Reference book
= referenceService
.load(BOOK1_UUID
);
314 TaxonNode n_acherontia_styx
= taxonNodeService
.find(ACHERONTIA_STYX_NODE_UUID
);
315 TaxonNode n_acherontia_lachersis
= taxonNodeService
.find(ACHERONTIA_LACHESIS_NODE_UUID
);
317 Exception exception
= null;
319 taxonNodeService
.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_styx
, n_acherontia_lachersis
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), book
, "33");
320 commitAndStartNewTransaction(null);
321 } catch (AccessDeniedException e
){
322 logger
.error("Unexpected failure of evaluation.", e
);
324 } catch (RuntimeException e
){
325 logger
.error("Unexpected failure of evaluation.", e
);
326 exception
= findThrowableOfTypeIn(PermissionDeniedException
.class, e
);
328 // needed in case saveOrUpdate was interrupted by the RuntimeException
329 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
331 startNewTransaction();
333 Assert
.assertNull("must not fail here!", exception
);
337 public final void testMakeTaxonNodeASynonymOfAnotherTaxonNodeAllow_2() {
339 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
340 SecurityContext context
= SecurityContextHolder
.getContext();
341 context
.setAuthentication(authentication
);
343 Reference book
= referenceService
.load(BOOK1_UUID
);
345 TaxonNode n_acherontia_styx
= taxonNodeService
.find(ACHERONTIA_STYX_NODE_UUID
);
346 TaxonNode n_acherontia_lachersis
= taxonNodeService
.find(ACHERONTIA_LACHESIS_NODE_UUID
);
348 Exception exception
= null;
350 taxonNodeService
.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_lachersis
, n_acherontia_styx
, SynonymRelationshipType
.HOMOTYPIC_SYNONYM_OF(), book
, "33");
351 commitAndStartNewTransaction(null);
352 } catch (AccessDeniedException e
){
353 logger
.error("Unexpected failure of evaluation.", e
);
355 } catch (RuntimeException e
){
356 logger
.error("Unexpected failure of evaluation.", e
);
357 exception
= findThrowableOfTypeIn(PermissionDeniedException
.class, e
);
359 // needed in case saveOrUpdate was interrupted by the RuntimeException
360 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
362 startNewTransaction();
364 Assert
.assertNull("must not fail here!", exception
);
368 public final void testUpdateReferenceAllow() throws ParsingException
{
371 authentication
= authenticationManager
.authenticate(tokenForUserManager
);
372 SecurityContext context
= SecurityContextHolder
.getContext();
373 context
.setAuthentication(authentication
);
375 // add REFERENCE[UPDATE] to taxonEditor
376 User taxonEditor
= userService
.load(TAXON_EDITOR_UUID
);
377 Set
<GrantedAuthority
> grantedAuthorities
= new HashSet
<GrantedAuthority
>();
378 grantedAuthorities
.addAll(taxonEditor
.getGrantedAuthorities());
379 GrantedAuthorityImpl referenceUpdate_ga
= new CdmAuthority(CdmPermissionClass
.REFERENCE
, null, EnumSet
.of(CRUD
.UPDATE
), null).asNewGrantedAuthority();
380 grantedAuthorities
.add(referenceUpdate_ga
);
381 taxonEditor
.setGrantedAuthorities(grantedAuthorities
);
382 userService
.saveOrUpdate(taxonEditor
);
383 commitAndStartNewTransaction(null);
385 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
386 context
= SecurityContextHolder
.getContext();
387 context
.setAuthentication(authentication
);
389 Reference book
= referenceService
.load(BOOK1_UUID
);
390 book
.setTitleCache("Mobydick", true);
391 Exception exception
= null;
393 referenceService
.saveOrUpdate(book
);
394 commitAndStartNewTransaction(null);
395 } catch (AccessDeniedException e
){
396 logger
.error("Unexpected failure of evaluation.", e
);
398 } catch (RuntimeException e
){
399 logger
.error("Unexpected failure of evaluation.", e
);
400 exception
= findThrowableOfTypeIn(PermissionDeniedException
.class, e
);
402 // needed in case saveOrUpdate was interrupted by the RuntimeException
403 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
405 startNewTransaction();
407 Assert
.assertNull("must not fail here!", exception
);
408 book
= referenceService
.load(BOOK1_UUID
);
409 Assert
.assertEquals("Mobydick", book
.getTitleCache());
413 public final void testUpateReferenceDeny() {
415 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
416 SecurityContext context
= SecurityContextHolder
.getContext();
417 context
.setAuthentication(authentication
);
419 TaxonBase taxon
= taxonService
.find(UUID_ACHERONTIA_STYX
);
420 taxon
.getName().getNomenclaturalReference().setTitleCache("Mobydick", true);
421 Exception exception
= null;
423 UUID uuid
= taxonService
.saveOrUpdate(taxon
);
424 commitAndStartNewTransaction(null);
425 } catch (AccessDeniedException e
){
426 logger
.debug("Expected failure of evaluation.", e
);
428 } catch (RuntimeException e
){
429 exception
= findThrowableOfTypeIn(PermissionDeniedException
.class, e
);
430 logger
.debug("Expected failure of evaluation.", e
);
432 // needed in case saveOrUpdate was interrupted by the RuntimeException
433 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
435 startNewTransaction();
437 Assert
.assertNotNull("must fail here!", exception
);
441 public void testChangeOwnPassword(){
443 SecurityContext context
= SecurityContextHolder
.getContext();
444 // authenticate as admin
445 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
446 context
.setAuthentication(authentication
);
448 // User currentUser = (User) context.getAuthentication().getPrincipal();
450 String newPass
= "poiweorijo";
451 userService
.changePassword(PASSWORD_TAXON_EDITOR
, newPass
);
452 commitAndStartNewTransaction(null);
454 // try to re-authenticate user with changed password
455 UsernamePasswordAuthenticationToken newTokenForTaxonEditor
= new UsernamePasswordAuthenticationToken("taxonEditor", newPass
);
456 authentication
= authenticationManager
.authenticate(newTokenForTaxonEditor
);
460 public void testChangeOthersPasswordAllow(){
462 SecurityContext context
= SecurityContextHolder
.getContext();
463 RuntimeException exception
= null;
465 // (1) authenticate as admin
466 authentication
= authenticationManager
.authenticate(tokenForAdmin
);
467 context
.setAuthentication(authentication
);
471 userService
.changePasswordForUser("taxonomist", "zuaisd");
472 commitAndStartNewTransaction(null);
473 } catch (AccessDeniedException e
){
474 logger
.error("Unexpected failure of evaluation.", e
);
476 } catch (RuntimeException e
){
477 exception
= findThrowableOfTypeIn(PermissionDeniedException
.class, e
);
478 logger
.error("Unexpected failure of evaluation.", exception
);
480 // needed in case saveOrUpdate was interrupted by the RuntimeException
481 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
483 startNewTransaction();
485 Assert
.assertNull("must not fail here!", exception
);
487 // ok, now try authenticating taxonomist with new password
488 UsernamePasswordAuthenticationToken newToken
= new UsernamePasswordAuthenticationToken("taxonomist", "zuaisd");
489 authentication
= authenticationManager
.authenticate(newToken
);
493 public void testChangeOthersPasswordDeny(){
495 SecurityContext context
= SecurityContextHolder
.getContext();
496 RuntimeException exception
= null;
498 // (2) authenticate as under privileged user - not an admin !!!
499 authentication
= authenticationManager
.authenticate(tokenForDescriptionEditor
);
500 context
.setAuthentication(authentication
);
502 // check test preconditions user name and authorities
503 Assert
.assertEquals("descriptionEditor", context
.getAuthentication().getName());
504 Collection
<?
extends GrantedAuthority
> authorities
= context
.getAuthentication().getAuthorities();
505 for(GrantedAuthority authority
: authorities
){
506 // role prefix 'ROLE_' is defined in org.springframework.security.access.vote.RoleVoter !!!
507 Assert
.assertNotSame("user must not have authority 'ROLE_ADMIN'", "ROLE_ADMIN", authority
.getAuthority());
509 // finally perform the test :
511 userService
.changePasswordForUser("partEditor", "poiweorijo");
512 commitAndStartNewTransaction(null);
513 } catch (AccessDeniedException e
){
514 logger
.debug("Expected failure of evaluation.", e
);
516 } catch (RuntimeException e
){
517 exception
= findThrowableOfTypeIn(PermissionDeniedException
.class, e
);
518 logger
.debug("Expected failure of evaluation.", e
);
520 // needed in case saveOrUpdate was interrupted by the RuntimeException
521 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
523 startNewTransaction();
525 Assert
.assertNotNull("must fail here!", exception
);
529 public void testUpdateUser(){
531 authentication
= authenticationManager
.authenticate(tokenForAdmin
);
532 SecurityContext context
= SecurityContextHolder
.getContext();
533 context
.setAuthentication(authentication
);
534 String username
= "standardUser";
535 String password
= "pw";
536 User user
= User
.NewInstance(username
, password
);
538 userService
.createUser(user
);
539 user
.setEmailAddress("test@bgbm.org");
541 userService
.updateUser(user
);
542 userService
.update(user
);
543 userService
.saveOrUpdate(user
);
544 commitAndStartNewTransaction(null);
549 * test with admin account - should succeed
552 public final void testTaxonSaveOrUpdateAllow_1() {
554 SecurityContext context
= SecurityContextHolder
.getContext();
556 authentication
= authenticationManager
.authenticate(tokenForAdmin
);
557 context
.setAuthentication(authentication
);
558 RuntimeException securityException
= null;
560 TaxonBase
<?
> taxon
= taxonService
.find(UUID_ACHERONTIA_STYX
);
561 Assert
.assertFalse(taxon
.isDoubtful());
562 taxon
.setDoubtful(true);
564 taxonService
.saveOrUpdate(taxon
);
565 commitAndStartNewTransaction(null);
566 } catch (RuntimeException e
){
567 securityException
= findSecurityRuntimeException(e
);
568 logger
.error("Unexpected failure of evaluation.", e
);
570 // needed in case saveOrUpdate was interrupted by the RuntimeException
571 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
573 startNewTransaction();
575 Assert
.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException
!= null ? securityException
.getMessage() : ""), securityException
);
577 taxon
= taxonService
.find(UUID_ACHERONTIA_STYX
);
578 Assert
.assertTrue("The change must be persisted", taxon
.isDoubtful());
582 * test with taxonEditor account - should succeed
585 public final void testTaxonSaveOrUpdateAllow_2() {
588 RuntimeException securityException
= null;
589 SecurityContext context
= SecurityContextHolder
.getContext();
591 // taxonEditor account - should succeed
592 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
594 context
.setAuthentication(authentication
);
596 TaxonBase
<?
> taxon
= taxonService
.find(UUID_ACHERONTIA_STYX
);
597 Assert
.assertFalse(taxon
.isDoubtful());
598 taxon
.setDoubtful(true);
600 taxonService
.saveOrUpdate(taxon
);
601 commitAndStartNewTransaction(null);
602 } catch (RuntimeException e
){
603 securityException
= findSecurityRuntimeException(e
);
604 logger
.error("Unexpected failure of evaluation.", e
);
606 // needed in case saveOrUpdate was interrupted by the RuntimeException
607 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
609 startNewTransaction();
611 Assert
.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException
!= null ? securityException
.getMessage() : ""), securityException
);
613 taxon
= taxonService
.find(UUID_ACHERONTIA_STYX
);
614 Assert
.assertTrue("The change must be persited", taxon
.isDoubtful());
618 * test with tokenForDescriptionEditor account - should fail
621 public final void testTaxonSaveOrUpdateDeny_2() {
623 SecurityContext context
= SecurityContextHolder
.getContext();
624 RuntimeException securityException
= null;
626 authentication
= authenticationManager
.authenticate(tokenForDescriptionEditor
);
627 context
.setAuthentication(authentication
);
629 TaxonBase
<?
> taxon
= taxonService
.find(UUID_ACHERONTIA_STYX
);
631 Assert
.assertFalse(taxon
.isDoubtful());
632 taxon
.setDoubtful(true);
634 taxonService
.saveOrUpdate(taxon
);
635 commitAndStartNewTransaction(null);
636 } catch (RuntimeException e
){
637 securityException
= findSecurityRuntimeException(e
);
638 logger
.debug("Expected failure of evaluation.", securityException
);
640 // needed in case saveOrUpdate was interrupted by the RuntimeException
641 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
643 startNewTransaction();
646 Assert
.assertNotNull("evaluation must fail since the user is not permitted", securityException
);
648 taxon
= taxonService
.find(UUID_ACHERONTIA_STYX
);
649 Assert
.assertFalse("The change must not be persited", taxon
.isDoubtful());
653 public final void testTaxonPublishAllow_ROLE_ADMIN() {
655 SecurityContext context
= SecurityContextHolder
.getContext();
657 authentication
= authenticationManager
.authenticate(tokenForAdmin
);
658 context
.setAuthentication(authentication
);
659 RuntimeException securityException
= null;
661 Taxon taxon
= (Taxon
) taxonService
.find(UUID_ACHERONTIA_STYX
);
663 boolean lastIsPublish
= taxon
.isPublish();
664 taxon
.setPublish(!lastIsPublish
);
666 taxonService
.saveOrUpdate(taxon
);
667 commitAndStartNewTransaction(null);
668 } catch (RuntimeException e
){
669 securityException
= findSecurityRuntimeException(e
);
670 logger
.error("Unexpected failure of evaluation.", e
);
672 // needed in case saveOrUpdate was interrupted by the RuntimeException
673 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
675 startNewTransaction();
677 Assert
.assertNull("evaluation must not fail since the user has ROLE_ADMIN, CAUSE :" + (securityException
!= null ? securityException
.getMessage() : ""), securityException
);
679 taxon
= (Taxon
) taxonService
.find(UUID_ACHERONTIA_STYX
);
680 Assert
.assertTrue("The change must be persisted", taxon
.isPublish() != lastIsPublish
);
685 * test with Taxonomist account which has the ROLE_PUBLISH
688 public final void testTaxonPublishAllow_ROLE_PUBLISH() {
690 SecurityContext context
= SecurityContextHolder
.getContext();
692 authentication
= authenticationManager
.authenticate(tokenForTaxonomist
);
693 context
.setAuthentication(authentication
);
694 RuntimeException securityException
= null;
696 Taxon taxon
= (Taxon
) taxonService
.find(UUID_ACHERONTIA_STYX
);
698 boolean lastIsPublish
= taxon
.isPublish();
699 taxon
.setPublish(!lastIsPublish
);
701 taxonService
.saveOrUpdate(taxon
);
702 commitAndStartNewTransaction(null);
703 } catch (RuntimeException e
){
704 securityException
= findSecurityRuntimeException(e
);
705 logger
.error("Unexpected failure of evaluation.", e
);
707 // needed in case saveOrUpdate was interrupted by the RuntimeException
708 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
710 startNewTransaction();
712 Assert
.assertNull("evaluation must not fail since the user has ROLE_ADMIN, CAUSE :" + (securityException
!= null ? securityException
.getMessage() : ""), securityException
);
714 taxon
= (Taxon
) taxonService
.find(UUID_ACHERONTIA_STYX
);
715 Assert
.assertTrue("The change must be persisted", taxon
.isPublish() != lastIsPublish
);
719 * test with TaxonEditor account which has not the ROLE_PUBLISH
722 public final void testTaxonPublishDeny() {
724 SecurityContext context
= SecurityContextHolder
.getContext();
726 authentication
= authenticationManager
.authenticate(tokenForTaxonEditor
);
727 context
.setAuthentication(authentication
);
728 RuntimeException securityException
= null;
730 Taxon taxon
= (Taxon
) taxonService
.find(UUID_ACHERONTIA_STYX
);
732 boolean lastIsPublish
= taxon
.isPublish();
733 taxon
.setPublish(!lastIsPublish
);
735 taxonService
.saveOrUpdate(taxon
);
736 commitAndStartNewTransaction(null);
737 } catch (RuntimeException e
){
738 securityException
= findSecurityRuntimeException(e
);
739 logger
.debug("Expected failure of evaluation.", securityException
);
741 // needed in case saveOrUpdate was interrupted by the RuntimeException
742 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
744 startNewTransaction();
747 Assert
.assertNotNull("evaluation must fail since the user is not permitted", securityException
);
749 taxon
= (Taxon
) taxonService
.find(UUID_ACHERONTIA_STYX
);
750 Assert
.assertTrue("The taxon must be unchanged", taxon
.isPublish() == lastIsPublish
);
754 * test with admin account - should succeed
757 public final void testTaxonDeleteAllow_1() {
759 SecurityContext context
= SecurityContextHolder
.getContext();
761 authentication
= authenticationManager
.authenticate(tokenForAdmin
);
762 context
.setAuthentication(authentication
);
763 RuntimeException securityException
= null;
765 TaxonBase
<?
> taxon
= taxonService
.load(UUID_LACTUCA
);
766 taxonService
.delete(taxon
);
767 commitAndStartNewTransaction(null);
772 Assert
.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException
!= null ? securityException
.getMessage() : ""), securityException
);
774 taxon
= taxonService
.load(UUID_LACTUCA
);
775 Assert
.assertNull("The taxon must be deleted", taxon
);
779 * test with admin account - should succeed
782 public final void testTaxonDeleteAllow_2() {
784 SecurityContext context
= SecurityContextHolder
.getContext();
786 authentication
= authenticationManager
.authenticate(tokenForAdmin
);
787 context
.setAuthentication(authentication
);
788 RuntimeException securityException
= null;
790 Taxon taxon
= (Taxon
)taxonService
.load(UUID_ACHERONTINII
);
793 DeleteResult result
= taxonService
.deleteTaxon(taxon
, null, null);
794 /*} catch (DataChangeNoRollbackException e) {
800 commitAndStartNewTransaction(null);
801 } catch (RuntimeException e
){
802 securityException
= findSecurityRuntimeException(e
);
803 logger
.error("Unexpected failure of evaluation.", e
);
805 // needed in case saveOrUpdate was interrupted by the RuntimeException
806 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
808 startNewTransaction();
810 Assert
.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException
!= null ? securityException
.getMessage() : ""), securityException
);
813 taxon
= (Taxon
)taxonService
.find(UUID_ACHERONTINII
);
814 Assert
.assertNull("The taxon must be deleted", taxon
);
819 * test with tokenForDescriptionEditor account - should fail
822 public final void testTaxonDeleteDeny() {
824 SecurityContext context
= SecurityContextHolder
.getContext();
825 RuntimeException securityException
= null;
827 authentication
= authenticationManager
.authenticate(tokenForDescriptionEditor
);
828 context
.setAuthentication(authentication
);
830 Taxon taxon
= (Taxon
)taxonService
.load(UUID_LACTUCA
);
831 DeleteResult result
= taxonService
.deleteTaxon(taxon
, null, null);
832 if (!result
.isError()) {
836 startNewTransaction();
839 //Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
841 taxon
= (Taxon
)taxonService
.load(UUID_LACTUCA
);
843 Assert
.assertNotNull("The change must still exist", taxon
);
844 Assert
.assertNotNull("The name must still exist",taxon
.getName());
849 @Ignore //FIXME: adding taxa to a description must be protected at the side of the Description itself!!
850 // => protecting method TaxonDescription.setTaxon() ?
851 public void testAddDescriptionToTaxon(){
853 SecurityContext context
= SecurityContextHolder
.getContext();
854 authentication
= authenticationManager
.authenticate(tokenForDescriptionEditor
);
855 context
.setAuthentication(authentication
);
857 RuntimeException securityException
= null;
859 Taxon taxon
= (Taxon
)taxonService
.load(ACHERONTIA_LACHESIS_UUID
);
861 TaxonDescription description
= TaxonDescription
.NewInstance(taxon
);
862 description
.setTitleCache("test");
864 descriptionService
.saveOrUpdate(description
);
865 commitAndStartNewTransaction(null);
866 } catch (RuntimeException e
){
867 securityException
= findSecurityRuntimeException(e
);
868 logger
.debug("Expected failure of evaluation.", securityException
);
870 // needed in case saveOrUpdate was interrupted by the RuntimeException
871 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
873 startNewTransaction();
877 * The user should not be granted to add the Description to a taxon
879 Assert
.assertNotNull("evaluation should fail since the user is not permitted to edit Taxa", securityException
);
880 taxon
= (Taxon
)taxonService
.load(ACHERONTIA_LACHESIS_UUID
);
881 assertTrue(taxon
.getDescriptions().contains(description
));
885 public void testMoveDescriptionElement(){
887 SecurityContext context
= SecurityContextHolder
.getContext();
888 authentication
= authenticationManager
.authenticate(tokenForTaxonomist
);
889 context
.setAuthentication(authentication
);
891 RuntimeException securityException
= null;
893 Taxon t_acherontia_lachesis
= (Taxon
)taxonService
.load(ACHERONTIA_LACHESIS_UUID
);
894 Taxon t_acherontia_styx
= (Taxon
)taxonService
.load(UUID_ACHERONTIA_STYX
);
896 TaxonDescription description_acherontia_styx
= t_acherontia_styx
.getDescriptions().iterator().next();
897 TaxonDescription description_acherontia_lachesis
= t_acherontia_lachesis
.getDescriptions().iterator().next();
900 descriptionService
.moveDescriptionElementsToDescription(description_acherontia_styx
.getElements(), description_acherontia_lachesis
, false);
901 commitAndStartNewTransaction(null);
902 } catch (RuntimeException e
){
903 securityException
= findSecurityRuntimeException(e
);
904 logger
.debug("Unexpected failure of evaluation.", securityException
);
906 // needed in case saveOrUpdate was interrupted by the RuntimeException
907 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
909 startNewTransaction();
914 Assert
.assertNull("evaluation should not fail since the user has sufficient permissions", securityException
);
918 // @Ignore // FIXME http://dev.e-taxonomy.eu/trac/ticket/4081 : #4081 (TaxonNodeServiceImpl.makeTaxonNodeASynonymOfAnotherTaxonNode() requires TAXONNAMEBASE.[UPDATE])
920 public void testAcceptedTaxonToSynomym(){
922 SecurityContext context
= SecurityContextHolder
.getContext();
923 authentication
= authenticationManager
.authenticate(tokenForPartEditor
);
924 context
.setAuthentication(authentication
);
926 RuntimeException securityException
= null;
928 Taxon t_acherontia_lachesis
= (Taxon
)taxonService
.load(ACHERONTIA_LACHESIS_UUID
);
929 Taxon t_acherontia_styx
= (Taxon
)taxonService
.load(UUID_ACHERONTIA_STYX
);
932 TaxonNode n_acherontia_lachesis
= t_acherontia_lachesis
.getTaxonNodes().iterator().next();
933 TaxonNode n_acherontia_styx
= t_acherontia_styx
.getTaxonNodes().iterator().next();
935 int numOfSynonymsBefore_styx
= t_acherontia_styx
.getSynonyms().size();
936 int numOfSynonymsBefore_lachesis
= t_acherontia_lachesis
.getSynonyms().size();
938 UUID synonymUuid
= null; // UUID.randomUUID();
941 Synonym synonym
= taxonNodeService
.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_lachesis
, n_acherontia_styx
, SynonymRelationshipType
.SYNONYM_OF(), null, null);
942 synonymUuid
= synonym
.getUuid();
943 taxonService
.saveOrUpdate(synonym
);
944 commitAndStartNewTransaction(null);
945 } catch (RuntimeException e
){
946 securityException
= findSecurityRuntimeException(e
);
947 logger
.error("Unexpected Exception ", e
);
948 Assert
.fail("Unexpected Exception: " + e
.getMessage());
950 // needed in case saveOrUpdate was interrupted by the RuntimeException
951 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
953 startNewTransaction();
958 Assert
.assertNull("evaluation should not fail since the user has sufficient permissions", securityException
);
960 // reload from db and check assertions
961 t_acherontia_styx
= (Taxon
)taxonService
.load(UUID_ACHERONTIA_STYX
);
962 Assert
.assertEquals("Acherontia styx now must have a synonym", numOfSynonymsBefore_styx
+ numOfSynonymsBefore_lachesis
+ 1, t_acherontia_styx
.getSynonyms().size());
963 Assert
.assertTrue("Acherontia lachesis now must be a synonym", taxonService
.load(synonymUuid
) instanceof Synonym
);
964 Assert
.assertNull("The old TaxonNode should no longer exist", taxonNodeService
.find(n_acherontia_lachesis
.getUuid()));
968 public void testCreateDescriptionWithElement(){
970 SecurityContext context
= SecurityContextHolder
.getContext();
971 authentication
= authenticationManager
.authenticate(tokenForDescriptionEditor
);
972 context
.setAuthentication(authentication
);
974 TaxonDescription description
= null;
975 RuntimeException securityException
= null;
976 Taxon taxon
= (Taxon
)taxonService
.load(UUID_ACHERONTINII
);
977 Assert
.assertTrue("taxon must not yet have descriptions", taxon
.getDescriptions().size() == 0);
980 // 1) test for failure - description element but no feature
981 description
= TaxonDescription
.NewInstance(taxon
);
982 DescriptionElementBase textdataNoFeature
= TextData
.NewInstance();
983 description
.addElement(textdataNoFeature
);
985 assertTrue(permissionEvaluator
.hasPermission(authentication
, description
, "UPDATE"));
987 descriptionService
.saveOrUpdate(description
);
988 commitAndStartNewTransaction(null);
989 } catch (RuntimeException e
){
990 securityException
= findSecurityRuntimeException(e
);
991 logger
.error("RuntimeException caught");
992 logger
.debug("Expected failure of evaluation.", securityException
);
994 // needed in case saveOrUpdate was interrupted by the RuntimeException
995 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
997 startNewTransaction();
1000 Assert
.assertNotNull("evaluation should fail", securityException
);
1001 taxon
= (Taxon
)taxonService
.load(UUID_ACHERONTINII
);
1002 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
1003 assertTrue("taxon must not have any description", descriptions
.size() == 0);
1008 public void testCreateDescriptionWithElementDeny_1(){
1010 SecurityContext context
= SecurityContextHolder
.getContext();
1011 authentication
= authenticationManager
.authenticate(tokenForDescriptionEditor
);
1012 context
.setAuthentication(authentication
);
1014 TaxonDescription description
= null;
1015 RuntimeException securityException
= null;
1016 Taxon taxon
= (Taxon
)taxonService
.load(UUID_ACHERONTINII
);
1017 Assert
.assertTrue("taxon must not yet have descriptions", taxon
.getDescriptions().size() == 0);
1019 // 2) test for failure - description element but not granted feature
1020 description
= TaxonDescription
.NewInstance(taxon
);
1021 DescriptionElementBase descriptionText
= TextData
.NewInstance(Feature
.DESCRIPTION());
1022 description
.addElement(descriptionText
);
1024 securityException
= null;
1025 assertTrue(permissionEvaluator
.hasPermission(authentication
, description
, "UPDATE"));
1027 descriptionService
.saveOrUpdate(description
);
1028 commitAndStartNewTransaction(null);
1029 } catch (RuntimeException e
){
1030 securityException
= findSecurityRuntimeException(e
);
1031 logger
.debug("Expected failure of evaluation.", securityException
);
1033 // needed in case saveOrUpdate was interrupted by the RuntimeException
1034 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1036 startNewTransaction();
1039 Assert
.assertNotNull("evaluation should fail", securityException
);
1040 taxon
= (Taxon
)taxonService
.load(UUID_ACHERONTINII
);
1041 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
1042 assertTrue("taxon must not have any description", descriptions
.size() == 0);
1047 public void testCreateDescriptionWithElementDeny_2(){
1049 SecurityContext context
= SecurityContextHolder
.getContext();
1050 authentication
= authenticationManager
.authenticate(tokenForDescriptionEditor
);
1051 context
.setAuthentication(authentication
);
1053 TaxonDescription description
= null;
1054 RuntimeException securityException
= null;
1055 Taxon taxon
= (Taxon
)taxonService
.load(UUID_ACHERONTINII
);
1056 Assert
.assertTrue("taxon must not yet have descriptions", taxon
.getDescriptions().size() == 0);
1058 // 3) test for failure
1059 description
= TaxonDescription
.NewInstance(taxon
);
1060 DescriptionElementBase ecologyText
= TextData
.NewInstance(Feature
.ECOLOGY());
1061 description
.addElement(ecologyText
);
1063 securityException
= null;
1064 assertTrue(permissionEvaluator
.hasPermission(authentication
, description
, "UPDATE"));
1066 descriptionService
.saveOrUpdate(description
);
1067 commitAndStartNewTransaction(null);
1068 } catch (RuntimeException e
){
1069 securityException
= findSecurityRuntimeException(e
);
1070 logger
.error("Unexpected failure of evaluation.", e
);
1072 // needed in case saveOrUpdate was interrupted by the RuntimeException
1073 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1075 startNewTransaction();
1078 Assert
.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException
!= null ? securityException
.getMessage() : ""), securityException
);
1079 taxon
= (Taxon
)taxonService
.load(UUID_ACHERONTINII
);
1080 Set
<TaxonDescription
> descriptions
= taxon
.getDescriptions();
1081 assertTrue("taxon must now have one description", descriptions
.size() == 1);
1082 assertTrue("description should have one description element", descriptions
.iterator().next().getElements().size() == 1);
1086 public void testSaveSynonymAllow(){
1088 SecurityContext context
= SecurityContextHolder
.getContext();
1089 RuntimeException securityException
= null;
1091 // 1) test for success
1092 authentication
= authenticationManager
.authenticate(tokenForTaxonomist
);
1093 context
.setAuthentication(authentication
);
1095 Synonym syn
= Synonym
.NewInstance(BotanicalName
.NewInstance(Rank
.SPECIES()), null);
1096 UUID synUuid
= UUID
.randomUUID();
1097 syn
.setUuid(synUuid
);
1099 taxonService
.saveOrUpdate(syn
);
1100 logger
.debug("will commit ...");
1101 commitAndStartNewTransaction(null);
1102 } catch (RuntimeException e
){
1103 securityException
= findSecurityRuntimeException(e
);
1104 logger
.error("Unexpected failure of evaluation.", e
);
1106 // needed in case saveOrUpdate was interrupted by the RuntimeException
1107 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1109 startNewTransaction();
1111 Assert
.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException
!= null ? securityException
.getMessage() : ""), securityException
);
1112 Assert
.assertNotNull("The new Synonym must be persited", taxonService
.find(synUuid
));
1116 public void testSaveSynonymDenial(){
1118 SecurityContext context
= SecurityContextHolder
.getContext();
1119 RuntimeException securityException
= null;
1120 // 2) test for denial
1121 authentication
= authenticationManager
.authenticate(tokenForDescriptionEditor
);
1122 context
.setAuthentication(authentication
);
1123 securityException
= null;
1124 Synonym syn
= Synonym
.NewInstance(BotanicalName
.NewInstance(Rank
.SPECIES()), null);
1125 UUID synUuid
= syn
.getUuid();
1127 taxonService
.saveOrUpdate(syn
);
1128 logger
.debug("will commit ...");
1129 commitAndStartNewTransaction(null);
1130 } catch (RuntimeException e
){
1131 securityException
= findSecurityRuntimeException(e
);
1132 logger
.debug("Expected failure of evaluation: " + securityException
.getClass());
1134 // needed in case saveOrUpdate was interrupted by the RuntimeException
1135 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1137 startNewTransaction();
1140 Assert
.assertNotNull("evaluation must fail since the user is not permitted", securityException
);
1141 Assert
.assertNull("The Synonym must not be persited", taxonService
.find(synUuid
));
1145 public void testEditPartOfClassificationAllow(){
1147 authentication
= authenticationManager
.authenticate(tokenForPartEditor
);
1148 SecurityContext context
= SecurityContextHolder
.getContext();
1149 context
.setAuthentication(authentication
);
1150 RuntimeException securityException
= null;
1151 Classification classification
= classificationService
.load(UUID
.fromString("aeee7448-5298-4991-b724-8d5b75a0a7a9"));
1153 TaxonNode acherontia_node
= taxonNodeService
.load(ACHERONTIA_NODE_UUID
);
1154 long numOfChildNodes
= acherontia_node
.getChildNodes().size();
1155 TaxonNode childNode
= acherontia_node
.addChildTaxon(Taxon
.NewInstance(BotanicalName
.NewInstance(Rank
.SPECIES()), null), null, null);
1158 taxonNodeService
.saveOrUpdate(acherontia_node
);
1159 commitAndStartNewTransaction(null);
1160 } catch (RuntimeException e
){
1161 securityException
= findSecurityRuntimeException(e
);
1162 logger
.error("Unexpected failure of evaluation.", securityException
);
1164 // needed in case saveOrUpdate was interrupted by the RuntimeException
1165 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1167 startNewTransaction();
1170 acherontia_node
= taxonNodeService
.load(ACHERONTIA_NODE_UUID
);
1171 Assert
.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException
!= null ? securityException
.getMessage() : ""), securityException
);
1172 Assert
.assertEquals("the acherontia_node must now have one more child node ", numOfChildNodes
+ 1 , acherontia_node
.getChildNodes().size());
1176 public void testEditPartOfClassificationDeny(){
1178 authentication
= authenticationManager
.authenticate(tokenForPartEditor
);
1179 SecurityContext context
= SecurityContextHolder
.getContext();
1180 context
.setAuthentication(authentication
);
1181 RuntimeException securityException
= null;
1184 securityException
= null;
1185 TaxonNode acherontiini_node
= taxonNodeService
.load(ACHERONTIINI_NODE_UUID
);
1186 int numOfChildNodes
= acherontiini_node
.getCountChildren();
1187 acherontiini_node
.addChildTaxon(Taxon
.NewInstance(BotanicalName
.NewInstance(Rank
.GENUS()), null), null, null);
1190 logger
.debug("==============================");
1191 taxonNodeService
.saveOrUpdate(acherontiini_node
);
1192 commitAndStartNewTransaction(null);
1193 } catch (RuntimeException e
){
1194 securityException
= findSecurityRuntimeException(e
);
1195 logger
.debug("Expected failure of evaluation.", securityException
);
1197 // needed in case saveOrUpdate was interrupted by the RuntimeException
1198 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1200 startNewTransaction();
1203 acherontiini_node
= taxonNodeService
.load(ACHERONTIINI_NODE_UUID
);
1204 Assert
.assertNotNull("evaluation must fail since the user is not permitted", securityException
);
1205 Assert
.assertEquals("the number of child nodes must be unchanged ", numOfChildNodes
, acherontiini_node
.getChildNodes().size());