completely reworking UserServiceImplTest and also renaming it to UserAndGroupServiceI...
authorAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Thu, 6 Feb 2014 14:20:58 +0000 (14:20 +0000)
committerAndreas Kohlbecker <a.kohlbecker@bgbm.org>
Thu, 6 Feb 2014 14:20:58 +0000 (14:20 +0000)
.gitattributes
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/UserService.java
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/AbstractSecurityTestBase.java [new file with mode: 0644]
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/SecurityTest.java
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/UserAndGroupServiceImplTest.java [new file with mode: 0644]
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/UserServiceImplTest.java [deleted file]
cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/UserServiceImplTest.xml [deleted file]

index 82c18e2b5a693f3f849c94215374d3dbb4942c48..b265420d4a22ac0b94b45eb8a24bb92b74902a18 100644 (file)
@@ -2262,6 +2262,7 @@ cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/application/FirstDataInserter
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/facade/DerivedUnitFacadeCacheStrategyTest.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/facade/DerivedUnitFacadeFieldUnitCacheStrategyTest.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/facade/DerivedUnitFacadeTest.java -text
+cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/AbstractSecurityTestBase.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/ClassificationServiceImplTest.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/CommonServiceImplTest.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/DescriptionServiceImplTest.java -text
@@ -2283,7 +2284,7 @@ cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/TaxonServiceImplTest.
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/TaxonServiceSearchTest.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/TermServiceImplTest.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/TransmissionEngineDistributionTest.java -text
-cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/UserServiceImplTest.java -text
+cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/UserAndGroupServiceImplTest.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/lsid/LSIDAuthorityServiceTest.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/lsid/LSIDDataServiceTest.java -text
 cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/lsid/LSIDMetadataServiceTest.java -text
@@ -2343,7 +2344,6 @@ cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/TaxonServiceImpl
 cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/TaxonServiceSearchTest.xml -text
 cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/TermServiceImplTest.xml -text
 cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/TransmissionEngineDistributionTest.xml -text
-cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/UserServiceImplTest.xml -text
 cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/lsid/LSIDAuthorityServiceTest.testGetAuthorityWSDL-result.wsdl -text
 cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/lsid/LSIDAuthorityServiceTest.testGetAvailableServices.xml -text
 cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/lsid/LSIDAuthorityServiceTest.testGetAvailableServicesWithKnownLSID-result.wsdl -text
index fe1d1a9d7667a2c925a9c3cb681427d9dc95eb45..05eae83379f76895a458a434f347f60d6f6e1c83 100644 (file)
@@ -34,7 +34,6 @@ import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;\r
 import org.springframework.security.core.userdetails.cache.NullUserCache;\r
 import org.springframework.stereotype.Service;\r
-import org.springframework.transaction.annotation.Propagation;\r
 import org.springframework.transaction.annotation.Transactional;\r
 import org.springframework.util.Assert;\r
 \r
@@ -131,9 +130,9 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
             Object salt = this.saltSource.getSalt(user);\r
 \r
             String password = passwordEncoder.encodePassword(newPassword, salt);\r
-            ((User)user).setPassword(password);\r
+            user.setPassword(password);\r
 \r
-            dao.update((User)user);\r
+            dao.update(user);\r
             SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(authentication, newPassword));\r
             userCache.removeUserFromCache(user.getUsername());\r
         } else {\r
@@ -160,9 +159,9 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
             Object salt = this.saltSource.getSalt(user);\r
 \r
             String password = passwordEncoder.encodePassword(newPassword, salt);\r
-            ((User)user).setPassword(password);\r
+            user.setPassword(password);\r
 \r
-            dao.update((User)user);\r
+            dao.update(user);\r
             userCache.removeUserFromCache(user.getUsername());\r
         } catch(NonUniqueResultException nure) {\r
             throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1);\r
@@ -198,7 +197,7 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
 \r
         User user = dao.findUserByUsername(username);\r
         if(user != null) {\r
-            dao.delete((User)user);\r
+            dao.delete(user);\r
         }\r
 \r
         userCache.removeUserFromCache(username);\r
@@ -236,6 +235,7 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
      */\r
     // NOTE: this method must not be secured since it is being used during the\r
     //       authentication process\r
+    @Override\r
     public UserDetails loadUserByUsername(String username)\r
             throws UsernameNotFoundException, DataAccessException {\r
         Assert.hasText(username);\r
@@ -250,6 +250,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         }\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#addGroupAuthority(java.lang.String, org.springframework.security.core.GrantedAuthority)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
@@ -263,6 +267,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         }\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#addUserToGroup(java.lang.String, java.lang.String)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
@@ -279,6 +287,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         }\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#createGroup(java.lang.String, java.util.List)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
@@ -295,6 +307,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         groupDao.save(group);\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#deleteGroup(java.lang.String)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
@@ -305,12 +321,20 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         groupDao.delete(group);\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#findAllGroups()\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
     public List<String> findAllGroups() {\r
         return groupDao.listNames(null,null);\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#findGroupAuthorities(java.lang.String)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
     public List<GrantedAuthority> findGroupAuthorities(String groupName) {\r
@@ -320,6 +344,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         return new ArrayList<GrantedAuthority>(group.getGrantedAuthorities());\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#findUsersInGroup(java.lang.String)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
     public List<String> findUsersInGroup(String groupName) {\r
@@ -331,6 +359,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         return users;\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#removeGroupAuthority(java.lang.String, org.springframework.security.core.GrantedAuthority)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
@@ -345,6 +377,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         }\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#removeUserFromGroup(java.lang.String, java.lang.String)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
@@ -361,6 +397,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         }\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see org.springframework.security.provisioning.GroupManager#renameGroup(java.lang.String, java.lang.String)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
@@ -374,6 +414,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         groupDao.update(group);\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see eu.etaxonomy.cdm.api.service.ServiceBase#save(eu.etaxonomy.cdm.model.common.CdmBase)\r
+     */\r
+    @Override\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_RUN_AS_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
     public UUID save(User user) {\r
@@ -385,6 +429,9 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         return user.getUuid();\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see eu.etaxonomy.cdm.api.service.ServiceBase#update(eu.etaxonomy.cdm.model.common.CdmBase)\r
+     */\r
     @Override\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
     public UUID update(User user) {\r
@@ -392,6 +439,9 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         return user.getUuid();\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see eu.etaxonomy.cdm.api.service.IUserService#saveGrantedAuthority(org.springframework.security.core.GrantedAuthority)\r
+     */\r
     @Override\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
@@ -399,6 +449,10 @@ public class UserService extends ServiceBase<User,IUserDao> implements IUserServ
         return grantedAuthorityDao.save((GrantedAuthorityImpl)grantedAuthority);\r
     }\r
 \r
+    /* (non-Javadoc)\r
+     * @see eu.etaxonomy.cdm.api.service.IUserService#saveGroup(eu.etaxonomy.cdm.model.common.Group)\r
+     */\r
+    @Override\r
     @Deprecated // use GroupService instead\r
     @Transactional(readOnly=false)\r
     @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")\r
diff --git a/cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/AbstractSecurityTestBase.java b/cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/AbstractSecurityTestBase.java
new file mode 100644 (file)
index 0000000..0c0f4c7
--- /dev/null
@@ -0,0 +1,102 @@
+// $Id$
+/**
+* Copyright (C) 2014 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.api.service;
+
+import java.util.UUID;
+
+import org.junit.Before;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+
+import eu.etaxonomy.cdm.config.Configuration;
+import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTestWithSecurity;
+
+/**
+ * @author a.kohlbecker
+ * @date Feb 4, 2014
+ *
+ */
+public abstract class AbstractSecurityTestBase extends CdmTransactionalIntegrationTestWithSecurity {
+
+    protected static final UUID PART_EDITOR_UUID = UUID.fromString("38a251bd-0ba4-426f-8fcb-5c09560749a7");
+
+    protected static final UUID TAXON_EDITOR_UUID = UUID.fromString("56eac992-67ba-40be-896c-4e992ca2afc0");
+
+    protected static final String PASSWORD_TAXON_EDITOR = "test2";
+
+    protected static final String PASSWORD_ADMIN = "sPePhAz6";
+
+    protected UsernamePasswordAuthenticationToken tokenForAdmin;
+
+    protected UsernamePasswordAuthenticationToken tokenForTaxonEditor;
+
+    protected UsernamePasswordAuthenticationToken tokenForDescriptionEditor;
+
+    protected UsernamePasswordAuthenticationToken tokenForPartEditor;
+
+    protected UsernamePasswordAuthenticationToken tokenForTaxonomist;
+
+    protected UsernamePasswordAuthenticationToken tokenForUserManager;
+
+
+    @Before
+    public void setUp(){
+        /* User 'admin':
+            - ROLE_ADMIN
+            - TAXONBASE.[READ]
+            - TAXONBASE.[CREATE]
+            - TAXONBASE.[DELETE]
+            - TAXONBASE.[UPDATE]
+        */
+        tokenForAdmin = new UsernamePasswordAuthenticationToken(Configuration.adminLogin, PASSWORD_ADMIN);
+
+        /* User 'userManager':
+            - ROLE_ADMIN
+            - TAXONBASE.[READ]
+            - TAXONBASE.[CREATE]
+            - TAXONBASE.[DELETE]
+            - TAXONBASE.[UPDATE]
+        */
+        tokenForUserManager = new UsernamePasswordAuthenticationToken("userManager", PASSWORD_ADMIN);
+
+        /* User 'taxonEditor':
+            - TAXONBASE.[CREATE]
+            - TAXONBASE.[UPDATE]
+        */
+        tokenForTaxonEditor = new UsernamePasswordAuthenticationToken("taxonEditor", PASSWORD_TAXON_EDITOR);
+
+        /*  User 'descriptionEditor':
+            - DESCRIPTIONBASE.[CREATE]
+            - DESCRIPTIONBASE.[UPDATE]
+            - DESCRIPTIONELEMENT(Ecology).[CREATE]
+            - DESCRIPTIONELEMENT(Ecology).[UPDATE]
+         */
+        tokenForDescriptionEditor = new UsernamePasswordAuthenticationToken("descriptionEditor", "test");
+
+        /* User 'partEditor':
+            - TAXONBASE.[ADMIN]
+            - TAXONNODE.[UPDATE,CREATE,DELETE,READ,UPDATE]{20c8f083-5870-4cbd-bf56-c5b2b98ab6a7}
+            - DESCRIPTIONELEMENTBASE.[CREATE,DELETE,READ,UPDATE]
+            - DESCRIPTIONBASE.[CREATE,DELETE,READ,UPDATE]
+         */
+        tokenForPartEditor = new UsernamePasswordAuthenticationToken("partEditor", "test4");
+
+        /* User 'taxonomist':
+            - TAXONBASE.[READ]
+            - TAXONBASE.[CREATE]
+            - TAXONBASE.[DELETE]
+            - TAXONBASE.[UPDATE]
+            - DESCRIPTIONELEMENTBASE.[CREATE,DELETE,READ,UPDATE]
+            - DESCRIPTIONBASE.[CREATE,DELETE,READ,UPDATE]
+         */
+        tokenForTaxonomist = new UsernamePasswordAuthenticationToken("taxonomist", "test4");
+    }
+
+
+}
index 88e9214b44b557604ce770929809a8749c1008ae..d2561e385ca673fa6cac24f7cacf1ed919d9fc9c 100644 (file)
@@ -21,7 +21,6 @@ import javax.sql.DataSource;
 \r
 import org.apache.log4j.Logger;\r
 import org.junit.Assert;\r
-import org.junit.Before;\r
 import org.junit.Ignore;\r
 import org.junit.Test;\r
 import org.springframework.security.access.AccessDeniedException;\r
@@ -41,7 +40,6 @@ import org.unitils.spring.annotation.SpringBeanByType;
 \r
 import eu.etaxonomy.cdm.api.service.exception.DataChangeNoRollbackException;\r
 import eu.etaxonomy.cdm.api.service.exception.ReferencedObjectUndeletableException;\r
-import eu.etaxonomy.cdm.config.Configuration;\r
 import eu.etaxonomy.cdm.database.PermissionDeniedException;\r
 import eu.etaxonomy.cdm.model.common.User;\r
 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;\r
@@ -59,11 +57,10 @@ import eu.etaxonomy.cdm.model.taxon.TaxonNode;
 import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionEvaluator;\r
 import eu.etaxonomy.cdm.persistence.hibernate.permission.Operation;\r
 import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
-import eu.etaxonomy.cdm.test.integration.CdmTransactionalIntegrationTestWithSecurity;\r
 \r
 \r
 @DataSet\r
-public class SecurityTest extends CdmTransactionalIntegrationTestWithSecurity{\r
+public class SecurityTest extends AbstractSecurityTestBase{\r
 \r
     private static final UUID UUID_ACHERONTINII = UUID.fromString("928a0167-98cd-4555-bf72-52116d067625");\r
 \r
@@ -71,11 +68,6 @@ public class SecurityTest extends CdmTransactionalIntegrationTestWithSecurity{
 \r
     private static final UUID UUID_LACTUCA = UUID.fromString("b2b007a4-9c8c-43a1-8da4-20ed85464cf2");\r
 \r
-    private static final UUID PART_EDITOR_UUID = UUID.fromString("38a251bd-0ba4-426f-8fcb-5c09560749a7");\r
-\r
-    private static final String PASSWORD_TAXON_EDITOR = "test2";\r
-\r
-    private static final String PASSWORD_ADMIN = "sPePhAz6";\r
 \r
     private static final UUID ACHERONTIA_NODE_UUID = UUID.fromString("20c8f083-5870-4cbd-bf56-c5b2b98ab6a7");\r
 \r
@@ -123,72 +115,6 @@ public class SecurityTest extends CdmTransactionalIntegrationTestWithSecurity{
     @SpringBean("cdmPermissionEvaluator")\r
     private CdmPermissionEvaluator permissionEvaluator;\r
 \r
-    private UsernamePasswordAuthenticationToken tokenForAdmin;\r
-\r
-    private UsernamePasswordAuthenticationToken tokenForTaxonEditor;\r
-\r
-    private UsernamePasswordAuthenticationToken tokenForDescriptionEditor;\r
-\r
-    private UsernamePasswordAuthenticationToken tokenForPartEditor;\r
-\r
-    private UsernamePasswordAuthenticationToken tokenForTaxonomist;\r
-\r
-    private UsernamePasswordAuthenticationToken tokenForUserManager;\r
-\r
-\r
-\r
-    @Before\r
-    public void setUp(){\r
-        /* User 'admin':\r
-            - ROLE_ADMIN\r
-            - TAXONBASE.[READ]\r
-            - TAXONBASE.[CREATE]\r
-            - TAXONBASE.[DELETE]\r
-            - TAXONBASE.[UPDATE]\r
-        */\r
-        tokenForAdmin = new UsernamePasswordAuthenticationToken(Configuration.adminLogin, PASSWORD_ADMIN);\r
-\r
-        /* User 'userManager':\r
-            - ROLE_ADMIN\r
-            - TAXONBASE.[READ]\r
-            - TAXONBASE.[CREATE]\r
-            - TAXONBASE.[DELETE]\r
-            - TAXONBASE.[UPDATE]\r
-        */\r
-        tokenForUserManager = new UsernamePasswordAuthenticationToken("userManager", PASSWORD_ADMIN);\r
-\r
-        /* User 'taxonEditor':\r
-            - TAXONBASE.[CREATE]\r
-            - TAXONBASE.[UPDATE]\r
-        */\r
-        tokenForTaxonEditor = new UsernamePasswordAuthenticationToken("taxonEditor", PASSWORD_TAXON_EDITOR);\r
-\r
-        /*  User 'descriptionEditor':\r
-            - DESCRIPTIONBASE.[CREATE]\r
-            - DESCRIPTIONBASE.[UPDATE]\r
-            - DESCRIPTIONELEMENT(Ecology).[CREATE]\r
-            - DESCRIPTIONELEMENT(Ecology).[UPDATE]\r
-         */\r
-        tokenForDescriptionEditor = new UsernamePasswordAuthenticationToken("descriptionEditor", "test");\r
-\r
-        /* User 'partEditor':\r
-            - TAXONBASE.[ADMIN]\r
-            - TAXONNODE.[UPDATE,CREATE,DELETE,READ,UPDATE]{20c8f083-5870-4cbd-bf56-c5b2b98ab6a7}\r
-            - DESCRIPTIONELEMENTBASE.[CREATE,DELETE,READ,UPDATE]\r
-            - DESCRIPTIONBASE.[CREATE,DELETE,READ,UPDATE]\r
-         */\r
-        tokenForPartEditor = new UsernamePasswordAuthenticationToken("partEditor", "test4");\r
-\r
-        /* User 'taxonomist':\r
-            - TAXONBASE.[READ]\r
-            - TAXONBASE.[CREATE]\r
-            - TAXONBASE.[DELETE]\r
-            - TAXONBASE.[UPDATE]\r
-            - DESCRIPTIONELEMENTBASE.[CREATE,DELETE,READ,UPDATE]\r
-            - DESCRIPTIONBASE.[CREATE,DELETE,READ,UPDATE]\r
-         */\r
-        tokenForTaxonomist = new UsernamePasswordAuthenticationToken("taxonomist", "test4");\r
-    }\r
 \r
 \r
     /**\r
diff --git a/cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/UserAndGroupServiceImplTest.java b/cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/UserAndGroupServiceImplTest.java
new file mode 100644 (file)
index 0000000..642975d
--- /dev/null
@@ -0,0 +1,197 @@
+/**\r
+* Copyright (C) 2009 EDIT\r
+* European Distributed Institute of Taxonomy\r
+* http://www.e-taxonomy.eu\r
+*\r
+* The contents of this file are subject to the Mozilla Public License Version 1.1\r
+* See LICENSE.TXT at the top of this package for the full license terms.\r
+*/\r
+\r
+package eu.etaxonomy.cdm.api.service;\r
+\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.apache.log4j.Logger;\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+import org.springframework.security.access.AccessDeniedException;\r
+import org.springframework.security.authentication.AuthenticationManager;\r
+import org.springframework.security.core.Authentication;\r
+import org.springframework.security.core.GrantedAuthority;\r
+import org.springframework.security.core.context.SecurityContext;\r
+import org.springframework.security.core.context.SecurityContextHolder;\r
+import org.unitils.dbunit.annotation.DataSet;\r
+import org.unitils.spring.annotation.SpringBeanByType;\r
+\r
+import eu.etaxonomy.cdm.database.PermissionDeniedException;\r
+import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;\r
+import eu.etaxonomy.cdm.model.common.User;\r
+import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;\r
+\r
+\r
+/**\r
+ * @author a.kohlbecker\r
+ * @date Feb 4, 2014\r
+ *\r
+ */\r
+@DataSet(value="SecurityTest.xml")\r
+public class UserAndGroupServiceImplTest extends AbstractSecurityTestBase {\r
+\r
+    protected static final Logger logger = Logger.getLogger(UserAndGroupServiceImplTest.class);\r
+\r
+    @SpringBeanByType\r
+    private AuthenticationManager authenticationManager;\r
+\r
+    @SpringBeanByType\r
+    private IUserService userService;\r
+\r
+    @SpringBeanByType\r
+    private IGroupService groupService;\r
+\r
+    @SpringBeanByType\r
+    private ITaxonService taxonService;\r
+\r
+\r
+    private Authentication authentication;\r
+\r
+\r
+    @Test\r
+    public void testCreateUser() {\r
+\r
+\r
+        authentication = authenticationManager.authenticate(tokenForAdmin);\r
+        SecurityContext context = SecurityContextHolder.getContext();\r
+        context.setAuthentication(authentication);\r
+\r
+\r
+        try{\r
+            userService.createUser(User.NewInstance("new user 1", "00000"));\r
+        }catch(Exception e){\r
+            Assert.fail();\r
+        }\r
+\r
+        authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+        context = SecurityContextHolder.getContext();\r
+        context.setAuthentication(authentication);\r
+\r
+        try{\r
+            userService.createUser(User.NewInstance("new user 2", "00000"));\r
+            Assert.fail();\r
+        }catch(Exception e){\r
+            Assert.assertEquals("Access is denied", e.getMessage());\r
+        }\r
+    }\r
+\r
+\r
+    @Test\r
+    public void testUpdateUser(){\r
+\r
+        // TaxonEditor should be able to change its own email address\r
+        authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+        SecurityContext context = SecurityContextHolder.getContext();\r
+        context.setAuthentication(authentication);\r
+\r
+        User user= userService.find(TAXON_EDITOR_UUID);\r
+        user.setEmailAddress("test@bgbm.org");\r
+\r
+        /* FIXME\r
+        try{\r
+            userService.updateUser(user);\r
+        }catch (Exception e){\r
+            Assert.fail("the user TaxonEditor should be able to change its own email address");\r
+        }\r
+        */\r
+\r
+        authentication = authenticationManager.authenticate(tokenForUserManager);\r
+        context = SecurityContextHolder.getContext();\r
+        context.setAuthentication(authentication);\r
+\r
+        user.setEmailAddress("user@bgbm.org");\r
+\r
+        try{\r
+            userService.updateUser(user);\r
+        }catch (Exception e){\r
+            Assert.fail("the user UserManager should be able to change others email addresses");\r
+        }\r
+\r
+        authentication = authenticationManager.authenticate(tokenForPartEditor);\r
+        context = SecurityContextHolder.getContext();\r
+        context.setAuthentication(authentication);\r
+\r
+        try{\r
+            userService.updateUser(user);\r
+            Assert.fail("the user PartEditor should NOT be able to change others email addresses");\r
+        }catch (Exception e){\r
+            Assert.assertEquals("Access is denied", e.getMessage());\r
+        }\r
+\r
+    }\r
+\r
+    @Test\r
+    public void testChangePassword(){\r
+\r
+        // the user TaxonEditor should be able to change its own password\r
+        authentication = authenticationManager.authenticate(tokenForTaxonEditor);\r
+        SecurityContext context = SecurityContextHolder.getContext();\r
+        context.setAuthentication(authentication);\r
+\r
+        userService.changePasswordForUser(tokenForTaxonEditor.getName(), "newPassword");\r
+\r
+        Exception exception = null;\r
+        // the user TaxonEditor should NOT be able to change others passwords\r
+        try{\r
+            userService.changePasswordForUser(tokenForAdmin.getName(), "newPassword");\r
+            commitAndStartNewTransaction(null);\r
+        } catch (AccessDeniedException e){\r
+            logger.debug("Expected failure of evaluation.", e);\r
+            exception  = e;\r
+        } catch (RuntimeException e){\r
+            exception = findThrowableOfTypeIn(PermissionDeniedException.class, e);\r
+            logger.debug("Expected failure of evaluation.", exception);\r
+        } finally {\r
+            // needed in case saveOrUpdate was interrupted by the RuntimeException\r
+            // commitAndStartNewTransaction() would raise an UnexpectedRollbackException\r
+            endTransaction();\r
+            startNewTransaction();\r
+        }\r
+        Assert.assertNotNull("must fail here!", exception);\r
+\r
+        // the user User manager should be able to change others passwords\r
+        authentication = authenticationManager.authenticate(tokenForUserManager);\r
+        context = SecurityContextHolder.getContext();\r
+        context.setAuthentication(authentication);\r
+        userService.changePasswordForUser(tokenForAdmin.getName(), "newPassword");\r
+    }\r
+\r
+\r
+    @Test\r
+    public void testCreateGroup(){\r
+\r
+        authentication = authenticationManager.authenticate(tokenForUserManager);\r
+        SecurityContext context = SecurityContextHolder.getContext();\r
+        context.setAuthentication(authentication);\r
+\r
+\r
+        List<GrantedAuthority> authorityList = new ArrayList<GrantedAuthority>();\r
+        GrantedAuthorityImpl rolePublishAthotrity = GrantedAuthorityImpl.NewInstance();\r
+        rolePublishAthotrity.setAuthority(Role.ROLE_PUBLISH.toString()); // testing if creating a Role from string is working\r
+        authorityList.add(rolePublishAthotrity);\r
+\r
+        String publishersGroupName = "publishers";\r
+\r
+        groupService.createGroup(publishersGroupName, authorityList);\r
+\r
+        commitAndStartNewTransaction(null);\r
+\r
+        List<GrantedAuthority> groupAuthorities = groupService.findGroupAuthorities(publishersGroupName);\r
+\r
+        Assert.assertEquals(Role.ROLE_PUBLISH.toString(), groupAuthorities.get(0).getAuthority());\r
+\r
+    }\r
+\r
+\r
+\r
+\r
+}\r
diff --git a/cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/UserServiceImplTest.java b/cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/UserServiceImplTest.java
deleted file mode 100644 (file)
index 0649e9c..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-/**\r
-* Copyright (C) 2009 EDIT\r
-* European Distributed Institute of Taxonomy\r
-* http://www.e-taxonomy.eu\r
-*\r
-* The contents of this file are subject to the Mozilla Public License Version 1.1\r
-* See LICENSE.TXT at the top of this package for the full license terms.\r
-*/\r
-\r
-package eu.etaxonomy.cdm.api.service;\r
-\r
-\r
-import java.util.ArrayList;\r
-import java.util.HashSet;\r
-import java.util.List;\r
-import java.util.Set;\r
-import java.util.UUID;\r
-\r
-import org.apache.log4j.Logger;\r
-import org.joda.time.DateTime;\r
-import org.junit.Assert;\r
-import org.junit.Before;\r
-import org.junit.Ignore;\r
-import org.junit.Test;\r
-import org.springframework.security.authentication.AuthenticationManager;\r
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\r
-import org.springframework.security.core.Authentication;\r
-import org.springframework.security.core.GrantedAuthority;\r
-import org.springframework.security.core.context.SecurityContext;\r
-import org.springframework.security.core.context.SecurityContextHolder;\r
-import org.unitils.dbunit.annotation.DataSet;\r
-import org.unitils.spring.annotation.SpringApplicationContext;\r
-import org.unitils.spring.annotation.SpringBeanByType;\r
-\r
-import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;\r
-import eu.etaxonomy.cdm.model.common.User;\r
-import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionEvaluator;\r
-import eu.etaxonomy.cdm.persistence.query.MatchMode;\r
-import eu.etaxonomy.cdm.test.integration.CdmIntegrationTest;\r
-\r
-@Ignore //FIXME tests are failing\r
-@SpringApplicationContext("file:./target/test-classes/eu/etaxonomy/cdm/applicationContext-securityTest.xml")\r
-public class UserServiceImplTest extends CdmIntegrationTest {\r
-\r
-    protected static final Logger logger = Logger.getLogger(UserServiceImplTest.class);\r
-\r
-    @SpringBeanByType\r
-    private AuthenticationManager authenticationManager;\r
-\r
-    @SpringBeanByType\r
-    private IUserService userService;\r
-\r
-    @SpringBeanByType\r
-    private IGroupService groupService;\r
-\r
-    @SpringBeanByType\r
-    private ITaxonService taxonService;\r
-\r
-    @SpringBeanByType\r
-    private CdmPermissionEvaluator permissionEvaluator;\r
-\r
-\r
-//     @SpringBeanByType\r
-//    public void setDataSource(@Qualifier("dataSource") DataSource dataSource) {\r
-//        this.dataSource=dataSource;\r
-//    }\r
-\r
-\r
-//\r
-//     @TestDataSource\r
-//     protected DataSource dataSource;\r
-\r
-    private Set<GrantedAuthority> expectedRoles;\r
-    private UsernamePasswordAuthenticationToken token;\r
-\r
-    private Authentication authentication;\r
-\r
-    UUID uuid;\r
-\r
-    @Before\r
-    public void setUp() {\r
-        expectedRoles = new HashSet<GrantedAuthority>();\r
-\r
-        GrantedAuthorityImpl update = GrantedAuthorityImpl.NewInstance();\r
-        update.setAuthority("USER.Update");\r
-        update.setUuid(UUID.fromString("14788361-1a7e-4eed-b22f-fd90a0b424ac"));\r
-        update.setCreated(new DateTime(2009,2,3,17,52,26,0));\r
-        GrantedAuthorityImpl annotate = GrantedAuthorityImpl.NewInstance();\r
-        annotate.setAuthority("USER.Create");\r
-        annotate.setUuid(UUID.fromString("fa56073c-0ffd-4384-b459-b2f07e35b689"));\r
-        annotate.setCreated(new DateTime(2009,2,3,17,52,26,0));\r
-        GrantedAuthorityImpl checkAnnotation = GrantedAuthorityImpl.NewInstance();\r
-        checkAnnotation.setAuthority("USER.Delete");\r
-        checkAnnotation.setUuid(UUID.fromString("e5354c0e-657b-4b4d-bb2f-791612199711"));\r
-        checkAnnotation.setCreated(new DateTime(2009,2,3,17,52,26,0));\r
-        GrantedAuthorityImpl userAdmin = GrantedAuthorityImpl.NewInstance();\r
-        userAdmin.setAuthority("USER.Admin");\r
-\r
-        expectedRoles.add(update);\r
-        expectedRoles.add(annotate);\r
-        expectedRoles.add(checkAnnotation);\r
-        expectedRoles.add(userAdmin);\r
-        String username = "useradmin";\r
-        String password = "password";\r
-        User user = User.NewInstance(username, password);\r
-        user.setAccountNonExpired(true);\r
-        user.setGrantedAuthorities(expectedRoles);\r
-        uuid = userService.save(user);\r
-\r
-        User standardUser =  User.NewInstance("standardUser", "pw");\r
-        uuid = userService.save(standardUser);\r
-\r
-        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);\r
-        authentication = authenticationManager.authenticate(token);\r
-        SecurityContext context = SecurityContextHolder.getContext();\r
-        context.setAuthentication(authentication);\r
-    }\r
-\r
-\r
-    @Test\r
-    @DataSet\r
-    public void testCreateUser() {\r
-        String username = "user2";\r
-        String password = "password";\r
-        User user = User.NewInstance(username, password);\r
-\r
-        userService.createUser(user);\r
-\r
-        List<User> userList = userService.listByUsername("user2", MatchMode.EXACT, null, null, null, null, null);\r
-        Assert.assertNotNull(userList);\r
-\r
-        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("standardUser", "pw");\r
-        authentication = authenticationManager.authenticate(token);\r
-        SecurityContext context = SecurityContextHolder.getContext();\r
-        context.setAuthentication(authentication);\r
-        try{\r
-            userService.createUser(user);\r
-            Assert.fail();\r
-        }catch(Exception e){\r
-            Assert.assertEquals("Access is denied", e.getMessage());\r
-        }\r
-    }\r
-\r
-\r
-\r
-    @Test\r
-    @DataSet\r
-    public void testUpdateUser(){\r
-        User user= userService.find(uuid);\r
-        user.setEmailAddress("test@bgbm.org");\r
-        try{\r
-        userService.updateUser(user);\r
-        }catch (Exception e){\r
-            Assert.fail();\r
-        }\r
-\r
-        try{\r
-            userService.update(user);\r
-            }catch (Exception e){\r
-                Assert.fail();\r
-            }\r
-        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("standardUser", "pw");\r
-        authentication = authenticationManager.authenticate(token);\r
-        SecurityContext context = SecurityContextHolder.getContext();\r
-        context.setAuthentication(authentication);\r
-        user.setEmailAddress("user@bgbm.org");\r
-        try{\r
-        userService.updateUser(user);\r
-        Assert.fail();\r
-        }catch (Exception e){\r
-            Assert.assertEquals("Access is denied", e.getMessage());\r
-        }\r
-\r
-        try{\r
-            userService.saveOrUpdate(user);\r
-            Assert.fail();\r
-        }catch (Exception e){\r
-            Assert.assertEquals("Access is denied", e.getMessage());\r
-        }\r
-        try{\r
-            userService.update(user);\r
-            Assert.fail();\r
-        }catch (Exception e){\r
-            Assert.assertEquals("Access is denied", e.getMessage());\r
-        }\r
-    }\r
-\r
-    @Test\r
-    @DataSet\r
-    public void testIfAnyGranted() {\r
-        Object p = authentication.getPrincipal();\r
-        Assert.assertTrue(p instanceof User);\r
-        User principal = (User)p;\r
-\r
-        Assert.assertEquals(principal.getUsername(),"useradmin");\r
-\r
-        Assert.assertNotNull(expectedRoles);\r
-        Assert.assertEquals(expectedRoles.size(), authentication.getAuthorities().size());\r
-    }\r
-\r
-\r
-    @Test\r
-    @DataSet\r
-    public void testCreateGroup(){\r
-\r
-        GrantedAuthorityImpl userAdminUpdate = GrantedAuthorityImpl.NewInstance();\r
-        userAdminUpdate.setAuthority("USER.update");\r
-        GrantedAuthorityImpl userAdminCreate = GrantedAuthorityImpl.NewInstance();\r
-        userAdminCreate.setAuthority("USER.create");\r
-        GrantedAuthorityImpl userAdminDelete = GrantedAuthorityImpl.NewInstance();\r
-        userAdminDelete.setAuthority("USER.delete");\r
-        List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();\r
-        list.add(userAdminUpdate);\r
-        list.add(userAdminDelete);\r
-        list.add(userAdminCreate);\r
-\r
-\r
-        userService.createGroup("UserAdmins", list);\r
-        String username = "user3";\r
-        String password = "password";\r
-        User user = User.NewInstance(username, password);\r
-        userService.createUser(user);\r
-        List<String> groups = userService.findAllGroups();\r
-        Assert.assertEquals("UserAdmins", groups.get(0));\r
-\r
-\r
-        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);\r
-        authentication = authenticationManager.authenticate(token);\r
-        SecurityContext context = SecurityContextHolder.getContext();\r
-        context.setAuthentication(authentication);\r
-\r
-        username = "user4";\r
-        password = "password";\r
-        user = User.NewInstance(username, password);\r
-        try{\r
-            userService.createUser(user);\r
-            Assert.fail();\r
-        }catch(Exception e){\r
-            Assert.assertEquals("Access is denied", e.getMessage());\r
-        }\r
-        groupService.addUserToGroup("user3", "UserAdmins");\r
-\r
-    // System.err.println(context.getAuthentication().getName());\r
-        try{\r
-            userService.createUser(user);\r
-        }catch(Exception e){\r
-            System.err.println(e.getMessage());\r
-            Assert.fail();\r
-        }\r
-\r
-    }\r
-\r
-\r
-    @Test\r
-    @DataSet\r
-    public void testChangePassword(){\r
-        String username = "useradmin";\r
-        String newPassword = "password2";\r
-        userService.changePasswordForUser(username, newPassword);\r
-        username = "user4";\r
-        String password = "password";\r
-        User user = User.NewInstance(username, password);\r
-        userService.createUser(user);\r
-        try{\r
-            userService.changePasswordForUser(username, "newPassword");\r
-        }catch (Exception e){\r
-            System.err.println(e.getMessage());\r
-            Assert.fail();\r
-        }\r
-    }\r
-\r
-}\r
diff --git a/cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/UserServiceImplTest.xml b/cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/UserServiceImplTest.xml
deleted file mode 100644 (file)
index fe699a4..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?>\r
-<dataset  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../service/dataset.xsd">\r
-\r
-  <PERMISSIONGROUP ID="1" NAME="CopyEditors" UUID="8a423129-6d88-41cc-a1da-96bca45f5838"/>\r
-  <PERMISSIONGROUP ID="2" NAME="Editors"    UUID="db5f3578-e689-43da-b1f0-e72f81c1fd79"/>\r
-\r
-  <PERMISSIONGROUP_GRANTEDAUTHORITYIMPL PERMISSIONGROUP_ID="1" GRANTEDAUTHORITIES_ID="2"/>\r
-  <PERMISSIONGROUP_GRANTEDAUTHORITYIMPL PERMISSIONGROUP_ID="1" GRANTEDAUTHORITIES_ID="4"/>\r
-  <PERMISSIONGROUP_GRANTEDAUTHORITYIMPL PERMISSIONGROUP_ID="2" GRANTEDAUTHORITIES_ID="1"/>\r
-  <PERMISSIONGROUP_GRANTEDAUTHORITYIMPL PERMISSIONGROUP_ID="2" GRANTEDAUTHORITIES_ID="6"/>\r
-  <GRANTEDAUTHORITYIMPL ID="1" UUID="441a3c40-0c84-11de-8c30-0800200c9a66" CREATED="2009-02-03 17:52:26.0" AUTHORITY="USER.READ"/>\r
-  <GRANTEDAUTHORITYIMPL ID="2" UUID="14788361-1a7e-4eed-b22f-fd90a0b424ac" CREATED="2009-02-03 17:52:26.0" AUTHORITY="USER.UPDATE"/>\r
-  <GRANTEDAUTHORITYIMPL ID="3" UUID="fa56073c-0ffd-4384-b459-b2f07e35b689" CREATED="2009-02-03 17:52:26.0" AUTHORITY="USER.CREATE"/>\r
-  <GRANTEDAUTHORITYIMPL ID="4" UUID="e5354c0e-657b-4b4d-bb2f-791612199711" CREATED="2009-02-03 17:52:26.0" AUTHORITY="USER.DELETE"/>\r
-  <GRANTEDAUTHORITYIMPL ID="6" UUID="7aea7ce1-0548-49d9-8a7b-324aab4a4a46" CREATED="2009-02-03 17:52:26.0" AUTHORITY="USER.Admin"/>\r
-  <USERACCOUNT USERNAME="ben" ID="1" UUID="e4acf200-63b6-11dd-ad8b-0800200c9a66" PASSWORD="e141bbb8bb7f4579aa3156fdbe0d1226" ENABLED="true" ACCOUNTNONEXPIRED="true" CREDENTIALSNONEXPIRED="true" ACCOUNTNONLOCKED="true"/>\r
-  <USERACCOUNT_GRANTEDAUTHORITYIMPL USERACCOUNT_ID="1" GRANTEDAUTHORITIES_ID="3"/>\r
-  <USERACCOUNT_PERMISSIONGROUP GROUPS_ID="1" MEMBERS_ID="1"/>\r
-  <USERACCOUNT_PERMISSIONGROUP GROUPS_ID="2" MEMBERS_ID="1"/>\r
-  <TAXONBASE DTYPE="Taxon" ID="4" CREATED="2009-02-03 17:52:26.0" UUID="9f512d7f-a11c-4aca-8203-ae954a6274a1" TITLECACHE="Abies sec. ???" PROTECTEDTITLECACHE="false" DOUBTFUL="false" PUBLISH="true" USENAMECACHE="false" TAXONSTATUSUNKNOWN="false" TAXONOMICCHILDRENCOUNT="0" NAME_ID="4" />\r
-  <TAXONNAMEBASE DTYPE="BotanicalName" ID="4" CREATED="2009-02-03 17:52:26.0" UUID="ebd459a6-52ec-4f7c-a520-32c82aa31011" TITLECACHE="Abies" PROTECTEDTITLECACHE="false" PARSINGPROBLEM="0" FULLTITLECACHE="Abies" PROBLEMENDS="-1" PROBLEMSTARTS="-1" PROTECTEDFULLTITLECACHE="false" AUTHORSHIPCACHE="" GENUSORUNINOMIAL="Abies" NAMECACHE="Abies" PROTECTEDAUTHORSHIPCACHE="false" PROTECTEDNAMECACHE="false" ANAMORPHIC="false" BINOMHYBRID="false" HYBRIDFORMULA="false" MONOMHYBRID="false" TRINOMHYBRID="false" HOMOTYPICALGROUP_ID="4" RANK_ID="774" COMBINATIONAUTHORTEAM_ID="1"/>\r
-</dataset>\r