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