- added abstract method createTestData() to CdmIntegrationalTest
[cdmlib.git] / cdmlib-services / src / test / java / eu / etaxonomy / cdm / api / service / SecurityTest.java
1 /**
2 * Copyright (C) 2011 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9 package eu.etaxonomy.cdm.api.service;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertFalse;
13 import static org.junit.Assert.assertTrue;
14
15 import java.io.FileNotFoundException;
16 import java.util.Collection;
17 import java.util.EnumSet;
18 import java.util.HashSet;
19 import java.util.List;
20 import java.util.Set;
21 import java.util.UUID;
22
23 import javax.sql.DataSource;
24
25 import org.apache.log4j.Logger;
26 import org.junit.Assert;
27 import org.junit.Ignore;
28 import org.junit.Test;
29 import org.springframework.security.access.AccessDeniedException;
30 import org.springframework.security.authentication.AuthenticationManager;
31 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
32 import org.springframework.security.authentication.dao.SaltSource;
33 import org.springframework.security.authentication.encoding.PasswordEncoder;
34 import org.springframework.security.core.Authentication;
35 import org.springframework.security.core.GrantedAuthority;
36 import org.springframework.security.core.context.SecurityContext;
37 import org.springframework.security.core.context.SecurityContextHolder;
38 import org.springframework.transaction.PlatformTransactionManager;
39 import org.unitils.database.annotations.TestDataSource;
40 import org.unitils.dbunit.annotation.DataSet;
41 import org.unitils.spring.annotation.SpringBean;
42 import org.unitils.spring.annotation.SpringBeanByType;
43
44 import sun.security.provider.PolicyParser.ParsingException;
45 import eu.etaxonomy.cdm.api.service.DeleteResult.DeleteStatus;
46 import eu.etaxonomy.cdm.api.service.exception.DataChangeNoRollbackException;
47 import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;
48 import eu.etaxonomy.cdm.database.PermissionDeniedException;
49 import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;
50 import eu.etaxonomy.cdm.model.common.User;
51 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
52 import eu.etaxonomy.cdm.model.description.Feature;
53 import eu.etaxonomy.cdm.model.description.TaxonDescription;
54 import eu.etaxonomy.cdm.model.description.TextData;
55 import eu.etaxonomy.cdm.model.name.BotanicalName;
56 import eu.etaxonomy.cdm.model.name.Rank;
57 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
58 import eu.etaxonomy.cdm.model.name.ZoologicalName;
59 import eu.etaxonomy.cdm.model.reference.Reference;
60 import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
61 import eu.etaxonomy.cdm.model.taxon.Classification;
62 import eu.etaxonomy.cdm.model.taxon.Synonym;
63 import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
64 import eu.etaxonomy.cdm.model.taxon.Taxon;
65 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
66 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
67 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
68 import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmAuthority;
69 import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionClass;
70 import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionEvaluator;
71 import eu.etaxonomy.cdm.persistence.hibernate.permission.Operation;
72 import eu.etaxonomy.cdm.persistence.query.MatchMode;
73
74
75 @DataSet
76 public class SecurityTest extends AbstractSecurityTestBase{
77
78
79 private static final Logger logger = Logger.getLogger(SecurityTest.class);
80
81 @SpringBeanByType
82 private ITaxonService taxonService;
83
84 @SpringBeanByType
85 private INameService nameService;
86
87 @SpringBeanByType
88 private IReferenceService referenceService;
89
90 @SpringBeanByType
91 private ITaxonNodeService taxonNodeService;
92
93 @SpringBeanByType
94 private IDescriptionService descriptionService;
95
96 @SpringBeanByType
97 private IUserService userService;
98
99 @SpringBeanByType
100 private IClassificationService classificationService;
101
102 @SpringBeanByType
103 private AuthenticationManager authenticationManager;
104
105 @SpringBeanByType
106 private SaltSource saltSource;
107
108 @SpringBeanByType
109 private PasswordEncoder passwordEncoder;
110
111 @SpringBean("cdmPermissionEvaluator")
112 private CdmPermissionEvaluator permissionEvaluator;
113
114 @TestDataSource
115 protected DataSource dataSource;
116
117 private Authentication authentication;
118
119
120 /**
121 * no assertions in this test, since it is only used to create password hashes for test data
122 */
123 @Test
124 public void testEncryptPassword(){
125
126 String password = PASSWORD_ADMIN;
127 User user = User.NewInstance("userManager", "");
128
129 Object salt = this.saltSource.getSalt(user);
130 String passwordEncrypted = passwordEncoder.encodePassword(password, salt);
131 logger.info("encrypted password: " + passwordEncrypted );
132 }
133
134 @Test
135 @DataSet
136 public void testHasPermission(){
137
138 Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()),null);
139
140 authentication = authenticationManager.authenticate(tokenForTaxonomist);
141 boolean hasPermission = permissionEvaluator.hasPermission(authentication, taxon, Operation.UPDATE);
142 assertTrue(hasPermission);
143
144 authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
145 hasPermission = permissionEvaluator.hasPermission(authentication, taxon, Operation.UPDATE);
146 assertFalse(hasPermission);
147 }
148
149 @Test
150 @DataSet
151 public void testListByUsernameAllow(){
152
153 authentication = authenticationManager.authenticate(tokenForTaxonomist);
154 SecurityContext context = SecurityContextHolder.getContext();
155 context.setAuthentication(authentication);
156
157 List<User> userList = userService.listByUsername("Editor", MatchMode.ANYWHERE, null, null, 0, null, null);
158 Assert.assertTrue("The user list must have elements", userList.size() > 0 );
159 }
160
161 @Test
162 @DataSet
163 public void testUserService_CreateDeny(){
164
165 authentication = authenticationManager.authenticate(tokenForTaxonomist);
166 SecurityContext context = SecurityContextHolder.getContext();
167 context.setAuthentication(authentication);
168
169 RuntimeException exception = null;
170 try {
171 userService.createUser(User.NewInstance("new guy", "alkjdsfalkj"));
172 commitAndStartNewTransaction(null);
173 } catch (AccessDeniedException e){
174 logger.debug("Expected failure of evaluation.", e);
175 exception = e;
176 } catch (RuntimeException e){
177 exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
178 logger.debug("Expected failure of evaluation.", e);
179 } finally {
180 // needed in case saveOrUpdate was interrupted by the RuntimeException
181 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
182 endTransaction();
183 startNewTransaction();
184 }
185 Assert.assertNotNull("Must fail here!", exception);
186
187 }
188
189 @Test
190 @DataSet
191 public void testUserService_CreateAllow(){
192
193 authentication = authenticationManager.authenticate(tokenForUserManager);
194 SecurityContext context = SecurityContextHolder.getContext();
195 context.setAuthentication(authentication);
196
197 RuntimeException exception = null;
198 try {
199 userService.createUser(User.NewInstance("new guy", "alkjdsfalkj"));
200 commitAndStartNewTransaction(null);
201 } catch (AccessDeniedException e){
202 logger.error("Unexpected failure of evaluation.", e);
203 exception = e;
204 } catch (RuntimeException e){
205 exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
206 logger.error("unexpected failure of evaluation.", exception);
207 } finally {
208 // needed in case saveOrUpdate was interrupted by the RuntimeException
209 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
210 endTransaction();
211 startNewTransaction();
212 }
213 Assert.assertNull("Must not fail here!", exception);
214
215 }
216
217
218 @Test
219 @DataSet
220 @Ignore // FIXME http://dev.e-taxonomy.eu/trac/ticket/3098
221 public void testHasPermissions(){
222
223 Taxon taxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()),null);
224
225 authentication = authenticationManager.authenticate(tokenForTaxonomist);
226 boolean hasPermission = permissionEvaluator.hasPermission(authentication, taxon, Operation.ALL);
227 assertTrue(hasPermission);
228 }
229
230
231 /**
232 * Test method for {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#saveTaxon(eu.etaxonomy.cdm.model.taxon.TaxonBase)}.
233 */
234 @Test
235 public final void testSaveTaxon() {
236
237 authentication = authenticationManager.authenticate(tokenForAdmin);
238 SecurityContext context = SecurityContextHolder.getContext();
239 context.setAuthentication(authentication);
240
241 Taxon expectedTaxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null);
242 expectedTaxon.getName().setTitleCache("Newby admin", true);
243 UUID uuid = taxonService.save(expectedTaxon);
244 commitAndStartNewTransaction(null);
245 TaxonBase<?> actualTaxon = taxonService.load(uuid);
246 assertEquals(expectedTaxon, actualTaxon);
247
248 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
249 context = SecurityContextHolder.getContext();
250 context.setAuthentication(authentication);
251 expectedTaxon = Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()), null);
252 expectedTaxon.getName().setTitleCache("Newby taxonEditor", true);
253 uuid = taxonService.saveOrUpdate(expectedTaxon);
254 commitAndStartNewTransaction(null);
255 actualTaxon = taxonService.load(uuid);
256 assertEquals(expectedTaxon, actualTaxon);
257
258 }
259
260 @Test
261 public final void testSaveNameAllow() {
262
263 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
264 SecurityContext context = SecurityContextHolder.getContext();
265 context.setAuthentication(authentication);
266
267 ZoologicalName newName = ZoologicalName.NewInstance(Rank.SPECIES());
268 newName.setTitleCache("Newby taxonEditor", true);
269 UUID uuid = nameService.saveOrUpdate(newName);
270 commitAndStartNewTransaction(null);
271 TaxonNameBase savedName = nameService.load(uuid);
272 assertEquals(newName, savedName);
273 }
274
275
276 @Test
277 public final void testReuseNameAllow() {
278
279 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
280 SecurityContext context = SecurityContextHolder.getContext();
281 context.setAuthentication(authentication);
282
283 TaxonBase taxon = taxonService.find(UUID_ACHERONTIA_STYX);
284 TaxonNameBase n_acherontia_thetis = taxon.getName();
285
286 Taxon newTaxon = Taxon.NewInstance(n_acherontia_thetis, ReferenceFactory.newGeneric());
287 Exception exception = null;
288 try {
289 UUID uuid = taxonService.save(newTaxon);
290 commitAndStartNewTransaction(null);
291 } catch (AccessDeniedException e){
292 logger.error("Unexpected failure of evaluation.", e);
293 exception = e;
294 } catch (RuntimeException e){
295 logger.error("Unexpected failure of evaluation.", e);
296 exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
297 } finally {
298 // needed in case saveOrUpdate was interrupted by the RuntimeException
299 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
300 endTransaction();
301 startNewTransaction();
302 }
303 Assert.assertNull("must not fail here!", exception);
304 }
305
306 @Test
307 public final void testMakeTaxonNodeASynonymOfAnotherTaxonNodeAllow_1() {
308
309 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
310 SecurityContext context = SecurityContextHolder.getContext();
311 context.setAuthentication(authentication);
312
313 Reference book = referenceService.load(BOOK1_UUID);
314
315 TaxonNode n_acherontia_styx = taxonNodeService.find(ACHERONTIA_STYX_NODE_UUID);
316 TaxonNode n_acherontia_lachersis = taxonNodeService.find(ACHERONTIA_LACHESIS_NODE_UUID);
317
318 Exception exception = null;
319 try {
320 taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_styx, n_acherontia_lachersis, SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF(), book , "33");
321 commitAndStartNewTransaction(null);
322 } catch (AccessDeniedException e){
323 logger.error("Unexpected failure of evaluation.", e);
324 exception = e;
325 } catch (RuntimeException e){
326 logger.error("Unexpected failure of evaluation.", e);
327 exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
328 }finally {
329 // needed in case saveOrUpdate was interrupted by the RuntimeException
330 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
331 endTransaction();
332 startNewTransaction();
333 }
334 Assert.assertNull("must not fail here!", exception);
335 }
336
337 @Test
338 public final void testMakeTaxonNodeASynonymOfAnotherTaxonNodeAllow_2() {
339
340 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
341 SecurityContext context = SecurityContextHolder.getContext();
342 context.setAuthentication(authentication);
343
344 Reference book = referenceService.load(BOOK1_UUID);
345
346 TaxonNode n_acherontia_styx = taxonNodeService.find(ACHERONTIA_STYX_NODE_UUID);
347 TaxonNode n_acherontia_lachersis = taxonNodeService.find(ACHERONTIA_LACHESIS_NODE_UUID);
348
349 Exception exception = null;
350 try {
351 taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_lachersis, n_acherontia_styx, SynonymRelationshipType.HOMOTYPIC_SYNONYM_OF(), book , "33");
352 commitAndStartNewTransaction(null);
353 } catch (AccessDeniedException e){
354 logger.error("Unexpected failure of evaluation.", e);
355 exception = e;
356 } catch (RuntimeException e){
357 logger.error("Unexpected failure of evaluation.", e);
358 exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
359 } finally {
360 // needed in case saveOrUpdate was interrupted by the RuntimeException
361 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
362 endTransaction();
363 startNewTransaction();
364 }
365 Assert.assertNull("must not fail here!", exception);
366 }
367
368 @Test
369 public final void testUpdateReferenceAllow() throws ParsingException {
370
371
372 authentication = authenticationManager.authenticate(tokenForUserManager);
373 SecurityContext context = SecurityContextHolder.getContext();
374 context.setAuthentication(authentication);
375
376 // add REFERENCE[UPDATE] to taxonEditor
377 User taxonEditor = userService.load(TAXON_EDITOR_UUID);
378 Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();
379 grantedAuthorities.addAll(taxonEditor.getGrantedAuthorities());
380 GrantedAuthorityImpl referenceUpdate_ga = new CdmAuthority(CdmPermissionClass.REFERENCE, null, EnumSet.of(CRUD.UPDATE), null).asNewGrantedAuthority();
381 grantedAuthorities.add(referenceUpdate_ga);
382 taxonEditor.setGrantedAuthorities(grantedAuthorities);
383 userService.saveOrUpdate(taxonEditor);
384 commitAndStartNewTransaction(null);
385
386 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
387 context = SecurityContextHolder.getContext();
388 context.setAuthentication(authentication);
389
390 Reference book = referenceService.load(BOOK1_UUID);
391 book.setTitleCache("Mobydick", true);
392 Exception exception = null;
393 try {
394 referenceService.saveOrUpdate(book);
395 commitAndStartNewTransaction(null);
396 } catch (AccessDeniedException e){
397 logger.error("Unexpected failure of evaluation.", e);
398 exception = e;
399 } catch (RuntimeException e){
400 logger.error("Unexpected failure of evaluation.", e);
401 exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
402 } finally {
403 // needed in case saveOrUpdate was interrupted by the RuntimeException
404 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
405 endTransaction();
406 startNewTransaction();
407 }
408 Assert.assertNull("must not fail here!", exception);
409 book = referenceService.load(BOOK1_UUID);
410 Assert.assertEquals("Mobydick", book.getTitleCache());
411 }
412
413 @Test
414 public final void testUpateReferenceDeny() {
415
416 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
417 SecurityContext context = SecurityContextHolder.getContext();
418 context.setAuthentication(authentication);
419
420 TaxonBase taxon = taxonService.find(UUID_ACHERONTIA_STYX);
421 taxon.getName().getNomenclaturalReference().setTitleCache("Mobydick", true);
422 Exception exception = null;
423 try {
424 UUID uuid = taxonService.saveOrUpdate(taxon);
425 commitAndStartNewTransaction(null);
426 } catch (AccessDeniedException e){
427 logger.debug("Expected failure of evaluation.", e);
428 exception = e;
429 } catch (RuntimeException e){
430 exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
431 logger.debug("Expected failure of evaluation.", e);
432 } finally {
433 // needed in case saveOrUpdate was interrupted by the RuntimeException
434 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
435 endTransaction();
436 startNewTransaction();
437 }
438 Assert.assertNotNull("must fail here!", exception);
439 }
440
441 @Test
442 public void testChangeOwnPassword(){
443
444 SecurityContext context = SecurityContextHolder.getContext();
445 // authenticate as admin
446 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
447 context.setAuthentication(authentication);
448
449 // User currentUser = (User) context.getAuthentication().getPrincipal();
450
451 String newPass = "poiweorijo";
452 userService.changePassword(PASSWORD_TAXON_EDITOR, newPass);
453 commitAndStartNewTransaction(null);
454
455 // try to re-authenticate user with changed password
456 UsernamePasswordAuthenticationToken newTokenForTaxonEditor = new UsernamePasswordAuthenticationToken("taxonEditor", newPass);
457 authentication = authenticationManager.authenticate(newTokenForTaxonEditor);
458 }
459
460 @Test
461 public void testChangeOthersPasswordAllow(){
462
463 SecurityContext context = SecurityContextHolder.getContext();
464 RuntimeException exception = null;
465
466 // (1) authenticate as admin
467 authentication = authenticationManager.authenticate(tokenForAdmin);
468 context.setAuthentication(authentication);
469
470
471 try{
472 userService.changePasswordForUser("taxonomist", "zuaisd");
473 commitAndStartNewTransaction(null);
474 } catch (AccessDeniedException e){
475 logger.error("Unexpected failure of evaluation.", e);
476 exception = e;
477 } catch (RuntimeException e){
478 exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
479 logger.error("Unexpected failure of evaluation.", exception);
480 } finally {
481 // needed in case saveOrUpdate was interrupted by the RuntimeException
482 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
483 endTransaction();
484 startNewTransaction();
485 }
486 Assert.assertNull("must not fail here!", exception);
487
488 // ok, now try authenticating taxonomist with new password
489 UsernamePasswordAuthenticationToken newToken = new UsernamePasswordAuthenticationToken("taxonomist", "zuaisd");
490 authentication = authenticationManager.authenticate(newToken);
491 }
492
493 @Test
494 public void testChangeOthersPasswordDeny(){
495
496 SecurityContext context = SecurityContextHolder.getContext();
497 RuntimeException exception = null;
498
499 // (2) authenticate as under privileged user - not an admin !!!
500 authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
501 context.setAuthentication(authentication);
502
503 // check test preconditions user name and authorities
504 Assert.assertEquals("descriptionEditor", context.getAuthentication().getName());
505 Collection<? extends GrantedAuthority> authorities = context.getAuthentication().getAuthorities();
506 for(GrantedAuthority authority: authorities){
507 // role prefix 'ROLE_' is defined in org.springframework.security.access.vote.RoleVoter !!!
508 Assert.assertNotSame("user must not have authority 'ROLE_ADMIN'", "ROLE_ADMIN", authority.getAuthority());
509 }
510 // finally perform the test :
511 try{
512 userService.changePasswordForUser("partEditor", "poiweorijo");
513 commitAndStartNewTransaction(null);
514 } catch (AccessDeniedException e){
515 logger.debug("Expected failure of evaluation.", e);
516 exception = e;
517 } catch (RuntimeException e){
518 exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
519 logger.debug("Expected failure of evaluation.", e);
520 } finally {
521 // needed in case saveOrUpdate was interrupted by the RuntimeException
522 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
523 endTransaction();
524 startNewTransaction();
525 }
526 Assert.assertNotNull("must fail here!", exception);
527 }
528
529 @Test
530 public void testUpdateUser(){
531
532 authentication = authenticationManager.authenticate(tokenForAdmin);
533 SecurityContext context = SecurityContextHolder.getContext();
534 context.setAuthentication(authentication);
535 String username = "standardUser";
536 String password = "pw";
537 User user = User.NewInstance(username, password);
538
539 userService.createUser(user);
540 user.setEmailAddress("test@bgbm.org");
541
542 userService.updateUser(user);
543 userService.update(user);
544 userService.saveOrUpdate(user);
545 commitAndStartNewTransaction(null);
546
547 }
548
549 /**
550 * test with admin account - should succeed
551 */
552 @Test
553 public final void testTaxonSaveOrUpdateAllow_1() {
554
555 SecurityContext context = SecurityContextHolder.getContext();
556
557 authentication = authenticationManager.authenticate(tokenForAdmin);
558 context.setAuthentication(authentication);
559 RuntimeException securityException= null;
560
561 TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);
562 Assert.assertFalse(taxon.isDoubtful());
563 taxon.setDoubtful(true);
564 try{
565 taxonService.saveOrUpdate(taxon);
566 commitAndStartNewTransaction(null);
567 } catch (RuntimeException e){
568 securityException = findSecurityRuntimeException(e);
569 logger.error("Unexpected failure of evaluation.", e);
570 } finally {
571 // needed in case saveOrUpdate was interrupted by the RuntimeException
572 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
573 endTransaction();
574 startNewTransaction();
575 }
576 Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
577 // reload taxon
578 taxon = taxonService.find(UUID_ACHERONTIA_STYX);
579 Assert.assertTrue("The change must be persisted", taxon.isDoubtful());
580 }
581
582 /**
583 * test with taxonEditor account - should succeed
584 */
585 @Test
586 public final void testTaxonSaveOrUpdateAllow_2() {
587
588
589 RuntimeException securityException= null;
590 SecurityContext context = SecurityContextHolder.getContext();
591
592 // taxonEditor account - should succeed
593 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
594
595 context.setAuthentication(authentication);
596
597 TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);
598 Assert.assertFalse(taxon.isDoubtful());
599 taxon.setDoubtful(true);
600 try{
601 taxonService.saveOrUpdate(taxon);
602 commitAndStartNewTransaction(null);
603 } catch (RuntimeException e){
604 securityException = findSecurityRuntimeException(e);
605 logger.error("Unexpected failure of evaluation.", e);
606 } finally {
607 // needed in case saveOrUpdate was interrupted by the RuntimeException
608 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
609 endTransaction();
610 startNewTransaction();
611 }
612 Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
613 // reload taxon
614 taxon = taxonService.find(UUID_ACHERONTIA_STYX);
615 Assert.assertTrue("The change must be persited", taxon.isDoubtful());
616 }
617
618 /**
619 * test with tokenForDescriptionEditor account - should fail
620 */
621 @Test
622 public final void testTaxonSaveOrUpdateDeny_2() {
623
624 SecurityContext context = SecurityContextHolder.getContext();
625 RuntimeException securityException = null;
626
627 authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
628 context.setAuthentication(authentication);
629
630 TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);
631
632 Assert.assertFalse(taxon.isDoubtful());
633 taxon.setDoubtful(true);
634 try {
635 taxonService.saveOrUpdate(taxon);
636 commitAndStartNewTransaction(null);
637 } catch (RuntimeException e){
638 securityException = findSecurityRuntimeException(e);
639 logger.debug("Expected failure of evaluation.", securityException);
640 } finally {
641 // needed in case saveOrUpdate was interrupted by the RuntimeException
642 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
643 endTransaction();
644 startNewTransaction();
645 }
646
647 Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
648 // reload taxon
649 taxon = taxonService.find(UUID_ACHERONTIA_STYX);
650 Assert.assertFalse("The change must not be persited", taxon.isDoubtful());
651 }
652
653 @Test
654 public final void testTaxonPublishAllow_ROLE_ADMIN() {
655
656 SecurityContext context = SecurityContextHolder.getContext();
657
658 authentication = authenticationManager.authenticate(tokenForAdmin);
659 context.setAuthentication(authentication);
660 RuntimeException securityException= null;
661
662 Taxon taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
663
664 boolean lastIsPublish = taxon.isPublish();
665 taxon.setPublish(!lastIsPublish);
666 try{
667 taxonService.saveOrUpdate(taxon);
668 commitAndStartNewTransaction(null);
669 } catch (RuntimeException e){
670 securityException = findSecurityRuntimeException(e);
671 logger.error("Unexpected failure of evaluation.", e);
672 } finally {
673 // needed in case saveOrUpdate was interrupted by the RuntimeException
674 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
675 endTransaction();
676 startNewTransaction();
677 }
678 Assert.assertNull("evaluation must not fail since the user has ROLE_ADMIN, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
679 // reload taxon
680 taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
681 Assert.assertTrue("The change must be persisted", taxon.isPublish() != lastIsPublish);
682 }
683
684
685 /**
686 * test with Taxonomist account which has the ROLE_PUBLISH
687 */
688 @Test
689 public final void testTaxonPublishAllow_ROLE_PUBLISH() {
690
691 SecurityContext context = SecurityContextHolder.getContext();
692
693 authentication = authenticationManager.authenticate(tokenForTaxonomist);
694 context.setAuthentication(authentication);
695 RuntimeException securityException= null;
696
697 Taxon taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
698
699 boolean lastIsPublish = taxon.isPublish();
700 taxon.setPublish(!lastIsPublish);
701 try{
702 taxonService.saveOrUpdate(taxon);
703 commitAndStartNewTransaction(null);
704 } catch (RuntimeException e){
705 securityException = findSecurityRuntimeException(e);
706 logger.error("Unexpected failure of evaluation.", e);
707 } finally {
708 // needed in case saveOrUpdate was interrupted by the RuntimeException
709 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
710 endTransaction();
711 startNewTransaction();
712 }
713 Assert.assertNull("evaluation must not fail since the user has ROLE_ADMIN, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
714 // reload taxon
715 taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
716 Assert.assertTrue("The change must be persisted", taxon.isPublish() != lastIsPublish);
717 }
718
719 /**
720 * test with TaxonEditor account which has not the ROLE_PUBLISH
721 */
722 @Test
723 public final void testTaxonPublishDeny() {
724
725 SecurityContext context = SecurityContextHolder.getContext();
726
727 authentication = authenticationManager.authenticate(tokenForTaxonEditor);
728 context.setAuthentication(authentication);
729 RuntimeException securityException= null;
730
731 Taxon taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
732
733 boolean lastIsPublish = taxon.isPublish();
734 taxon.setPublish(!lastIsPublish);
735 try {
736 taxonService.saveOrUpdate(taxon);
737 commitAndStartNewTransaction(null);
738 } catch (RuntimeException e){
739 securityException = findSecurityRuntimeException(e);
740 logger.debug("Expected failure of evaluation.", securityException);
741 } finally {
742 // needed in case saveOrUpdate was interrupted by the RuntimeException
743 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
744 endTransaction();
745 startNewTransaction();
746 }
747
748 Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
749 // reload taxon
750 taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
751 Assert.assertTrue("The taxon must be unchanged", taxon.isPublish() == lastIsPublish);
752 }
753
754 /**
755 * test with admin account - should succeed
756 */
757 @Test
758 public final void testTaxonDeleteAllow_1() {
759
760 SecurityContext context = SecurityContextHolder.getContext();
761
762 authentication = authenticationManager.authenticate(tokenForAdmin);
763 context.setAuthentication(authentication);
764 RuntimeException securityException= null;
765
766 TaxonBase<?> taxon = taxonService.load(UUID_LACTUCA);
767 taxonService.delete(taxon);
768 commitAndStartNewTransaction(null);
769
770
771
772
773 Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
774 // reload taxon
775 taxon = taxonService.load(UUID_LACTUCA);
776 Assert.assertNull("The taxon must be deleted", taxon);
777 }
778
779 /**
780 * test with admin account - should succeed
781 */
782 @Test
783 public final void testTaxonDeleteAllow_2() {
784
785 SecurityContext context = SecurityContextHolder.getContext();
786
787 authentication = authenticationManager.authenticate(tokenForAdmin);
788 context.setAuthentication(authentication);
789 RuntimeException securityException= null;
790
791 Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
792 try{
793 // try {
794 DeleteResult result = taxonService.deleteTaxon(taxon, null, null);
795 /*} catch (DataChangeNoRollbackException e) {
796 Assert.fail();
797 }*/
798 if (!result.isOk()){
799 Assert.fail();
800 }
801 commitAndStartNewTransaction(null);
802 } catch (RuntimeException e){
803 securityException = findSecurityRuntimeException(e);
804 logger.error("Unexpected failure of evaluation.", e);
805 } finally {
806 // needed in case saveOrUpdate was interrupted by the RuntimeException
807 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
808 endTransaction();
809 startNewTransaction();
810 }
811 Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
812 // reload taxon
813
814 taxon = (Taxon)taxonService.find(UUID_ACHERONTINII);
815 Assert.assertNull("The taxon must be deleted", taxon);
816 }
817
818
819 /**
820 * test with tokenForDescriptionEditor account - should fail
821 */
822 @Test
823 public final void testTaxonDeleteDeny() {
824
825 SecurityContext context = SecurityContextHolder.getContext();
826 RuntimeException securityException = null;
827
828 authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
829 context.setAuthentication(authentication);
830
831 Taxon taxon = (Taxon)taxonService.load(UUID_LACTUCA);
832 DeleteResult result = taxonService.deleteTaxon(taxon, null, null);
833 if (!result.isError()) {
834 Assert.fail();
835 }
836 endTransaction();
837 startNewTransaction();
838
839
840 //Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
841 // reload taxon
842 taxon = (Taxon)taxonService.load(UUID_LACTUCA);
843
844 Assert.assertNotNull("The change must still exist", taxon);
845 Assert.assertNotNull("The name must still exist",taxon.getName());
846 }
847
848
849 @Test
850 @Ignore //FIXME: adding taxa to a description must be protected at the side of the Description itself!!
851 // => protecting method TaxonDescription.setTaxon() ?
852 public void testAddDescriptionToTaxon(){
853
854 SecurityContext context = SecurityContextHolder.getContext();
855 authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
856 context.setAuthentication(authentication);
857
858 RuntimeException securityException = null;
859
860 Taxon taxon = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);
861
862 TaxonDescription description = TaxonDescription.NewInstance(taxon);
863 description.setTitleCache("test");
864 try {
865 descriptionService.saveOrUpdate(description);
866 commitAndStartNewTransaction(null);
867 } catch (RuntimeException e){
868 securityException = findSecurityRuntimeException(e);
869 logger.debug("Expected failure of evaluation.", securityException);
870 } finally {
871 // needed in case saveOrUpdate was interrupted by the RuntimeException
872 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
873 endTransaction();
874 startNewTransaction();
875 }
876 /*
877 * Expectation:
878 * The user should not be granted to add the Description to a taxon
879 */
880 Assert.assertNotNull("evaluation should fail since the user is not permitted to edit Taxa", securityException);
881 taxon = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);
882 assertTrue(taxon.getDescriptions().contains(description));
883 }
884
885 @Test
886 public void testMoveDescriptionElement(){
887
888 SecurityContext context = SecurityContextHolder.getContext();
889 authentication = authenticationManager.authenticate(tokenForTaxonomist);
890 context.setAuthentication(authentication);
891
892 RuntimeException securityException = null;
893
894 Taxon t_acherontia_lachesis = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);
895 Taxon t_acherontia_styx = (Taxon)taxonService.load(UUID_ACHERONTIA_STYX);
896
897 TaxonDescription description_acherontia_styx = t_acherontia_styx.getDescriptions().iterator().next();
898 TaxonDescription description_acherontia_lachesis = t_acherontia_lachesis.getDescriptions().iterator().next();
899
900 try {
901 descriptionService.moveDescriptionElementsToDescription(description_acherontia_styx.getElements(), description_acherontia_lachesis, false);
902 commitAndStartNewTransaction(null);
903 } catch (RuntimeException e){
904 securityException = findSecurityRuntimeException(e);
905 logger.debug("Unexpected failure of evaluation.", securityException);
906 } finally {
907 // needed in case saveOrUpdate was interrupted by the RuntimeException
908 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
909 endTransaction();
910 startNewTransaction();
911 }
912 /*
913 * Expectation:
914 */
915 Assert.assertNull("evaluation should not fail since the user has sufficient permissions", securityException);
916
917 }
918
919 // @Ignore // FIXME http://dev.e-taxonomy.eu/trac/ticket/4081 : #4081 (TaxonNodeServiceImpl.makeTaxonNodeASynonymOfAnotherTaxonNode() requires TAXONNAMEBASE.[UPDATE])
920 @Test
921 public void testAcceptedTaxonToSynomym(){
922
923 SecurityContext context = SecurityContextHolder.getContext();
924 authentication = authenticationManager.authenticate(tokenForPartEditor);
925 context.setAuthentication(authentication);
926
927 RuntimeException securityException = null;
928
929 Taxon t_acherontia_lachesis = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);
930 Taxon t_acherontia_styx = (Taxon)taxonService.load(UUID_ACHERONTIA_STYX);
931
932
933 TaxonNode n_acherontia_lachesis = t_acherontia_lachesis.getTaxonNodes().iterator().next();
934 TaxonNode n_acherontia_styx = t_acherontia_styx.getTaxonNodes().iterator().next();
935
936 int numOfSynonymsBefore_styx = t_acherontia_styx.getSynonyms().size();
937 int numOfSynonymsBefore_lachesis = t_acherontia_lachesis.getSynonyms().size();
938
939 UUID synonymUuid = null; // UUID.randomUUID();
940
941 try {
942 Synonym synonym = taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_lachesis, n_acherontia_styx, SynonymRelationshipType.SYNONYM_OF(), null, null);
943 synonymUuid = synonym.getUuid();
944 taxonService.saveOrUpdate(synonym);
945 commitAndStartNewTransaction(null);
946 } catch (RuntimeException e){
947 securityException = findSecurityRuntimeException(e);
948 logger.error("Unexpected Exception ", e);
949 Assert.fail("Unexpected Exception: " + e.getMessage());
950 } finally {
951 // needed in case saveOrUpdate was interrupted by the RuntimeException
952 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
953 endTransaction();
954 startNewTransaction();
955 }
956 /*
957 * Expectation:
958 */
959 Assert.assertNull("evaluation should not fail since the user has sufficient permissions", securityException);
960
961 // reload from db and check assertions
962 t_acherontia_styx = (Taxon)taxonService.load(UUID_ACHERONTIA_STYX);
963 Assert.assertEquals("Acherontia styx now must have a synonym", numOfSynonymsBefore_styx + numOfSynonymsBefore_lachesis + 1, t_acherontia_styx.getSynonyms().size());
964 Assert.assertTrue("Acherontia lachesis now must be a synonym", taxonService.load(synonymUuid) instanceof Synonym);
965 Assert.assertNull("The old TaxonNode should no longer exist", taxonNodeService.find(n_acherontia_lachesis.getUuid()));
966 }
967
968 @Test
969 public void testCreateDescriptionWithElement(){
970
971 SecurityContext context = SecurityContextHolder.getContext();
972 authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
973 context.setAuthentication(authentication);
974
975 TaxonDescription description = null;
976 RuntimeException securityException = null;
977 Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
978 Assert.assertTrue("taxon must not yet have descriptions", taxon.getDescriptions().size() == 0);
979
980
981 // 1) test for failure - description element but no feature
982 description = TaxonDescription.NewInstance(taxon);
983 DescriptionElementBase textdataNoFeature = TextData.NewInstance();
984 description.addElement(textdataNoFeature);
985
986 assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));
987 try{
988 descriptionService.saveOrUpdate(description);
989 commitAndStartNewTransaction(null);
990 } catch (RuntimeException e){
991 securityException = findSecurityRuntimeException(e);
992 logger.error("RuntimeException caught");
993 logger.debug("Expected failure of evaluation.", securityException);
994 } finally {
995 // needed in case saveOrUpdate was interrupted by the RuntimeException
996 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
997 endTransaction();
998 startNewTransaction();
999 }
1000
1001 Assert.assertNotNull("evaluation should fail", securityException);
1002 taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1003 Set<TaxonDescription> descriptions = taxon.getDescriptions();
1004 assertTrue("taxon must not have any description", descriptions.size() == 0);
1005
1006 }
1007
1008 @Test
1009 public void testCreateDescriptionWithElementDeny_1(){
1010
1011 SecurityContext context = SecurityContextHolder.getContext();
1012 authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
1013 context.setAuthentication(authentication);
1014
1015 TaxonDescription description = null;
1016 RuntimeException securityException = null;
1017 Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1018 Assert.assertTrue("taxon must not yet have descriptions", taxon.getDescriptions().size() == 0);
1019
1020 // 2) test for failure - description element but not granted feature
1021 description = TaxonDescription.NewInstance(taxon);
1022 DescriptionElementBase descriptionText = TextData.NewInstance(Feature.DESCRIPTION());
1023 description.addElement(descriptionText);
1024
1025 securityException = null;
1026 assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));
1027 try{
1028 descriptionService.saveOrUpdate(description);
1029 commitAndStartNewTransaction(null);
1030 } catch (RuntimeException e){
1031 securityException = findSecurityRuntimeException(e);
1032 logger.debug("Expected failure of evaluation.", securityException);
1033 } finally {
1034 // needed in case saveOrUpdate was interrupted by the RuntimeException
1035 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1036 endTransaction();
1037 startNewTransaction();
1038 }
1039
1040 Assert.assertNotNull("evaluation should fail", securityException);
1041 taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1042 Set<TaxonDescription> descriptions = taxon.getDescriptions();
1043 assertTrue("taxon must not have any description", descriptions.size() == 0);
1044
1045 }
1046
1047 @Test
1048 public void testCreateDescriptionWithElementDeny_2(){
1049
1050 SecurityContext context = SecurityContextHolder.getContext();
1051 authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
1052 context.setAuthentication(authentication);
1053
1054 TaxonDescription description = null;
1055 RuntimeException securityException = null;
1056 Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1057 Assert.assertTrue("taxon must not yet have descriptions", taxon.getDescriptions().size() == 0);
1058
1059 // 3) test for failure
1060 description = TaxonDescription.NewInstance(taxon);
1061 DescriptionElementBase ecologyText = TextData.NewInstance(Feature.ECOLOGY());
1062 description.addElement(ecologyText);
1063
1064 securityException = null;
1065 assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));
1066 try{
1067 descriptionService.saveOrUpdate(description);
1068 commitAndStartNewTransaction(null);
1069 } catch (RuntimeException e){
1070 securityException = findSecurityRuntimeException(e);
1071 logger.error("Unexpected failure of evaluation.", e);
1072 } finally {
1073 // needed in case saveOrUpdate was interrupted by the RuntimeException
1074 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1075 endTransaction();
1076 startNewTransaction();
1077 }
1078
1079 Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
1080 taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1081 Set<TaxonDescription> descriptions = taxon.getDescriptions();
1082 assertTrue("taxon must now have one description", descriptions.size() == 1);
1083 assertTrue("description should have one description element", descriptions.iterator().next().getElements().size() == 1);
1084 }
1085
1086 @Test
1087 public void testSaveSynonymAllow(){
1088
1089 SecurityContext context = SecurityContextHolder.getContext();
1090 RuntimeException securityException = null;
1091
1092 // 1) test for success
1093 authentication = authenticationManager.authenticate(tokenForTaxonomist);
1094 context.setAuthentication(authentication);
1095
1096 Synonym syn = Synonym.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null);
1097 UUID synUuid = UUID.randomUUID();
1098 syn.setUuid(synUuid);
1099 try{
1100 taxonService.saveOrUpdate(syn);
1101 logger.debug("will commit ...");
1102 commitAndStartNewTransaction(null);
1103 } catch (RuntimeException e){
1104 securityException = findSecurityRuntimeException(e);
1105 logger.error("Unexpected failure of evaluation.", e);
1106 } finally {
1107 // needed in case saveOrUpdate was interrupted by the RuntimeException
1108 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1109 endTransaction();
1110 startNewTransaction();
1111 }
1112 Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
1113 Assert.assertNotNull("The new Synonym must be persited", taxonService.find(synUuid));
1114 }
1115
1116 @Test
1117 public void testSaveSynonymDenial(){
1118
1119 SecurityContext context = SecurityContextHolder.getContext();
1120 RuntimeException securityException = null;
1121 // 2) test for denial
1122 authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
1123 context.setAuthentication(authentication);
1124 securityException = null;
1125 Synonym syn = Synonym.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null);
1126 UUID synUuid = syn.getUuid();
1127 try{
1128 taxonService.saveOrUpdate(syn);
1129 logger.debug("will commit ...");
1130 commitAndStartNewTransaction(null);
1131 } catch (RuntimeException e){
1132 securityException = findSecurityRuntimeException(e);
1133 logger.debug("Expected failure of evaluation: " + securityException.getClass());
1134 } finally {
1135 // needed in case saveOrUpdate was interrupted by the RuntimeException
1136 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1137 endTransaction();
1138 startNewTransaction();
1139 }
1140
1141 Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
1142 Assert.assertNull("The Synonym must not be persited", taxonService.find(synUuid));
1143 }
1144
1145 @Test
1146 public void testEditPartOfClassificationAllow(){
1147
1148 authentication = authenticationManager.authenticate(tokenForPartEditor);
1149 SecurityContext context = SecurityContextHolder.getContext();
1150 context.setAuthentication(authentication);
1151 RuntimeException securityException = null;
1152 Classification classification = classificationService.load(UUID.fromString("aeee7448-5298-4991-b724-8d5b75a0a7a9"));
1153 // test for success
1154 TaxonNode acherontia_node = taxonNodeService.load(ACHERONTIA_NODE_UUID);
1155 long numOfChildNodes = acherontia_node.getChildNodes().size();
1156 TaxonNode childNode = acherontia_node.addChildTaxon(Taxon.NewInstance(BotanicalName.NewInstance(Rank.SPECIES()), null), null, null);
1157
1158 try{
1159 taxonNodeService.saveOrUpdate(acherontia_node);
1160 commitAndStartNewTransaction(null);
1161 } catch (RuntimeException e){
1162 securityException = findSecurityRuntimeException(e);
1163 logger.error("Unexpected failure of evaluation.", securityException);
1164 } finally {
1165 // needed in case saveOrUpdate was interrupted by the RuntimeException
1166 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1167 endTransaction();
1168 startNewTransaction();
1169 }
1170
1171 acherontia_node = taxonNodeService.load(ACHERONTIA_NODE_UUID);
1172 Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
1173 Assert.assertEquals("the acherontia_node must now have one more child node ", numOfChildNodes + 1 , acherontia_node.getChildNodes().size());
1174 }
1175
1176 @Test
1177 public void testEditPartOfClassificationDeny(){
1178
1179 authentication = authenticationManager.authenticate(tokenForPartEditor);
1180 SecurityContext context = SecurityContextHolder.getContext();
1181 context.setAuthentication(authentication);
1182 RuntimeException securityException = null;
1183
1184 // test for denial
1185 securityException = null;
1186 TaxonNode acherontiini_node = taxonNodeService.load(ACHERONTIINI_NODE_UUID);
1187 int numOfChildNodes = acherontiini_node.getCountChildren();
1188 acherontiini_node.addChildTaxon(Taxon.NewInstance(BotanicalName.NewInstance(Rank.GENUS()), null), null, null);
1189
1190 try{
1191 logger.debug("==============================");
1192 taxonNodeService.saveOrUpdate(acherontiini_node);
1193 commitAndStartNewTransaction(null);
1194 } catch (RuntimeException e){
1195 securityException = findSecurityRuntimeException(e);
1196 logger.debug("Expected failure of evaluation.", securityException);
1197 } finally {
1198 // needed in case saveOrUpdate was interrupted by the RuntimeException
1199 // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1200 endTransaction();
1201 startNewTransaction();
1202 }
1203
1204 acherontiini_node = taxonNodeService.load(ACHERONTIINI_NODE_UUID);
1205 Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
1206 Assert.assertEquals("the number of child nodes must be unchanged ", numOfChildNodes , acherontiini_node.getChildNodes().size());
1207
1208 }
1209
1210 /* (non-Javadoc)
1211 * @see eu.etaxonomy.cdm.test.integration.CdmIntegrationTest#createTestData()
1212 */
1213 @Override
1214 protected void createTestDataSet() throws FileNotFoundException {
1215 // TODO Auto-generated method stub
1216
1217 }
1218
1219 }