Project

General

Profile

Download (51.3 KB) Statistics
| Branch: | Tag: | Revision:
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.metadata.SecReferenceHandlingEnum;
49
import eu.etaxonomy.cdm.model.name.Rank;
50
import eu.etaxonomy.cdm.model.name.TaxonName;
51
import eu.etaxonomy.cdm.model.name.TaxonNameFactory;
52
import eu.etaxonomy.cdm.model.permission.CRUD;
53
import eu.etaxonomy.cdm.model.permission.GrantedAuthorityImpl;
54
import eu.etaxonomy.cdm.model.permission.Operation;
55
import eu.etaxonomy.cdm.model.permission.PermissionClass;
56
import eu.etaxonomy.cdm.model.permission.User;
57
import eu.etaxonomy.cdm.model.reference.Reference;
58
import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
59
import eu.etaxonomy.cdm.model.taxon.Synonym;
60
import eu.etaxonomy.cdm.model.taxon.SynonymType;
61
import eu.etaxonomy.cdm.model.taxon.Taxon;
62
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
63
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
64
import eu.etaxonomy.cdm.persistence.permission.CdmAuthority;
65
import eu.etaxonomy.cdm.persistence.permission.CdmAuthorityParsingException;
66
import eu.etaxonomy.cdm.persistence.permission.ICdmPermissionEvaluator;
67
import eu.etaxonomy.cdm.persistence.query.MatchMode;
68
import eu.etaxonomy.cdm.test.unitils.CleanSweepInsertLoadStrategy;
69

    
70
@DataSet(loadStrategy=CleanSweepInsertLoadStrategy.class)
71
public class SecurityTest extends AbstractSecurityTestBase{
72

    
73
    private static final Logger logger = Logger.getLogger(SecurityTest.class);
74

    
75
    @SpringBeanByType
76
    private ITaxonService taxonService;
77

    
78
    @SpringBeanByType
79
    private INameService nameService;
80

    
81
    @SpringBeanByType
82
    private IReferenceService referenceService;
83

    
84
    @SpringBeanByType
85
    private ITaxonNodeService taxonNodeService;
86

    
87
    @SpringBeanByType
88
    private IDescriptionService descriptionService;
89

    
90
    @SpringBeanByType
91
    private IUserService userService;
92

    
93
    @SpringBeanByType
94
    private IClassificationService classificationService;
95

    
96
    @SpringBeanByType
97
    private AuthenticationManager authenticationManager;
98

    
99
    @SpringBeanByType
100
    private SaltSource saltSource;
101

    
102
    @SpringBeanByType
103
    private PasswordEncoder passwordEncoder;
104

    
105
    @SpringBean("cdmPermissionEvaluator")
106
    private ICdmPermissionEvaluator permissionEvaluator;
107

    
108
    @TestDataSource
109
    protected DataSource dataSource;
110

    
111
    private Authentication authentication;
112

    
113
    /**
114
     * no assertions in this test, since it is only used to create password hashes for test data
115
     */
116
    @Test
117
    public void testEncryptPassword(){
118

    
119
        String password = PASSWORD_ADMIN;
120
        User user = User.NewInstance("userManager", "");
121

    
122
        Object salt = this.saltSource.getSalt(user);
123
        String passwordEncrypted = passwordEncoder.encodePassword(password, salt);
124
        logger.info("encrypted password: " + passwordEncrypted );
125
    }
126

    
127
    @Test
128
    @DataSet
129
    public void testHasPermission(){
130

    
131
        Taxon taxon = Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.GENUS()),null);
132

    
133
        authentication = authenticationManager.authenticate(tokenForTaxonomist);
134
        boolean hasPermission = permissionEvaluator.hasPermission(authentication, taxon, Operation.UPDATE);
135
        assertTrue(hasPermission);
136

    
137
        authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
138
        hasPermission = permissionEvaluator.hasPermission(authentication, taxon, Operation.UPDATE);
139
        assertFalse(hasPermission);
140
    }
141

    
142
    @Test
143
    @DataSet
144
    public void testListByUsernameAllow(){
145

    
146
        authentication = authenticationManager.authenticate(tokenForTaxonomist);
147
        SecurityContext context = SecurityContextHolder.getContext();
148
        context.setAuthentication(authentication);
149

    
150
        List<User> userList = userService.listByUsername("Editor", MatchMode.ANYWHERE, null, null, 0, null, null);
151
        Assert.assertTrue("The user list must have elements", userList.size() > 0 );
152
    }
153

    
154
    @Test
155
    @DataSet
156
    public void testUserService_CreateDeny(){
157

    
158
        authentication = authenticationManager.authenticate(tokenForTaxonomist);
159
        SecurityContext context = SecurityContextHolder.getContext();
160
        context.setAuthentication(authentication);
161

    
162
        RuntimeException exception = null;
163
        try {
164
            userService.createUser(User.NewInstance("new guy", "alkjdsfalkj"));
165
            commitAndStartNewTransaction(null);
166
        } catch (AccessDeniedException e){
167
            logger.debug("Expected failure of evaluation.", e);
168
            exception = e;
169
        } catch (RuntimeException e){
170
            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
171
            logger.debug("Expected failure of evaluation.", e);
172
        } finally {
173
            // needed in case saveOrUpdate was interrupted by the RuntimeException
174
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
175
            endTransaction();
176
            startNewTransaction();
177
        }
178
        Assert.assertNotNull("Must fail here!", exception);
179

    
180
    }
181

    
182
    @Test
183
    @DataSet
184
    public void testUserService_CreateAllow(){
185

    
186
        authentication = authenticationManager.authenticate(tokenForUserManager);
187
        SecurityContext context = SecurityContextHolder.getContext();
188
        context.setAuthentication(authentication);
189

    
190
        RuntimeException exception = null;
191
        try {
192
            userService.createUser(User.NewInstance("new guy", "alkjdsfalkj"));
193
            commitAndStartNewTransaction(null);
194
        } catch (AccessDeniedException e){
195
            logger.error("Unexpected failure of evaluation.", e);
196
            exception = e;
197
        } catch (RuntimeException e){
198
            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
199
            logger.error("unexpected failure of evaluation.", exception);
200
        } finally {
201
            // needed in case saveOrUpdate was interrupted by the RuntimeException
202
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
203
            endTransaction();
204
            startNewTransaction();
205
        }
206
        Assert.assertNull("Must not fail here!", exception);
207

    
208
    }
209

    
210

    
211
    @Test
212
    @DataSet
213
    @Ignore // FIXME https://dev.e-taxonomy.eu/redmine/issues/3098
214
    public void testHasPermissions(){
215

    
216
        Taxon taxon = Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.GENUS()),null);
217

    
218
        authentication = authenticationManager.authenticate(tokenForTaxonomist);
219
        boolean hasPermission = permissionEvaluator.hasPermission(authentication, taxon, Operation.ALL);
220
        assertTrue(hasPermission);
221
    }
222

    
223

    
224
    /**
225
     * Test method for {@link eu.etaxonomy.cdm.api.service.TaxonServiceImpl#saveTaxon(eu.etaxonomy.cdm.model.taxon.TaxonBase)}.
226
     */
227
    @Test
228
    public final void testSaveTaxon() {
229

    
230
        authentication = authenticationManager.authenticate(tokenForAdmin);
231
        SecurityContext context = SecurityContextHolder.getContext();
232
        context.setAuthentication(authentication);
233

    
234
        Taxon expectedTaxon = Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null);
235
        expectedTaxon.getName().setTitleCache("Newby admin", true);
236
        UUID uuid = taxonService.save(expectedTaxon).getUuid();
237
        commitAndStartNewTransaction(null);
238
        TaxonBase<?> actualTaxon = taxonService.load(uuid);
239
        assertEquals(expectedTaxon, actualTaxon);
240

    
241
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
242
        context = SecurityContextHolder.getContext();
243
        context.setAuthentication(authentication);
244
        expectedTaxon = Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.GENUS()), null);
245
        expectedTaxon.getName().setTitleCache("Newby taxonEditor", true);
246
        uuid = taxonService.saveOrUpdate(expectedTaxon);
247
        commitAndStartNewTransaction(null);
248
        actualTaxon = taxonService.load(uuid);
249
        assertEquals(expectedTaxon, actualTaxon);
250

    
251
    }
252

    
253
    @Test
254
    public final void testSaveNameAllow() {
255

    
256
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
257
        SecurityContext context = SecurityContextHolder.getContext();
258
        context.setAuthentication(authentication);
259

    
260
        TaxonName newName = TaxonNameFactory.NewZoologicalInstance(Rank.SPECIES());
261
        newName.setTitleCache("Newby taxonEditor", true);
262
        UUID uuid = nameService.saveOrUpdate(newName);
263
        commitAndStartNewTransaction(null);
264
        TaxonName savedName = nameService.load(uuid);
265
        assertEquals(newName, savedName);
266
    }
267

    
268

    
269
    @Test
270
    @Ignore  //#5829  should be fixed as soon as possible
271
    public final void testReuseNameAllow() {
272

    
273
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
274
        SecurityContext context = SecurityContextHolder.getContext();
275
        context.setAuthentication(authentication);
276

    
277
        TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);
278
        TaxonName n_acherontia_thetis = taxon.getName();
279

    
280
        Reference sec = ReferenceFactory.newGeneric();
281
        sec.setUuid(UUID.fromString("bd7e4a15-6403-49a9-a6df-45b46fa99efd"));
282
        Taxon newTaxon = Taxon.NewInstance(n_acherontia_thetis, sec);
283
        Exception exception = null;
284
        try {
285
            taxonService.save(newTaxon);
286
            commitAndStartNewTransaction(null);
287
        } catch (AccessDeniedException e){
288
            logger.error("Unexpected failure of evaluation.", e);
289
            exception = e;
290
        } catch (RuntimeException e){
291
            logger.error("Unexpected failure of evaluation.", e);
292
            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
293
        } finally {
294
            // needed in case saveOrUpdate was interrupted by the RuntimeException
295
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
296
            endTransaction();
297
            startNewTransaction();
298
        }
299
        Assert.assertNull("must not fail here!", exception);
300
    }
301

    
302
    @Test
303
    public final void testMakeTaxonNodeASynonymOfAnotherTaxonNodeAllow_1() {
304

    
305
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
306
        SecurityContext context = SecurityContextHolder.getContext();
307
        context.setAuthentication(authentication);
308

    
309
        Reference book = referenceService.load(BOOK1_UUID);
310

    
311
        TaxonNode n_acherontia_styx = taxonNodeService.find(ACHERONTIA_STYX_NODE_UUID);
312
        TaxonNode n_acherontia_lachersis = taxonNodeService.find(ACHERONTIA_LACHESIS_NODE_UUID);
313

    
314
        Exception exception = null;
315
        try {
316
            taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_styx, n_acherontia_lachersis, SynonymType.HETEROTYPIC_SYNONYM_OF(), book , "33", SecReferenceHandlingEnum.KeepOrWarn, true);
317
            commitAndStartNewTransaction(null);
318
        } catch (AccessDeniedException e){
319
            logger.error("Unexpected failure of evaluation.", e);
320
            exception = e;
321
        } catch (RuntimeException e){
322
            logger.error("Unexpected failure of evaluation.", e);
323
            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
324
        }finally {
325
            // needed in case saveOrUpdate was interrupted by the RuntimeException
326
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
327
            endTransaction();
328
            startNewTransaction();
329
        }
330
        Assert.assertNull("must not fail here!", exception);
331
    }
332

    
333
    @Test
334
    public final void testMakeTaxonNodeASynonymOfAnotherTaxonNodeAllow_2() {
335

    
336
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
337
        SecurityContext context = SecurityContextHolder.getContext();
338
        context.setAuthentication(authentication);
339

    
340
        Reference book = referenceService.load(BOOK1_UUID);
341

    
342
        TaxonNode n_acherontia_styx = taxonNodeService.find(ACHERONTIA_STYX_NODE_UUID);
343
        TaxonNode n_acherontia_lachersis = taxonNodeService.find(ACHERONTIA_LACHESIS_NODE_UUID);
344

    
345
        Exception exception = null;
346
        try {
347
            taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_lachersis, n_acherontia_styx, SynonymType.HOMOTYPIC_SYNONYM_OF(), book , "33", null, true);
348
            commitAndStartNewTransaction(null);
349
        } catch (AccessDeniedException e){
350
            logger.error("Unexpected failure of evaluation.", e);
351
            exception = e;
352
        } catch (RuntimeException e){
353
            logger.error("Unexpected failure of evaluation.", e);
354
            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
355
        }  finally {
356
            // needed in case saveOrUpdate was interrupted by the RuntimeException
357
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
358
            endTransaction();
359
            startNewTransaction();
360
        }
361
        Assert.assertNull("must not fail here!", exception);
362
    }
363

    
364
    @Test
365
    public final void testUpdateReferenceAllow() throws CdmAuthorityParsingException {
366

    
367

    
368
        authentication = authenticationManager.authenticate(tokenForUserManager);
369
        SecurityContext context = SecurityContextHolder.getContext();
370
        context.setAuthentication(authentication);
371

    
372
        // add REFERENCE[UPDATE] to taxonEditor
373
        User taxonEditor = userService.load(TAXON_EDITOR_UUID);
374
        Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();
375
        grantedAuthorities.addAll(taxonEditor.getGrantedAuthorities());
376
        GrantedAuthorityImpl referenceUpdate_ga = new CdmAuthority(PermissionClass.REFERENCE, null, EnumSet.of(CRUD.UPDATE), null).asNewGrantedAuthority();
377
        grantedAuthorities.add(referenceUpdate_ga);
378
        taxonEditor.setGrantedAuthorities(grantedAuthorities);
379
        userService.saveOrUpdate(taxonEditor);
380
        commitAndStartNewTransaction(null);
381

    
382
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
383
        context = SecurityContextHolder.getContext();
384
        context.setAuthentication(authentication);
385

    
386
        Reference book = referenceService.load(BOOK1_UUID);
387
        book.setTitleCache("Mobydick", true);
388
        Exception exception = null;
389
        try {
390
            referenceService.saveOrUpdate(book);
391
            commitAndStartNewTransaction(null);
392
        } catch (AccessDeniedException e){
393
            logger.error("Unexpected failure of evaluation.", e);
394
            exception = e;
395
        } catch (RuntimeException e){
396
            logger.error("Unexpected failure of evaluation.", e);
397
            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
398
        } finally {
399
            // needed in case saveOrUpdate was interrupted by the RuntimeException
400
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
401
            endTransaction();
402
            startNewTransaction();
403
        }
404
        Assert.assertNull("must not fail here!", exception);
405
        book = referenceService.load(BOOK1_UUID);
406
        Assert.assertEquals("Mobydick", book.getTitleCache());
407
    }
408

    
409
    @Test
410
    public final void testUpateReferenceDeny() {
411

    
412
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
413
        SecurityContext context = SecurityContextHolder.getContext();
414
        context.setAuthentication(authentication);
415

    
416
        TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);
417
        taxon.getName().getNomenclaturalReference().setTitleCache("Mobydick", true);
418
        Exception exception = null;
419
        try {
420
            taxonService.saveOrUpdate(taxon);
421
            commitAndStartNewTransaction(null);
422
        } catch (AccessDeniedException e){
423
            logger.debug("Expected failure of evaluation.", e);
424
            exception  = e;
425
        } catch (RuntimeException e){
426
            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
427
            logger.debug("Expected failure of evaluation.", e);
428
        } finally {
429
            // needed in case saveOrUpdate was interrupted by the RuntimeException
430
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
431
            endTransaction();
432
            startNewTransaction();
433
        }
434
        Assert.assertNotNull("must fail here!", exception);
435
    }
436

    
437
    @Test
438
    public void testChangeOwnPassword(){
439

    
440
        SecurityContext context = SecurityContextHolder.getContext();
441
        // authenticate as admin
442
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
443
        context.setAuthentication(authentication);
444

    
445
//        User currentUser =  (User) context.getAuthentication().getPrincipal();
446

    
447
        String newPass = "poiweorijo";
448
        userService.changePassword(PASSWORD_TAXON_EDITOR, newPass);
449
        commitAndStartNewTransaction(null);
450

    
451
        // try to re-authenticate user with changed password
452
        UsernamePasswordAuthenticationToken newTokenForTaxonEditor = new UsernamePasswordAuthenticationToken("taxonEditor", newPass);
453
        authentication = authenticationManager.authenticate(newTokenForTaxonEditor);
454
    }
455

    
456
    @Test
457
    public void testChangeOthersPasswordAllow(){
458

    
459
        SecurityContext context = SecurityContextHolder.getContext();
460
        RuntimeException exception = null;
461

    
462
        // (1) authenticate as admin
463
        authentication = authenticationManager.authenticate(tokenForAdmin);
464
        context.setAuthentication(authentication);
465

    
466

    
467
        try{
468
            userService.changePasswordForUser("taxonomist", "zuaisd");
469
            commitAndStartNewTransaction(null);
470
        } catch (AccessDeniedException e){
471
            logger.error("Unexpected failure of evaluation.", e);
472
            exception = e;
473
        } catch (RuntimeException e){
474
            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
475
            logger.error("Unexpected failure of evaluation.", exception);
476
        } finally {
477
            // needed in case saveOrUpdate was interrupted by the RuntimeException
478
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
479
            endTransaction();
480
            startNewTransaction();
481
        }
482
        Assert.assertNull("must not fail here!", exception);
483

    
484
        // ok, now try authenticating taxonomist with new password
485
        UsernamePasswordAuthenticationToken newToken = new UsernamePasswordAuthenticationToken("taxonomist", "zuaisd");
486
        authentication = authenticationManager.authenticate(newToken);
487
    }
488

    
489
    @Test
490
    public void testChangeOthersPasswordDeny(){
491

    
492
        SecurityContext context = SecurityContextHolder.getContext();
493
        RuntimeException exception = null;
494

    
495
        // (2) authenticate as under privileged user - not an admin !!!
496
        authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
497
        context.setAuthentication(authentication);
498

    
499
        // check test preconditions user name and authorities
500
        Assert.assertEquals("descriptionEditor", context.getAuthentication().getName());
501
        Collection<? extends GrantedAuthority> authorities = context.getAuthentication().getAuthorities();
502
        for(GrantedAuthority authority: authorities){
503
            // role prefix 'ROLE_' is defined in org.springframework.security.access.vote.RoleVoter !!!
504
            Assert.assertNotSame("user must not have authority 'ROLE_ADMIN'", "ROLE_ADMIN", authority.getAuthority());
505
        }
506
        // finally perform the test :
507
        try{
508
            userService.changePasswordForUser("partEditor", "poiweorijo");
509
            commitAndStartNewTransaction(null);
510
        } catch (AccessDeniedException e){
511
            logger.debug("Expected failure of evaluation.", e);
512
            exception = e;
513
        } catch (RuntimeException e){
514
            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);
515
            logger.debug("Expected failure of evaluation.", e);
516
        } finally {
517
            // needed in case saveOrUpdate was interrupted by the RuntimeException
518
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
519
            endTransaction();
520
            startNewTransaction();
521
        }
522
        Assert.assertNotNull("must fail here!", exception);
523
    }
524

    
525
    @Test
526
    public void testUpdateUser(){
527

    
528
        authentication = authenticationManager.authenticate(tokenForAdmin);
529
        SecurityContext context = SecurityContextHolder.getContext();
530
        context.setAuthentication(authentication);
531
        String username = "standardUser";
532
        String password = "pw";
533
        User user = User.NewInstance(username, password);
534

    
535
        userService.createUser(user);
536
        user.setEmailAddress("test@bgbm.org");
537

    
538
        userService.updateUser(user);
539
        userService.update(user);
540
        userService.saveOrUpdate(user);
541
        commitAndStartNewTransaction(null);
542

    
543
    }
544

    
545
    /**
546
     * test with admin account - should succeed
547
     */
548
    @Test
549
    public final void testTaxonSaveOrUpdateAllow_1() {
550

    
551
        SecurityContext context = SecurityContextHolder.getContext();
552

    
553
        authentication = authenticationManager.authenticate(tokenForAdmin);
554
        context.setAuthentication(authentication);
555
        RuntimeException securityException= null;
556

    
557
        TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);
558
        Assert.assertFalse(taxon.isDoubtful());
559
        taxon.setDoubtful(true);
560
        try{
561
            taxonService.saveOrUpdate(taxon);
562
            commitAndStartNewTransaction(null);
563
        } catch (RuntimeException e){
564
            securityException  = findSecurityRuntimeException(e);
565
            logger.error("Unexpected failure of evaluation.", e);
566
        } finally {
567
            // needed in case saveOrUpdate was interrupted by the RuntimeException
568
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
569
            endTransaction();
570
            startNewTransaction();
571
        }
572
        Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
573
        // reload taxon
574
        taxon = taxonService.find(UUID_ACHERONTIA_STYX);
575
        Assert.assertTrue("The change must be persisted", taxon.isDoubtful());
576
    }
577

    
578
    /**
579
     * test with taxonEditor account - should succeed
580
     */
581
    @Test
582
    public final void testTaxonSaveOrUpdateAllow_2() {
583

    
584

    
585
        RuntimeException securityException= null;
586
        SecurityContext context = SecurityContextHolder.getContext();
587

    
588
         // taxonEditor account - should succeed
589
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
590

    
591
        context.setAuthentication(authentication);
592

    
593
        TaxonBase<?>  taxon = taxonService.find(UUID_ACHERONTIA_STYX);
594
        Assert.assertFalse(taxon.isDoubtful());
595
        taxon.setDoubtful(true);
596
        try{
597
            taxonService.saveOrUpdate(taxon);
598
            commitAndStartNewTransaction(null);
599
        } catch (RuntimeException e){
600
            securityException  = findSecurityRuntimeException(e);
601
            logger.error("Unexpected failure of evaluation.", e);
602
        } finally {
603
            // needed in case saveOrUpdate was interrupted by the RuntimeException
604
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
605
            endTransaction();
606
            startNewTransaction();
607
        }
608
        Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
609
        // reload taxon
610
        taxon = taxonService.find(UUID_ACHERONTIA_STYX);
611
        Assert.assertTrue("The change must be persited", taxon.isDoubtful());
612
    }
613

    
614
    /**
615
     * test with tokenForDescriptionEditor account - should fail
616
     */
617
    @Test
618
    public final void testTaxonSaveOrUpdateDeny_2() {
619

    
620
        SecurityContext context = SecurityContextHolder.getContext();
621
        RuntimeException securityException = null;
622

    
623
        authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
624
        context.setAuthentication(authentication);
625

    
626
        TaxonBase<?> taxon = taxonService.find(UUID_ACHERONTIA_STYX);
627

    
628
        Assert.assertFalse(taxon.isDoubtful());
629
        taxon.setDoubtful(true);
630
        try {
631
            taxonService.saveOrUpdate(taxon);
632
            commitAndStartNewTransaction(null);
633
        } catch (RuntimeException e){
634
            securityException = findSecurityRuntimeException(e);
635
            logger.debug("Expected failure of evaluation.", securityException);
636
        } finally {
637
            // needed in case saveOrUpdate was interrupted by the RuntimeException
638
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
639
            endTransaction();
640
            startNewTransaction();
641
        }
642

    
643
        Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
644
        // reload taxon
645
        taxon = taxonService.find(UUID_ACHERONTIA_STYX);
646
        Assert.assertFalse("The change must not be persited", taxon.isDoubtful());
647
    }
648

    
649
    @Test
650
    public final void testTaxonPublishAllow_ROLE_ADMIN() {
651

    
652
        SecurityContext context = SecurityContextHolder.getContext();
653

    
654
        authentication = authenticationManager.authenticate(tokenForAdmin);
655
        context.setAuthentication(authentication);
656
        RuntimeException securityException= null;
657

    
658
        Taxon taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
659

    
660
        boolean lastIsPublish = taxon.isPublish();
661
        taxon.setPublish(!lastIsPublish);
662
        try{
663
            taxonService.saveOrUpdate(taxon);
664
            commitAndStartNewTransaction(null);
665
        } catch (RuntimeException e){
666
            securityException  = findSecurityRuntimeException(e);
667
            logger.error("Unexpected failure of evaluation.", e);
668
        } finally {
669
            // needed in case saveOrUpdate was interrupted by the RuntimeException
670
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
671
            endTransaction();
672
            startNewTransaction();
673
        }
674
        Assert.assertNull("evaluation must not fail since the user has ROLE_ADMIN, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
675
        // reload taxon
676
        taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
677
        Assert.assertTrue("The change must be persisted", taxon.isPublish() != lastIsPublish);
678
    }
679

    
680

    
681
    /**
682
     * test with Taxonomist account which has the ROLE_PUBLISH
683
     */
684
    @Test
685
    public final void testTaxonPublishAllow_ROLE_PUBLISH() {
686

    
687
        SecurityContext context = SecurityContextHolder.getContext();
688

    
689
        authentication = authenticationManager.authenticate(tokenForTaxonomist);
690
        context.setAuthentication(authentication);
691
        RuntimeException securityException= null;
692

    
693
        Taxon taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
694

    
695
        boolean lastIsPublish = taxon.isPublish();
696
        taxon.setPublish(!lastIsPublish);
697
        try{
698
            taxonService.saveOrUpdate(taxon);
699
            commitAndStartNewTransaction(null);
700
        } catch (RuntimeException e){
701
            securityException  = findSecurityRuntimeException(e);
702
            logger.error("Unexpected failure of evaluation.", e);
703
        } finally {
704
            // needed in case saveOrUpdate was interrupted by the RuntimeException
705
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
706
            endTransaction();
707
            startNewTransaction();
708
        }
709
        Assert.assertNull("evaluation must not fail since the user has ROLE_ADMIN, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
710
        // reload taxon
711
        taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
712
        Assert.assertTrue("The change must be persisted", taxon.isPublish() != lastIsPublish);
713
    }
714

    
715
    /**
716
     * test with TaxonEditor account which has not the ROLE_PUBLISH
717
     */
718
    @Test
719
    public final void testTaxonPublishDeny() {
720

    
721
        SecurityContext context = SecurityContextHolder.getContext();
722

    
723
        authentication = authenticationManager.authenticate(tokenForTaxonEditor);
724
        context.setAuthentication(authentication);
725
        RuntimeException securityException= null;
726

    
727
        Taxon taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
728

    
729
        boolean lastIsPublish = taxon.isPublish();
730
        taxon.setPublish(!lastIsPublish);
731
        try {
732
            taxonService.saveOrUpdate(taxon);
733
            commitAndStartNewTransaction(null);
734
        } catch (RuntimeException e){
735
            securityException = findSecurityRuntimeException(e);
736
            logger.debug("Expected failure of evaluation.", securityException);
737
        } finally {
738
            // needed in case saveOrUpdate was interrupted by the RuntimeException
739
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
740
            endTransaction();
741
            startNewTransaction();
742
        }
743

    
744
        Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
745
        // reload taxon
746
        taxon = (Taxon) taxonService.find(UUID_ACHERONTIA_STYX);
747
        Assert.assertTrue("The taxon must be unchanged", taxon.isPublish() == lastIsPublish);
748
    }
749

    
750
    /**
751
     * test with admin account - should succeed
752
     */
753
    @Test
754
    public final void testTaxonDeleteAllow_1() {
755

    
756
        SecurityContext context = SecurityContextHolder.getContext();
757

    
758
        authentication = authenticationManager.authenticate(tokenForAdmin);
759
        context.setAuthentication(authentication);
760
        RuntimeException securityException= null;
761

    
762
        TaxonBase<?> taxon = taxonService.load(UUID_LACTUCA);
763
        taxonService.delete(taxon);
764
        commitAndStartNewTransaction(null);
765

    
766
        Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
767
        // reload taxon
768
        taxon = taxonService.load(UUID_LACTUCA);
769
        Assert.assertNull("The taxon must be deleted", taxon);
770
    }
771

    
772
    /**
773
     * test with admin account - should succeed
774
     */
775
    @Test
776
   public final void testTaxonDeleteAllow_2() {
777

    
778
        SecurityContext context = SecurityContextHolder.getContext();
779

    
780
        authentication = authenticationManager.authenticate(tokenForAdmin);
781
        context.setAuthentication(authentication);
782
        RuntimeException securityException= null;
783

    
784
        Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
785
        try{
786
           // try {
787
        	DeleteResult result = taxonService.deleteTaxon(taxon.getUuid(), null, taxon.getTaxonNodes().iterator().next().getClassification().getUuid());
788
            /*} catch (DataChangeNoRollbackException e) {
789
                Assert.fail();
790
            }*/
791
            if (!result.isOk()){
792
            	Assert.fail();
793
            }
794
            commitAndStartNewTransaction(null);
795
        } catch (RuntimeException e){
796
            securityException  = findSecurityRuntimeException(e);
797
            logger.error("Unexpected failure of evaluation.", e);
798
        } finally {
799
            // needed in case saveOrUpdate was interrupted by the RuntimeException
800
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
801
            endTransaction();
802
            startNewTransaction();
803
        }
804
        Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
805
        // reload taxon
806

    
807
        taxon = (Taxon)taxonService.find(UUID_ACHERONTINII);
808
        Assert.assertNull("The taxon must be deleted", taxon);
809
    }
810

    
811

    
812
    /**
813
     * test with tokenForDescriptionEditor account - should fail
814
     */
815
    @Test
816
    public final void testTaxonDeleteDeny() {
817

    
818
        SecurityContext context = SecurityContextHolder.getContext();
819
//        RuntimeException securityException = null;
820

    
821
        authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
822
        context.setAuthentication(authentication);
823

    
824
        Taxon taxon = (Taxon)taxonService.load(UUID_LACTUCA);
825
        try{
826
        DeleteResult result = taxonService.deleteTaxon(taxon.getUuid(), null, null);
827
        if(result.isOk()){
828
            Assert.fail();
829
        }
830
        }catch(PermissionDeniedException e){
831

    
832
        }
833
       endTransaction();
834
       startNewTransaction();
835

    
836

    
837
        //Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
838
        // reload taxon
839
        taxon = (Taxon)taxonService.load(UUID_LACTUCA);
840

    
841
        Assert.assertNotNull("The change must still exist", taxon);
842
        Assert.assertNotNull("The name must still exist",taxon.getName());
843
    }
844

    
845

    
846
    @Test
847
    @Ignore //FIXME: adding taxa to a description must be protected at the side of the Description itself!!
848
            //        => protecting method TaxonDescription.setTaxon() ?
849
    public void testAddDescriptionToTaxon(){
850

    
851
        SecurityContext context = SecurityContextHolder.getContext();
852
        authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
853
        context.setAuthentication(authentication);
854

    
855
        RuntimeException securityException = null;
856

    
857
        Taxon taxon = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);
858

    
859
        TaxonDescription description = TaxonDescription.NewInstance(taxon);
860
        description.setTitleCache("test", true);
861
        try {
862
            descriptionService.saveOrUpdate(description);
863
            commitAndStartNewTransaction(null);
864
        } catch (RuntimeException e){
865
            securityException = findSecurityRuntimeException(e);
866
            logger.debug("Expected failure of evaluation.", securityException);
867
        } finally {
868
            // needed in case saveOrUpdate was interrupted by the RuntimeException
869
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
870
            endTransaction();
871
            startNewTransaction();
872
        }
873
        /*
874
         * Expectation:
875
         * The user should not be granted to add the Description to a taxon
876
         */
877
        Assert.assertNotNull("evaluation should fail since the user is not permitted to edit Taxa", securityException);
878
        taxon = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);
879
        assertTrue(taxon.getDescriptions().contains(description));
880
    }
881

    
882
    @Test
883
    public void testMoveDescriptionElement(){
884

    
885
        SecurityContext context = SecurityContextHolder.getContext();
886
        authentication = authenticationManager.authenticate(tokenForTaxonomist);
887
        context.setAuthentication(authentication);
888

    
889
        RuntimeException securityException = null;
890

    
891
        Taxon t_acherontia_lachesis = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);
892
        Taxon t_acherontia_styx = (Taxon)taxonService.load(UUID_ACHERONTIA_STYX);
893

    
894
        TaxonDescription description_acherontia_styx = t_acherontia_styx.getDescriptions().iterator().next();
895
        TaxonDescription description_acherontia_lachesis = t_acherontia_lachesis.getDescriptions().iterator().next();
896

    
897
        try {
898
            descriptionService.moveDescriptionElementsToDescription(description_acherontia_styx.getElements(), description_acherontia_lachesis, false, true);
899
            commitAndStartNewTransaction(null);
900
        } catch (RuntimeException e){
901
            securityException = findSecurityRuntimeException(e);
902
            logger.debug("Unexpected failure of evaluation.", securityException);
903
        } finally {
904
            // needed in case saveOrUpdate was interrupted by the RuntimeException
905
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
906
            endTransaction();
907
            startNewTransaction();
908
        }
909
        /*
910
         * Expectation:
911
         */
912
        Assert.assertNull("evaluation should not fail since the user has sufficient permissions", securityException);
913

    
914
    }
915

    
916
//    @Ignore // FIXME https://dev.e-taxonomy.eu/redmine/issues/4081 : #4081 (TaxonNodeServiceImpl.makeTaxonNodeASynonymOfAnotherTaxonNode() requires TAXONNAME.[UPDATE])
917
    @Test
918
    public void testAcceptedTaxonToSynomym(){
919

    
920
        SecurityContext context = SecurityContextHolder.getContext();
921
        authentication = authenticationManager.authenticate(tokenForPartEditor);
922
        context.setAuthentication(authentication);
923

    
924
        RuntimeException securityException = null;
925

    
926
        Taxon t_acherontia_lachesis = (Taxon)taxonService.load(ACHERONTIA_LACHESIS_UUID);
927
        UUID name_acherontia_lachesis_uuid = t_acherontia_lachesis.getName().getUuid();
928
        Taxon t_acherontia_styx = (Taxon)taxonService.load(UUID_ACHERONTIA_STYX);
929
        int countSynsBefore = t_acherontia_styx.getSynonyms().size();
930

    
931
        TaxonNode n_acherontia_lachesis = t_acherontia_lachesis.getTaxonNodes().iterator().next();
932
        TaxonNode n_acherontia_styx = t_acherontia_styx.getTaxonNodes().iterator().next();
933

    
934
        int numOfSynonymsBefore_styx = t_acherontia_styx.getSynonyms().size();
935
        int numOfSynonymsBefore_lachesis = t_acherontia_lachesis.getSynonyms().size();
936

    
937

    
938
        try {
939
            taxonNodeService.makeTaxonNodeASynonymOfAnotherTaxonNode(n_acherontia_lachesis, n_acherontia_styx, SynonymType.SYNONYM_OF(), null, null, null, true);
940
//            synonymUuid = synonym.getUuid();
941
//            taxonService.saveOrUpdate(synonym);
942
            commitAndStartNewTransaction(null);
943
        } catch (RuntimeException e){
944
            securityException = findSecurityRuntimeException(e);
945
            logger.error("Unexpected Exception ", e);
946
            Assert.fail("Unexpected Exception: " + e.getMessage());
947
        } finally {
948
            // needed in case saveOrUpdate was interrupted by the RuntimeException
949
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
950
            endTransaction();
951
            startNewTransaction();
952
        }
953
        /*
954
         * Expectation:
955
         */
956
        Assert.assertNull("evaluation should not fail since the user has sufficient permissions", securityException);
957

    
958
        // reload from db and check assertions
959
        t_acherontia_styx = (Taxon)taxonService.load(UUID_ACHERONTIA_STYX);
960
        Assert.assertEquals(numOfSynonymsBefore_styx +1 + numOfSynonymsBefore_lachesis, t_acherontia_styx.getSynonyms().size());
961

    
962
        Assert.assertNotNull(nameService.load(name_acherontia_lachesis_uuid) );
963
        Assert.assertNull("The old TaxonNode should no longer exist", taxonNodeService.find(n_acherontia_lachesis.getUuid()));
964
    }
965

    
966
    @Test
967
    public void testCreateDescriptionWithElement(){
968

    
969
        SecurityContext context = SecurityContextHolder.getContext();
970
        authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
971
        context.setAuthentication(authentication);
972

    
973
        TaxonDescription description = null;
974
        RuntimeException securityException = null;
975
        Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
976
        Assert.assertTrue("taxon must not yet have descriptions", taxon.getDescriptions().size() == 0);
977

    
978

    
979
        // 1) test for failure - description element but no feature
980
        description = TaxonDescription.NewInstance(taxon);
981
        DescriptionElementBase textdataNoFeature = TextData.NewInstance();
982
        description.addElement(textdataNoFeature);
983

    
984
        assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));
985
        try{
986
            descriptionService.saveOrUpdate(description);
987
            commitAndStartNewTransaction(null);
988
        } catch (RuntimeException e){
989
            securityException = findSecurityRuntimeException(e);
990
            logger.error("RuntimeException caught");
991
            logger.debug("Expected failure of evaluation.", securityException);
992
        } finally {
993
            // needed in case saveOrUpdate was interrupted by the RuntimeException
994
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
995
            endTransaction();
996
            startNewTransaction();
997
        }
998

    
999
        Assert.assertNotNull("evaluation should fail", securityException);
1000
        taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1001
        Set<TaxonDescription> descriptions = taxon.getDescriptions();
1002
        assertTrue("taxon must not have any description", descriptions.size() == 0);
1003

    
1004
    }
1005

    
1006
    @Test
1007
    public void testCreateDescriptionWithElementDeny_1(){
1008

    
1009
        SecurityContext context = SecurityContextHolder.getContext();
1010
        authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
1011
        context.setAuthentication(authentication);
1012

    
1013
        TaxonDescription description = null;
1014
        RuntimeException securityException = null;
1015
        Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1016
        Assert.assertTrue("taxon must not yet have descriptions", taxon.getDescriptions().size() == 0);
1017

    
1018
        // 2) test for failure  - description element but not granted feature
1019
        description = TaxonDescription.NewInstance(taxon);
1020
        DescriptionElementBase descriptionText = TextData.NewInstance(Feature.DESCRIPTION());
1021
        description.addElement(descriptionText);
1022

    
1023
        assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));
1024
        try{
1025
            descriptionService.saveOrUpdate(description);
1026
            commitAndStartNewTransaction(null);
1027
        } catch (RuntimeException e){
1028
            securityException = findSecurityRuntimeException(e);
1029
            logger.debug("Expected failure of evaluation.", securityException);
1030
        } finally {
1031
            // needed in case saveOrUpdate was interrupted by the RuntimeException
1032
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1033
            endTransaction();
1034
            startNewTransaction();
1035
        }
1036

    
1037
        Assert.assertNotNull("evaluation should fail", securityException);
1038
        taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1039
        Set<TaxonDescription> descriptions = taxon.getDescriptions();
1040
        assertTrue("taxon must not have any description", descriptions.size() == 0);
1041

    
1042
    }
1043

    
1044
    @Test
1045
    public void testCreateDescriptionWithElementDeny_2(){
1046

    
1047
        SecurityContext context = SecurityContextHolder.getContext();
1048
        authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
1049
        context.setAuthentication(authentication);
1050

    
1051
        TaxonDescription description = null;
1052
        RuntimeException securityException = null;
1053
        Taxon taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1054
        Assert.assertTrue("taxon must not yet have descriptions", taxon.getDescriptions().size() == 0);
1055

    
1056
        // 3) test for failure
1057
        description = TaxonDescription.NewInstance(taxon);
1058
        DescriptionElementBase ecologyText = TextData.NewInstance(Feature.ECOLOGY());
1059
        description.addElement(ecologyText);
1060

    
1061
        assertTrue(permissionEvaluator.hasPermission(authentication, description, "UPDATE"));
1062
        try{
1063
            descriptionService.saveOrUpdate(description);
1064
            commitAndStartNewTransaction(null);
1065
        } catch (RuntimeException e){
1066
            securityException = findSecurityRuntimeException(e);
1067
            logger.error("Unexpected failure of evaluation.", e);
1068
        } finally {
1069
            // needed in case saveOrUpdate was interrupted by the RuntimeException
1070
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1071
            endTransaction();
1072
            startNewTransaction();
1073
        }
1074

    
1075
        Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
1076
        taxon = (Taxon)taxonService.load(UUID_ACHERONTINII);
1077
        Set<TaxonDescription> descriptions = taxon.getDescriptions();
1078
        assertTrue("taxon must now have one description", descriptions.size() == 1);
1079
        assertTrue("description should have one description element", descriptions.iterator().next().getElements().size() == 1);
1080
    }
1081

    
1082
    @Test
1083
    public void testSaveSynonymAllow(){
1084

    
1085
        SecurityContext context = SecurityContextHolder.getContext();
1086
        RuntimeException securityException = null;
1087

    
1088
        // 1) test for success
1089
        authentication = authenticationManager.authenticate(tokenForTaxonomist);
1090
        context.setAuthentication(authentication);
1091

    
1092
        Synonym syn = Synonym.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null);
1093
        UUID synUuid = UUID.randomUUID();
1094
        syn.setUuid(synUuid);
1095
        try{
1096
            taxonService.saveOrUpdate(syn);
1097
            logger.debug("will commit ...");
1098
            commitAndStartNewTransaction(null);
1099
        } catch (RuntimeException e){
1100
            securityException = findSecurityRuntimeException(e);
1101
            logger.error("Unexpected failure of evaluation.", e);
1102
        } finally {
1103
            // needed in case saveOrUpdate was interrupted by the RuntimeException
1104
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1105
            endTransaction();
1106
            startNewTransaction();
1107
        }
1108
        Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
1109
        Assert.assertNotNull("The new Synonym must be persited", taxonService.find(synUuid));
1110
    }
1111

    
1112
    @Test
1113
    public void testSaveSynonymDenial(){
1114

    
1115
        SecurityContext context = SecurityContextHolder.getContext();
1116
        RuntimeException securityException = null;
1117
        // 2) test for denial
1118
        authentication = authenticationManager.authenticate(tokenForDescriptionEditor);
1119
        context.setAuthentication(authentication);
1120
        Synonym syn = Synonym.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null);
1121
        UUID synUuid = syn.getUuid();
1122
        try{
1123
            taxonService.saveOrUpdate(syn);
1124
            logger.debug("will commit ...");
1125
            commitAndStartNewTransaction(null);
1126
        } catch (RuntimeException e){
1127
            securityException = findSecurityRuntimeException(e);
1128
            logger.debug("Expected failure of evaluation: " + securityException.getClass());
1129
        } finally {
1130
            // needed in case saveOrUpdate was interrupted by the RuntimeException
1131
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1132
            endTransaction();
1133
            startNewTransaction();
1134
        }
1135

    
1136
        Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
1137
        Assert.assertNull("The Synonym must not be persited", taxonService.find(synUuid));
1138
    }
1139

    
1140
    @Test
1141
    public void testEditPartOfClassificationAllow(){
1142

    
1143
        authentication = authenticationManager.authenticate(tokenForPartEditor);
1144
        SecurityContext context = SecurityContextHolder.getContext();
1145
        context.setAuthentication(authentication);
1146
        RuntimeException securityException = null;
1147
        classificationService.load(UUID.fromString("aeee7448-5298-4991-b724-8d5b75a0a7a9"));
1148
        // test for success
1149
        TaxonNode acherontia_node = taxonNodeService.load(ACHERONTIA_NODE_UUID);
1150
        long numOfChildNodes = acherontia_node.getChildNodes().size();
1151
        TaxonNode acherontia_child_node = acherontia_node.addChildTaxon(Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.SPECIES()), null), null, null);
1152

    
1153
        try{
1154
            taxonNodeService.saveOrUpdate(acherontia_child_node);
1155
            commitAndStartNewTransaction(null);
1156
        } catch (RuntimeException e){
1157
            securityException = findSecurityRuntimeException(e);
1158
            logger.error("Unexpected failure of evaluation.", securityException);
1159
        } finally {
1160
            // needed in case saveOrUpdate was interrupted by the RuntimeException
1161
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1162
            endTransaction();
1163
            startNewTransaction();
1164
        }
1165

    
1166
        acherontia_node = taxonNodeService.load(ACHERONTIA_NODE_UUID);
1167
        Assert.assertNull("evaluation must not fail since the user is permitted, CAUSE :" + (securityException != null ? securityException.getMessage() : ""), securityException);
1168
        Assert.assertEquals("the acherontia_node must now have one more child node ", numOfChildNodes + 1 , acherontia_node.getChildNodes().size());
1169
    }
1170

    
1171
    @Test
1172
    public void testEditPartOfClassificationDeny(){
1173

    
1174
        authentication = authenticationManager.authenticate(tokenForPartEditor);
1175
        SecurityContext context = SecurityContextHolder.getContext();
1176
        context.setAuthentication(authentication);
1177
        RuntimeException securityException = null;
1178

    
1179
        // test for denial
1180
        TaxonNode acherontiini_node = taxonNodeService.load(ACHERONTIINI_NODE_UUID);
1181
        int numOfChildNodes = acherontiini_node.getCountChildren();
1182
        acherontiini_node.addChildTaxon(Taxon.NewInstance(TaxonNameFactory.NewBotanicalInstance(Rank.GENUS()), null), null, null);
1183

    
1184
        try{
1185
            logger.debug("==============================");
1186
            taxonNodeService.saveOrUpdate(acherontiini_node);
1187
            commitAndStartNewTransaction(null);
1188
        } catch (RuntimeException e){
1189
            securityException = findSecurityRuntimeException(e);
1190
            logger.debug("Expected failure of evaluation.", securityException);
1191
        } finally {
1192
            // needed in case saveOrUpdate was interrupted by the RuntimeException
1193
            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException
1194
            endTransaction();
1195
            startNewTransaction();
1196
        }
1197

    
1198
        acherontiini_node = taxonNodeService.load(ACHERONTIINI_NODE_UUID);
1199
        Assert.assertNotNull("evaluation must fail since the user is not permitted", securityException);
1200
        Assert.assertEquals("the number of child nodes must be unchanged ", numOfChildNodes , acherontiini_node.getChildNodes().size());
1201

    
1202
    }
1203

    
1204
    /* (non-Javadoc)
1205
     * @see eu.etaxonomy.cdm.test.integration.CdmIntegrationTest#createTestData()
1206
     */
1207
    @Override
1208
    public void createTestDataSet() throws FileNotFoundException {
1209
        // TODO Auto-generated method stub
1210

    
1211
    }
1212

    
1213
}
(24-24/38)