From 043a8860ec058fc189cbbd5865caca791864c373 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 20 May 2019 16:11:19 -0400 Subject: [PATCH 01/51] SHIBUI-1262: 1304 --- .../admin/ui/domain/versioning/Version.java | 32 ++++++++++++++++ .../EntityDescriptorVersionService.java | 17 +++++++++ .../VersionJsonSerializationBasicTests.groovy | 37 +++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/Version.java create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/Version.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/Version.java new file mode 100644 index 000000000..ce3687507 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/Version.java @@ -0,0 +1,32 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.versioning; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * Represents version information of any versioned entity in the system. + */ +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +@EqualsAndHashCode +public class Version implements Serializable { + + private String id; + + private String creator; + + private LocalDateTime date; + + private static final long serialVersionUID = 3429591830989243421L; + +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java new file mode 100644 index 000000000..44e1bb9d8 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java @@ -0,0 +1,17 @@ +package edu.internet2.tier.shibboleth.admin.ui.service; + +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; +import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version; + +import java.util.List; + +/** + * API containing operations pertaining to {@link EntityDescriptor} versioning. + */ +public interface EntityDescriptorVersionService { + + List findVersionsForEntityDescriptor(String resourceId); + + EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionToken); +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy new file mode 100644 index 000000000..07c37a55c --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy @@ -0,0 +1,37 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.versioning + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +import spock.lang.Specification + +import java.time.LocalDateTime +import java.time.Month + +class VersionJsonSerializationBasicTests extends Specification { + + ObjectMapper mapper + + def setup() { + mapper = new ObjectMapper() + mapper.registerModule(new JavaTimeModule()) + } + + def "Verify basic Version JSON serialization"() { + given: + def staticDate = LocalDateTime.of(2019, Month.MAY,20,15,0,0) + def version = new Version('2', 'kramer', staticDate) + def expectedJson = """ + { + "id": "2", + "creator": "kramer", + "date": "${staticDate.toString()}" + } + """ + + when: + def deSerialized = mapper.readValue(expectedJson, Version) + + then: + deSerialized == version + } +} From 729af5225f1220139968709dc3906efae8abe2dc Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 21 May 2019 11:29:28 -0400 Subject: [PATCH 02/51] SHIBUI-1262 [1303] --- .../EntityDescriptorController.java | 55 ++++++++++++++++--- .../EntityDescriptorVersionService.java | 2 +- .../EntityDescriptorControllerTests.groovy | 4 +- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java index 80213f5cd..b3ea0fb62 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java @@ -2,6 +2,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; +import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version; import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository; import edu.internet2.tier.shibboleth.admin.ui.security.model.User; @@ -9,6 +10,7 @@ import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository; import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService; import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService; import org.opensaml.core.xml.io.MarshallingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,6 +36,7 @@ import javax.annotation.PostConstruct; import javax.xml.ws.Response; import java.net.URI; +import java.util.List; import java.util.stream.Collectors; @RestController @@ -52,20 +55,17 @@ public class EntityDescriptorController { @Autowired RestTemplateBuilder restTemplateBuilder; - private UserRepository userRepository; - - private RoleRepository roleRepository; - private UserService userService; private RestTemplate restTemplate; + private EntityDescriptorVersionService versionService; + private static Logger LOGGER = LoggerFactory.getLogger(EntityDescriptorController.class); - public EntityDescriptorController(UserRepository userRepository, RoleRepository roleRepository, UserService userService) { - this.userRepository = userRepository; - this.roleRepository = roleRepository; + public EntityDescriptorController(UserService userService, EntityDescriptorVersionService versionService) { this.userService = userService; + this.versionService = versionService; } @PostConstruct @@ -220,6 +220,40 @@ public ResponseEntity deleteOne(@PathVariable String resourceId) { } } + //Versioning endpoints + + @GetMapping("/EntityDescriptor/{resourceId}/Versions") + public ResponseEntity getAllVersions(@PathVariable String resourceId) { + EntityDescriptor ed = entityDescriptorRepository.findByResourceId(resourceId); + if (ed == null) { + return ResponseEntity.notFound().build(); + } + List versions = versionService.findVersionsForEntityDescriptor(resourceId); + if (versions.isEmpty()) { + return ResponseEntity.notFound().build(); + } + if(isAuthorizedFor(ed.getCreatedBy())) { + return ResponseEntity.ok(versions); + } + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + @GetMapping("/EntityDescriptor/{resourceId}/Versions/{versionId}") + public ResponseEntity getSpecificVersion(@PathVariable String resourceId, @PathVariable String versionId) { + EntityDescriptorRepresentation edRepresentation = + versionService.findSpecificVersionOfEntityDescriptor(resourceId, versionId); + + if (edRepresentation == null) { + return ResponseEntity.notFound().build(); + } + if(isAuthorizedFor(edRepresentation.getCreatedBy())) { + return ResponseEntity.ok(edRepresentation); + } + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + //Private methods + private static URI getResourceUriFor(EntityDescriptor ed) { return ServletUriComponentsBuilder .fromCurrentServletMapping().path("/api/EntityDescriptor") @@ -267,4 +301,11 @@ private ResponseEntity handleUploadingEntityDescriptorXml(byte[] rawXmlBytes, .body(entityDescriptorService.createRepresentationFromDescriptor(persistedEd)); } + private boolean isAuthorizedFor(String username) { + User u = userService.getCurrentUser(); + return (u != null) && + (u.getRole().equals("ROLE_ADMIN") + || (u.getUsername().equals(username))); + } + } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java index 44e1bb9d8..5e1542ea2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java @@ -13,5 +13,5 @@ public interface EntityDescriptorVersionService { List findVersionsForEntityDescriptor(String resourceId); - EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionToken); + EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId); } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy index 928cd18ec..89cb89d54 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy @@ -11,6 +11,7 @@ import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorReposit import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityDescriptorServiceImpl import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityServiceImpl import edu.internet2.tier.shibboleth.admin.ui.util.RandomGenerator @@ -69,6 +70,7 @@ class EntityDescriptorControllerTests extends Specification { RoleRepository roleRepository = Mock() UserService userService + EntityDescriptorVersionService versionService = Mock() def setup() { generator = new TestObjectGenerator() @@ -78,7 +80,7 @@ class EntityDescriptorControllerTests extends Specification { userService = new UserService(roleRepository, userRepository) service = new JPAEntityDescriptorServiceImpl(openSamlObjects, new JPAEntityServiceImpl(openSamlObjects), userService) - controller = new EntityDescriptorController(userRepository, roleRepository, userService) + controller = new EntityDescriptorController(userService, versionService) controller.entityDescriptorRepository = entityDescriptorRepository controller.openSamlObjects = openSamlObjects controller.entityDescriptorService = service From acc9ce502a4076c3f96647459dd4f35232d54baf Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 21 May 2019 15:27:01 -0400 Subject: [PATCH 03/51] SHIBUI-1262 [1305] --- .../admin/ui/configuration/DevConfig.groovy | 8 +++++ .../EntitiesVersioningConfiguration.java | 15 ++++++++ .../EntityDescriptorVersionService.java | 25 +++++++++++++ ...tyDescriptorVersioningConfiguration.groovy | 36 +++++++++++++++++++ ...JPAEntityDescriptorServiceImplTests.groovy | 3 +- 5 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy index 8db64fd67..2ed81b941 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy @@ -15,6 +15,8 @@ import edu.internet2.tier.shibboleth.admin.ui.security.model.Role import edu.internet2.tier.shibboleth.admin.ui.security.model.User import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService import edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Profile @@ -156,4 +158,10 @@ class DevConfig { it }) } + + @Profile('dev-ed-versioning') + @Bean + EntityDescriptorVersionService stubEntityDescriptorVersionService(EntityDescriptorService entityDescriptorService) { + return EntityDescriptorVersionService.stubImpl(entityDescriptorService) + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java new file mode 100644 index 000000000..5f1b64b46 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java @@ -0,0 +1,15 @@ +package edu.internet2.tier.shibboleth.admin.ui.configuration; + +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class EntitiesVersioningConfiguration { + + //@Bean + EntityDescriptorVersionService entityDescriptorVersionService(EntityDescriptorService entityDescriptorService) { + //TODO create real impl when available + return null; + } +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java index 5e1542ea2..da2910834 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java @@ -4,6 +4,8 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version; +import java.time.LocalDateTime; +import java.util.Arrays; import java.util.List; /** @@ -14,4 +16,27 @@ public interface EntityDescriptorVersionService { List findVersionsForEntityDescriptor(String resourceId); EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId); + + /* Factory method to return stub impl for dev and testing purposes */ + static EntityDescriptorVersionService stubImpl(final EntityDescriptorService entityDescriptorService) { + return new EntityDescriptorVersionService() { + @Override + public List findVersionsForEntityDescriptor(String resourceId) { + return Arrays.asList( + new Version("1", "kramer", LocalDateTime.now().minusDays(10)), + new Version("2", "newman", LocalDateTime.now().minusDays(5)) + ); + } + + @Override + public EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) { + EntityDescriptor ed = new EntityDescriptor(); + ed.setID("1"); + ed.setEntityID("http://versioning/stub"); + ed.setCreatedBy("kramer"); + ed.setCreatedDate(LocalDateTime.now().minusDays(10)); + return entityDescriptorService.createRepresentationFromDescriptor(ed); + } + }; + } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy new file mode 100644 index 000000000..f3d1346e0 --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy @@ -0,0 +1,36 @@ +package edu.internet2.tier.shibboleth.admin.ui.configuration + +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService +import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +import java.time.LocalDateTime + +@Configuration +class TestEntityDescriptorVersioningConfiguration { + + @Autowired + EntityDescriptorService entityDescriptorService + + @Bean + EntityDescriptorVersionService stubEntityDescriptorVersionService() { + return new EntityDescriptorVersionService() { + @Override + List findVersionsForEntityDescriptor(String resourceId) { + return [new Version(id: '1', creator: 'kramer', date: LocalDateTime.now().minusDays(3)), + new Version(id: '2', creator: 'newman', date: LocalDateTime.now())] + } + + @Override + EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) { + return entityDescriptorService.createRepresentationFromDescriptor(new TestObjectGenerator().buildEntityDescriptor()) + } + } + } + +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy index b0626d431..eeb22048e 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.ShibbolethUiApplication import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.CustomPropertiesConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.TestEntityDescriptorVersioningConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.SPSSODescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.XSAny @@ -40,7 +41,7 @@ import org.xmlunit.diff.ElementSelectors import spock.lang.Ignore import spock.lang.Specification -@ContextConfiguration(classes=[CoreShibUiConfiguration, CustomPropertiesConfiguration]) +@ContextConfiguration(classes=[CoreShibUiConfiguration, CustomPropertiesConfiguration, TestEntityDescriptorVersioningConfiguration]) @SpringBootTest(classes = ShibbolethUiApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) @PropertySource("classpath:application.yml") class JPAEntityDescriptorServiceImplTests extends Specification { From b3c4b1fd10743e1b6adaebc4df5c132e7ad13e65 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 24 May 2019 12:07:11 -0400 Subject: [PATCH 04/51] SHIBUI-1262 [1307 WIP] --- .../admin/ui/configuration/DevConfig.groovy | 30 +++++++++++++- .../EntityDescriptors.groovy | 40 +++++++++++++++++++ .../EntityDescriptorController.java | 1 + .../admin/ui/domain/AbstractXMLObject.java | 2 + .../admin/ui/domain/EntityDescriptor.java | 13 ++++++ .../FileBackedHttpMetadataResolver.java | 2 - .../ui/domain/resolvers/MetadataResolver.java | 2 + .../EntityDescriptorVersionService.java | 4 +- 8 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/util/entitydescriptors/EntityDescriptors.groovy diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy index 2ed81b941..4887be48e 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy @@ -1,6 +1,15 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration +import edu.internet2.tier.shibboleth.admin.ui.domain.AffiliateMember +import edu.internet2.tier.shibboleth.admin.ui.domain.AffiliationDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.ContactPerson +import edu.internet2.tier.shibboleth.admin.ui.domain.EncryptionMethod import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.Extensions +import edu.internet2.tier.shibboleth.admin.ui.domain.KeyDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.Organization +import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationDisplayName +import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationName import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver @@ -9,6 +18,8 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResol import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataQueryProtocolScheme import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes +import edu.internet2.tier.shibboleth.admin.ui.domain.util.entitydescriptors.EntityDescriptors +import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.security.model.Role @@ -18,8 +29,11 @@ import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService import edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.context.event.ApplicationStartedEvent import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Profile +import org.springframework.context.event.EventListener import org.springframework.stereotype.Component import org.springframework.transaction.annotation.Transactional @@ -34,6 +48,9 @@ class DevConfig { private final MetadataResolverRepository metadataResolverRepository private final EntityDescriptorRepository entityDescriptorRepository + @Autowired + private OpenSamlObjects openSamlObjects + DevConfig(UserRepository adminUserRepository, MetadataResolverRepository metadataResolverRepository, RoleRepository roleRepository, EntityDescriptorRepository entityDescriptorRepository) { this.adminUserRepository = adminUserRepository this.metadataResolverRepository = metadataResolverRepository @@ -161,7 +178,16 @@ class DevConfig { @Profile('dev-ed-versioning') @Bean - EntityDescriptorVersionService stubEntityDescriptorVersionService(EntityDescriptorService entityDescriptorService) { - return EntityDescriptorVersionService.stubImpl(entityDescriptorService) + EntityDescriptorVersionService stubEntityDescriptorVersionService(EntityDescriptorService entityDescriptorService, + EntityDescriptorRepository entityDescriptorRepository) { + return EntityDescriptorVersionService.stubImpl(entityDescriptorService, entityDescriptorRepository) + } + + @Transactional + @EventListener + void edForVersioningDev(ApplicationStartedEvent e) { + if (e.applicationContext.environment.activeProfiles.contains('dev-ed-versioning')) { + this.entityDescriptorRepository.save(EntityDescriptors.prebakedEntityDescriptor(openSamlObjects)) + } } } diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/util/entitydescriptors/EntityDescriptors.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/util/entitydescriptors/EntityDescriptors.groovy new file mode 100644 index 000000000..b7514e2c0 --- /dev/null +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/util/entitydescriptors/EntityDescriptors.groovy @@ -0,0 +1,40 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.util.entitydescriptors + +import edu.internet2.tier.shibboleth.admin.ui.domain.ContactPerson +import edu.internet2.tier.shibboleth.admin.ui.domain.EmailAddress +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.GivenName +import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects +import org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration + +/** + * Utility class to statically construct a graph of EntityDescriptor objects useful for dev and testing. + */ +final class EntityDescriptors { + + private EntityDescriptors() { + } + + static EntityDescriptor prebakedEntityDescriptor(OpenSamlObjects openSamlObjects) { + openSamlObjects.buildDefaultInstanceOfType(EntityDescriptor.class).with { + it.contactPersons = [openSamlObjects.buildDefaultInstanceOfType(ContactPerson.class).with { + it.type = ContactPersonTypeEnumeration.ADMINISTRATIVE + it.givenName = openSamlObjects.buildDefaultInstanceOfType(GivenName.class).with { + it.name = 'name' + it + } + it.emailAddresses.add(openSamlObjects.buildDefaultInstanceOfType(EmailAddress.class).with { + it.address = 'test@test' + it + }) + it + }] + + + //Main ed + it + } + } + + +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java index b3ea0fb62..6690d4520 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java @@ -38,6 +38,7 @@ import java.net.URI; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; @RestController @RequestMapping("/api") diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractXMLObject.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractXMLObject.java index 1e8f4c2a0..5d28825fd 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractXMLObject.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractXMLObject.java @@ -3,6 +3,7 @@ import lombok.EqualsAndHashCode; import net.shibboleth.utilities.java.support.collection.LockableClassToInstanceMultiMap; import net.shibboleth.utilities.java.support.xml.QNameSupport; +import org.hibernate.envers.Audited; import org.opensaml.core.config.ConfigurationService; import org.opensaml.core.xml.Namespace; import org.opensaml.core.xml.NamespaceManager; @@ -30,6 +31,7 @@ @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @EqualsAndHashCode(callSuper = true) +@Audited public abstract class AbstractXMLObject extends AbstractAuditable implements XMLObject { private String namespaceURI; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java index 2f53e5cc8..b2b2d885c 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java @@ -4,6 +4,9 @@ import com.google.common.collect.Lists; import lombok.EqualsAndHashCode; +import org.hibernate.envers.AuditOverride; +import org.hibernate.envers.Audited; +import org.hibernate.envers.NotAudited; import org.opensaml.core.config.ConfigurationService; import org.opensaml.core.xml.XMLObject; import org.opensaml.core.xml.config.XMLObjectProviderRegistry; @@ -33,6 +36,8 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited +@AuditOverride(forClass = AbstractAuditable.class) public class EntityDescriptor extends AbstractDescriptor implements org.opensaml.saml.saml2.metadata.EntityDescriptor { private String localId; @@ -45,31 +50,39 @@ public class EntityDescriptor extends AbstractDescriptor implements org.opensaml private String resourceId; @OneToOne(cascade = CascadeType.ALL) + @NotAudited private Organization organization; @OneToMany(cascade = CascadeType.ALL) @OrderColumn + @NotAudited private List contactPersons = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL) @OrderColumn + @NotAudited private List roleDescriptors; @OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "entitydesc_addlmetdatlocations_id") @OrderColumn + @NotAudited private List additionalMetadataLocations = new ArrayList<>(); @OneToOne(cascade = CascadeType.ALL) + @NotAudited private AuthnAuthorityDescriptor authnAuthorityDescriptor; @OneToOne(cascade = CascadeType.ALL) + @NotAudited private AttributeAuthorityDescriptor attributeAuthorityDescriptor; @OneToOne(cascade = CascadeType.ALL) + @NotAudited private PDPDescriptor pdpDescriptor; @OneToOne(cascade = CascadeType.ALL) + @NotAudited private AffiliationDescriptor affiliationDescriptor; public EntityDescriptor() { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java index 4ffadae52..b80b8190f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/FileBackedHttpMetadataResolver.java @@ -16,8 +16,6 @@ @Getter @Setter @ToString -@Audited -@AuditOverride(forClass = AbstractAuditable.class) public class FileBackedHttpMetadataResolver extends MetadataResolver { public FileBackedHttpMetadataResolver() { type = "FileBackedHttpMetadataResolver"; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java index ec639ba38..11300c3b7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java @@ -11,6 +11,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; +import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; import javax.persistence.CascadeType; @@ -39,6 +40,7 @@ @JsonSubTypes.Type(value = FilesystemMetadataResolver.class, name = "FilesystemMetadataResolver"), @JsonSubTypes.Type(value = ResourceBackedMetadataResolver.class, name = "ResourceBackedMetadataResolver")}) @Audited +@AuditOverride(forClass = AbstractAuditable.class) public class MetadataResolver extends AbstractAuditable { @JsonProperty("@type") diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java index da2910834..e53072f99 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java @@ -3,6 +3,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version; +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository; import java.time.LocalDateTime; import java.util.Arrays; @@ -18,7 +19,8 @@ public interface EntityDescriptorVersionService { EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId); /* Factory method to return stub impl for dev and testing purposes */ - static EntityDescriptorVersionService stubImpl(final EntityDescriptorService entityDescriptorService) { + static EntityDescriptorVersionService stubImpl(final EntityDescriptorService entityDescriptorService, + final EntityDescriptorRepository entityDescriptorRepository) { return new EntityDescriptorVersionService() { @Override public List findVersionsForEntityDescriptor(String resourceId) { From c69d412a8af8f17268b5fe35d8d00f725fe0c72e Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 28 May 2019 10:05:04 -0400 Subject: [PATCH 05/51] SHIBUI-1262 [1307 WIP] --- ...sonSchemaValidatingControllerAdvice.groovy | 2 +- .../admin/ui/domain/AbstractXMLObject.java | 2 + .../admin/ui/domain/ContactPerson.java | 7 ++ .../admin/ui/domain/EmailAddress.java | 3 + .../admin/ui/domain/EntityDescriptor.java | 2 - .../shibboleth/admin/ui/domain/GivenName.java | 3 + ...tityDescriptorEnversVersioningTests.groovy | 65 +++++++++++++++++++ .../envers/EnversTestsSupport.groovy | 20 ++++++ 8 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy index 9151e4ef4..bd3050cfd 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy @@ -24,7 +24,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocati * * @author Dmitriy Kopylenko */ -@ControllerAdvice +//@ControllerAdvice class RelyingPartyOverridesJsonSchemaValidatingControllerAdvice extends RequestBodyAdviceAdapter { @Autowired diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractXMLObject.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractXMLObject.java index 5d28825fd..3b4ac0d92 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractXMLObject.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractXMLObject.java @@ -3,6 +3,7 @@ import lombok.EqualsAndHashCode; import net.shibboleth.utilities.java.support.collection.LockableClassToInstanceMultiMap; import net.shibboleth.utilities.java.support.xml.QNameSupport; +import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; import org.opensaml.core.config.ConfigurationService; import org.opensaml.core.xml.Namespace; @@ -32,6 +33,7 @@ @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @EqualsAndHashCode(callSuper = true) @Audited +@AuditOverride(forClass = AbstractAuditable.class) public abstract class AbstractXMLObject extends AbstractAuditable implements XMLObject { private String namespaceURI; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ContactPerson.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ContactPerson.java index 104dc076f..ca0400f32 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ContactPerson.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ContactPerson.java @@ -1,6 +1,8 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; +import org.hibernate.envers.NotAudited; import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration; @@ -12,20 +14,24 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class ContactPerson extends AbstractAttributeExtensibleXMLObject implements org.opensaml.saml.saml2.metadata.ContactPerson { private String contactPersonType; @OneToOne(cascade = CascadeType.ALL) + @NotAudited private Extensions extensions; @OneToOne(cascade = CascadeType.ALL) + @NotAudited private Company company; @OneToOne(cascade = CascadeType.ALL) private GivenName givenName; @OneToOne(cascade = CascadeType.ALL) + @NotAudited private SurName surName; @OneToMany(cascade = CascadeType.ALL) @@ -36,6 +42,7 @@ public class ContactPerson extends AbstractAttributeExtensibleXMLObject implemen @OneToMany(cascade = CascadeType.ALL) @JoinColumn(name = "contactpersn_telenmbr_id") @OrderColumn + @NotAudited private List telephoneNumbers = new ArrayList<>(); @Override diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java index 313ebd65e..2cf346579 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java @@ -1,11 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.AuditOverride; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class EmailAddress extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.EmailAddress { private String address; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java index b2b2d885c..c9b7d207d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java @@ -37,7 +37,6 @@ @Entity @EqualsAndHashCode(callSuper = true) @Audited -@AuditOverride(forClass = AbstractAuditable.class) public class EntityDescriptor extends AbstractDescriptor implements org.opensaml.saml.saml2.metadata.EntityDescriptor { private String localId; @@ -55,7 +54,6 @@ public class EntityDescriptor extends AbstractDescriptor implements org.opensaml @OneToMany(cascade = CascadeType.ALL) @OrderColumn - @NotAudited private List contactPersons = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java index 785b60804..612733fc4 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java @@ -1,11 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.AuditOverride; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class GivenName extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.GivenName { private String name; diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy new file mode 100644 index 000000000..424eff552 --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -0,0 +1,65 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository.envers + +import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import org.hibernate.envers.AuditReaderFactory +import org.hibernate.envers.query.AuditQuery +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.domain.EntityScan +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.context.ContextConfiguration +import org.springframework.transaction.PlatformTransactionManager +import spock.lang.Specification + +import javax.persistence.EntityManager + +import static edu.internet2.tier.shibboleth.admin.ui.domain.util.entitydescriptors.EntityDescriptors.prebakedEntityDescriptor +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction + +/** + * Testing entity descriptor envers versioning + */ +@DataJpaTest +@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration]) +@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) +@EntityScan("edu.internet2.tier.shibboleth.admin.ui") +class EntityDescriptorEnversVersioningTests extends Specification { + + @Autowired + EntityDescriptorRepository entityDescriptorRepository + + @Autowired + EntityManager entityManager + + @Autowired + PlatformTransactionManager txMgr + + @Autowired + OpenSamlObjects openSamlObjects + + def "test versioning with contact persons"() { + when: + EntityDescriptor ed = doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(prebakedEntityDescriptor(openSamlObjects)) + } + def entityDescriptorHistory = resolverHistory() + + then: + entityDescriptorHistory.size() == 1 + } + + private resolverHistory() { + def auditReader = AuditReaderFactory.get(entityManager) + AuditQuery auditQuery = auditReader + .createQuery() + .forRevisionsOfEntity(EntityDescriptor, false, false) + auditQuery.resultList + + } +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy new file mode 100644 index 000000000..cbeb93c9b --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy @@ -0,0 +1,20 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository.envers + +import org.springframework.transaction.PlatformTransactionManager +import org.springframework.transaction.support.DefaultTransactionDefinition + +import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW + +class EnversTestsSupport { + + //This explicit low level transaction dance is required in order to verify history/version data that envers + //writes out only after the explicit transaction is committed, therefore making it impossible to verify within the main tx + //boundary of the test method which commits tx only after an execution of the test method. This let's us explicitly + //start/commit transaction making envers data written out and verifiable + static doInExplicitTransaction(PlatformTransactionManager txMgr, Closure uow) { + def txStatus = txMgr.getTransaction(new DefaultTransactionDefinition(PROPAGATION_REQUIRES_NEW)) + def entity = uow() + txMgr.commit(txStatus) + entity + } +} From a328e514adfb5baefbc00fb3010396744028c8e6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 28 May 2019 11:30:28 -0400 Subject: [PATCH 06/51] SHIBUI-1262 [1307 WIP] --- ...tityDescriptorEnversVersioningTests.groovy | 59 ++++++++++++++++++- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 424eff552..73d857bb6 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -5,8 +5,11 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.Internationalization import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService import org.hibernate.envers.AuditReaderFactory import org.hibernate.envers.query.AuditQuery import org.springframework.beans.factory.annotation.Autowired @@ -21,6 +24,8 @@ import javax.persistence.EntityManager import static edu.internet2.tier.shibboleth.admin.ui.domain.util.entitydescriptors.EntityDescriptors.prebakedEntityDescriptor import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction +import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE +import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER /** * Testing entity descriptor envers versioning @@ -34,6 +39,9 @@ class EntityDescriptorEnversVersioningTests extends Specification { @Autowired EntityDescriptorRepository entityDescriptorRepository + @Autowired + EntityDescriptorService entityDescriptorService + @Autowired EntityManager entityManager @@ -48,18 +56,63 @@ class EntityDescriptorEnversVersioningTests extends Specification { EntityDescriptor ed = doInExplicitTransaction(txMgr) { entityDescriptorRepository.save(prebakedEntityDescriptor(openSamlObjects)) } - def entityDescriptorHistory = resolverHistory() + def entityDescriptorHistory = getRevisionHistory() then: entityDescriptorHistory.size() == 1 + + when: + def representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'administrative', name: 'nameUPDATED', emailAddress: 'test@test')] + it + } + entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation) + + then: + entityDescriptorHistory.size() == 2 + entityDescriptorHistory[1][0].contactPersons[0].givenName.name == 'nameUPDATED' + entityDescriptorHistory[1][0].contactPersons[0].type == ADMINISTRATIVE + entityDescriptorHistory[1][1].principalUserName == 'anonymous' + entityDescriptorHistory[1][1].timestamp > 0L + + when: + representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED', emailAddress: 'test@test.com')] + it + } + entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation) + + ed.contactPersons[0].emailAddresses[0].address + then: + entityDescriptorHistory.size() == 3 + entityDescriptorHistory[2][0].contactPersons[0].givenName.name == 'nameUPDATED' + entityDescriptorHistory[2][0].contactPersons[0].type == OTHER + entityDescriptorHistory[2][0].contactPersons[0].emailAddresses[0].address == 'test@test.com' + entityDescriptorHistory[2][1].principalUserName == 'anonymous' + entityDescriptorHistory[2][1].timestamp > 0L + + //Also make sure we have our original revision + entityDescriptorHistory[0][0].contactPersons[0].givenName.name == 'name' + entityDescriptorHistory[0][0].contactPersons[0].type == ADMINISTRATIVE + entityDescriptorHistory[0][0].contactPersons[0].emailAddresses[0].address == 'test@test' + entityDescriptorHistory[0][1].principalUserName == 'anonymous' + entityDescriptorHistory[0][1].timestamp > 0L + } - private resolverHistory() { + private updateAndGetRevisionHistory(ed, representation) { + entityDescriptorService.updateDescriptorFromRepresentation(ed, representation) + doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + getRevisionHistory() + } + + private getRevisionHistory() { def auditReader = AuditReaderFactory.get(entityManager) AuditQuery auditQuery = auditReader .createQuery() .forRevisionsOfEntity(EntityDescriptor, false, false) auditQuery.resultList - } } From be74f0b1ff97e0c01b831c54ce85f4945eaabcc0 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 28 May 2019 11:37:25 -0400 Subject: [PATCH 07/51] SHIBUI-1262 [1307 WIP] --- .../envers/EntityDescriptorEnversVersioningTests.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 73d857bb6..6c0305c57 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -82,7 +82,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { } entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation) - ed.contactPersons[0].emailAddresses[0].address then: entityDescriptorHistory.size() == 3 entityDescriptorHistory[2][0].contactPersons[0].givenName.name == 'nameUPDATED' From 0d4a43d356b7ca056882152260b93f04b08d1bca Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 28 May 2019 12:07:57 -0400 Subject: [PATCH 08/51] SHIBUI-1262 [1307 WIP] --- ...tityDescriptorEnversVersioningTests.groovy | 33 +++++++------------ .../envers/EnversTestsSupport.groovy | 27 +++++++++++++++ 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 6c0305c57..db54aa66a 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -10,8 +10,6 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRe import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService -import org.hibernate.envers.AuditReaderFactory -import org.hibernate.envers.query.AuditQuery import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest @@ -24,6 +22,8 @@ import javax.persistence.EntityManager import static edu.internet2.tier.shibboleth.admin.ui.domain.util.entitydescriptors.EntityDescriptors.prebakedEntityDescriptor import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionHistory +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistory import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER @@ -56,7 +56,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { EntityDescriptor ed = doInExplicitTransaction(txMgr) { entityDescriptorRepository.save(prebakedEntityDescriptor(openSamlObjects)) } - def entityDescriptorHistory = getRevisionHistory() + def entityDescriptorHistory = getRevisionHistory(entityManager) then: entityDescriptorHistory.size() == 1 @@ -66,7 +66,10 @@ class EntityDescriptorEnversVersioningTests extends Specification { it.contacts = [new ContactRepresentation(type: 'administrative', name: 'nameUPDATED', emailAddress: 'test@test')] it } - entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation) + entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) then: entityDescriptorHistory.size() == 2 @@ -80,7 +83,11 @@ class EntityDescriptorEnversVersioningTests extends Specification { it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED', emailAddress: 'test@test.com')] it } - entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation) + entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, + entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) then: entityDescriptorHistory.size() == 3 @@ -98,20 +105,4 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorHistory[0][1].timestamp > 0L } - - private updateAndGetRevisionHistory(ed, representation) { - entityDescriptorService.updateDescriptorFromRepresentation(ed, representation) - doInExplicitTransaction(txMgr) { - entityDescriptorRepository.save(ed) - } - getRevisionHistory() - } - - private getRevisionHistory() { - def auditReader = AuditReaderFactory.get(entityManager) - AuditQuery auditQuery = auditReader - .createQuery() - .forRevisionsOfEntity(EntityDescriptor, false, false) - auditQuery.resultList - } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy index cbeb93c9b..93fc12c1f 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy @@ -1,8 +1,15 @@ package edu.internet2.tier.shibboleth.admin.ui.repository.envers +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService +import org.hibernate.envers.AuditReaderFactory +import org.hibernate.envers.query.AuditQuery import org.springframework.transaction.PlatformTransactionManager import org.springframework.transaction.support.DefaultTransactionDefinition +import javax.persistence.EntityManager + import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW class EnversTestsSupport { @@ -17,4 +24,24 @@ class EnversTestsSupport { txMgr.commit(txStatus) entity } + + static updateAndGetRevisionHistory(ed, representation, + EntityDescriptorService eds, + EntityDescriptorRepository edr, + PlatformTransactionManager txMgr, + EntityManager em) { + eds.updateDescriptorFromRepresentation(ed, representation) + doInExplicitTransaction(txMgr) { + edr.save(ed) + } + getRevisionHistory(em) + } + + static getRevisionHistory(EntityManager em) { + def auditReader = AuditReaderFactory.get(em) + AuditQuery auditQuery = auditReader + .createQuery() + .forRevisionsOfEntity(EntityDescriptor, false, false) + auditQuery.resultList + } } From aa26d56f2e5534e0733d581d2d50872bcac2300f Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 28 May 2019 16:03:34 -0400 Subject: [PATCH 09/51] SHIBUI-1262 [1307 WIP] --- ...tityDescriptorEnversVersioningTests.groovy | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index db54aa66a..9e5b47f70 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -4,18 +4,23 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfigurat import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.ContactPerson +import edu.internet2.tier.shibboleth.admin.ui.domain.EmailAddress import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.GivenName import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService +import org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest import org.springframework.data.jpa.repository.config.EnableJpaRepositories import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager +import spock.lang.Shared import spock.lang.Specification import javax.persistence.EntityManager @@ -51,18 +56,30 @@ class EntityDescriptorEnversVersioningTests extends Specification { @Autowired OpenSamlObjects openSamlObjects + @Shared + EntityDescriptor ed = new EntityDescriptor() + def "test versioning with contact persons"() { when: - EntityDescriptor ed = doInExplicitTransaction(txMgr) { - entityDescriptorRepository.save(prebakedEntityDescriptor(openSamlObjects)) + def representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] + it } - def entityDescriptorHistory = getRevisionHistory(entityManager) + def entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) then: entityDescriptorHistory.size() == 1 + entityDescriptorHistory[0][0].contactPersons[0].givenName.name == 'name' + entityDescriptorHistory[0][0].contactPersons[0].type == ADMINISTRATIVE + entityDescriptorHistory[0][0].contactPersons[0].emailAddresses[0].address == 'test@test' + entityDescriptorHistory[0][1].principalUserName == 'anonymous' + entityDescriptorHistory[0][1].timestamp > 0L when: - def representation = new EntityDescriptorRepresentation().with { + representation = new EntityDescriptorRepresentation().with { it.contacts = [new ContactRepresentation(type: 'administrative', name: 'nameUPDATED', emailAddress: 'test@test')] it } @@ -75,12 +92,13 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorHistory.size() == 2 entityDescriptorHistory[1][0].contactPersons[0].givenName.name == 'nameUPDATED' entityDescriptorHistory[1][0].contactPersons[0].type == ADMINISTRATIVE + entityDescriptorHistory[1][0].contactPersons[0].emailAddresses[0].address == 'test@test' entityDescriptorHistory[1][1].principalUserName == 'anonymous' entityDescriptorHistory[1][1].timestamp > 0L when: representation = new EntityDescriptorRepresentation().with { - it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED', emailAddress: 'test@test.com')] + it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED2', emailAddress: 'test@test.com')] it } entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, @@ -91,7 +109,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { then: entityDescriptorHistory.size() == 3 - entityDescriptorHistory[2][0].contactPersons[0].givenName.name == 'nameUPDATED' + entityDescriptorHistory[2][0].contactPersons[0].givenName.name == 'nameUPDATED2' entityDescriptorHistory[2][0].contactPersons[0].type == OTHER entityDescriptorHistory[2][0].contactPersons[0].emailAddresses[0].address == 'test@test.com' entityDescriptorHistory[2][1].principalUserName == 'anonymous' From 77e3f60e0e2cf71c3e6f734bc7f7bf85ca0bcde6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 28 May 2019 16:04:25 -0400 Subject: [PATCH 10/51] SHIBUI-1262 [1307 WIP] --- .../envers/EntityDescriptorEnversVersioningTests.groovy | 7 ------- 1 file changed, 7 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 9e5b47f70..7ef59d0c7 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -4,16 +4,12 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfigurat import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration -import edu.internet2.tier.shibboleth.admin.ui.domain.ContactPerson -import edu.internet2.tier.shibboleth.admin.ui.domain.EmailAddress import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.GivenName import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService -import org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest @@ -25,9 +21,6 @@ import spock.lang.Specification import javax.persistence.EntityManager -import static edu.internet2.tier.shibboleth.admin.ui.domain.util.entitydescriptors.EntityDescriptors.prebakedEntityDescriptor -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionHistory import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistory import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER From a57d648716b0c76bcfbe87ed6d3c12aea2c761e2 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 28 May 2019 16:06:40 -0400 Subject: [PATCH 11/51] SHIBUI-1262 [1307 WIP] --- .../admin/ui/configuration/DevConfig.groovy | 1 - .../EntityDescriptors.groovy | 40 ------------------- 2 files changed, 41 deletions(-) delete mode 100644 backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/util/entitydescriptors/EntityDescriptors.groovy diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy index 4887be48e..582624141 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy @@ -18,7 +18,6 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResol import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataQueryProtocolScheme import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes -import edu.internet2.tier.shibboleth.admin.ui.domain.util.entitydescriptors.EntityDescriptors import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/util/entitydescriptors/EntityDescriptors.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/util/entitydescriptors/EntityDescriptors.groovy deleted file mode 100644 index b7514e2c0..000000000 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/util/entitydescriptors/EntityDescriptors.groovy +++ /dev/null @@ -1,40 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.domain.util.entitydescriptors - -import edu.internet2.tier.shibboleth.admin.ui.domain.ContactPerson -import edu.internet2.tier.shibboleth.admin.ui.domain.EmailAddress -import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.GivenName -import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects -import org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration - -/** - * Utility class to statically construct a graph of EntityDescriptor objects useful for dev and testing. - */ -final class EntityDescriptors { - - private EntityDescriptors() { - } - - static EntityDescriptor prebakedEntityDescriptor(OpenSamlObjects openSamlObjects) { - openSamlObjects.buildDefaultInstanceOfType(EntityDescriptor.class).with { - it.contactPersons = [openSamlObjects.buildDefaultInstanceOfType(ContactPerson.class).with { - it.type = ContactPersonTypeEnumeration.ADMINISTRATIVE - it.givenName = openSamlObjects.buildDefaultInstanceOfType(GivenName.class).with { - it.name = 'name' - it - } - it.emailAddresses.add(openSamlObjects.buildDefaultInstanceOfType(EmailAddress.class).with { - it.address = 'test@test' - it - }) - it - }] - - - //Main ed - it - } - } - - -} From 7d876571b15f5378a7a2efe727ff9e0a233765b4 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 28 May 2019 16:06:53 -0400 Subject: [PATCH 12/51] SHIBUI-1262 [1307 WIP] --- .../admin/ui/configuration/DevConfig.groovy | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy index 582624141..1c2dc4cd1 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy @@ -1,23 +1,10 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration -import edu.internet2.tier.shibboleth.admin.ui.domain.AffiliateMember -import edu.internet2.tier.shibboleth.admin.ui.domain.AffiliationDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.ContactPerson -import edu.internet2.tier.shibboleth.admin.ui.domain.EncryptionMethod + import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.Extensions -import edu.internet2.tier.shibboleth.admin.ui.domain.KeyDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.Organization -import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationDisplayName -import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationName import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataQueryProtocolScheme -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.* import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository From dcf2ec2759294ae38cefccc5e061a68db6eb2ab4 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 28 May 2019 16:11:02 -0400 Subject: [PATCH 13/51] SHIBUI-1262 [1307 WIP] --- .../shibboleth/admin/ui/configuration/DevConfig.groovy | 8 -------- 1 file changed, 8 deletions(-) diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy index 1c2dc4cd1..6f853e089 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy @@ -168,12 +168,4 @@ class DevConfig { EntityDescriptorRepository entityDescriptorRepository) { return EntityDescriptorVersionService.stubImpl(entityDescriptorService, entityDescriptorRepository) } - - @Transactional - @EventListener - void edForVersioningDev(ApplicationStartedEvent e) { - if (e.applicationContext.environment.activeProfiles.contains('dev-ed-versioning')) { - this.entityDescriptorRepository.save(EntityDescriptors.prebakedEntityDescriptor(openSamlObjects)) - } - } } From a8e82ba8c603d1fc76d45cf0f4da82ecb461c051 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 29 May 2019 16:46:17 -0400 Subject: [PATCH 14/51] SHIBUI-1262 [1307 WIP] --- .../AbstractElementExtensibleXMLObject.java | 2 + .../admin/ui/domain/EncryptionMethod.java | 2 + .../shibboleth/admin/ui/domain/Endpoint.java | 4 +- .../admin/ui/domain/EntityDescriptor.java | 13 +---- .../admin/ui/domain/Extensions.java | 2 + .../admin/ui/domain/KeyDescriptor.java | 2 + .../shibboleth/admin/ui/domain/KeyInfo.java | 2 + .../admin/ui/domain/LocalizedName.java | 3 ++ .../admin/ui/domain/Organization.java | 2 + .../ui/domain/OrganizationDisplayName.java | 2 + .../admin/ui/domain/OrganizationName.java | 2 + .../admin/ui/domain/OrganizationURL.java | 2 + .../admin/ui/domain/RoleDescriptor.java | 2 + ...tityDescriptorEnversVersioningTests.groovy | 50 +++++++++++++++++-- 14 files changed, 73 insertions(+), 17 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractElementExtensibleXMLObject.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractElementExtensibleXMLObject.java index d406e8256..03a91e284 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractElementExtensibleXMLObject.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractElementExtensibleXMLObject.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.ElementExtensibleXMLObject; import org.opensaml.core.xml.XMLObject; @@ -20,6 +21,7 @@ @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @EqualsAndHashCode(callSuper = true) +@Audited public abstract class AbstractElementExtensibleXMLObject extends AbstractXMLObject implements ElementExtensibleXMLObject { @OneToMany(cascade = CascadeType.ALL) @OrderColumn diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java index 688dea31d..06a47da63 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EncryptionMethod.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.xmlsec.encryption.KeySize; import org.opensaml.xmlsec.encryption.OAEPparams; @@ -10,6 +11,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class EncryptionMethod extends AbstractElementExtensibleXMLObject implements org.opensaml.saml.saml2.metadata.EncryptionMethod { private String algorithm; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Endpoint.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Endpoint.java index 97094187a..2699895a0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Endpoint.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Endpoint.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import javax.annotation.Nonnull; @@ -14,6 +15,7 @@ */ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class Endpoint extends AbstractAttributeExtensibleXMLObject implements org.opensaml.saml.saml2.metadata.Endpoint { private String binding; @@ -72,4 +74,4 @@ public List getUnknownXMLObjects() { public List getUnknownXMLObjects(@Nonnull QName qName) { return null; //TODO } -} \ No newline at end of file +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java index c9b7d207d..b2054d362 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java @@ -2,30 +2,21 @@ import com.google.common.base.MoreObjects; import com.google.common.collect.Lists; - import lombok.EqualsAndHashCode; -import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; import org.hibernate.envers.NotAudited; -import org.opensaml.core.config.ConfigurationService; import org.opensaml.core.xml.XMLObject; -import org.opensaml.core.xml.config.XMLObjectProviderRegistry; -import org.opensaml.core.xml.io.MarshallingException; import org.springframework.util.StringUtils; -import org.w3c.dom.Element; import javax.annotation.Nullable; - -import javax.persistence.JoinColumn; import javax.persistence.CascadeType; import javax.persistence.Entity; +import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.OrderColumn; import javax.persistence.Transient; - import javax.xml.namespace.QName; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -49,7 +40,6 @@ public class EntityDescriptor extends AbstractDescriptor implements org.opensaml private String resourceId; @OneToOne(cascade = CascadeType.ALL) - @NotAudited private Organization organization; @OneToMany(cascade = CascadeType.ALL) @@ -58,7 +48,6 @@ public class EntityDescriptor extends AbstractDescriptor implements org.opensaml @OneToMany(cascade = CascadeType.ALL) @OrderColumn - @NotAudited private List roleDescriptors; @OneToMany(cascade = CascadeType.ALL) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Extensions.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Extensions.java index c1538f463..01dcf4aa8 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Extensions.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Extensions.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import javax.annotation.Nullable; @@ -13,6 +14,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class Extensions extends AbstractElementExtensibleXMLObject implements org.opensaml.saml.saml2.metadata.Extensions { @Nullable @Override diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/KeyDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/KeyDescriptor.java index 74ddbaa2c..2b07eea4c 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/KeyDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/KeyDescriptor.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import org.opensaml.security.credential.UsageType; import org.opensaml.xmlsec.signature.KeyInfo; @@ -12,6 +13,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class KeyDescriptor extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.KeyDescriptor { @Column(name = "keyDescriptorName") diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/KeyInfo.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/KeyInfo.java index 7ea604d17..7497e5837 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/KeyInfo.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/KeyInfo.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import org.opensaml.xmlsec.encryption.AgreementMethod; import org.opensaml.xmlsec.encryption.EncryptedKey; @@ -29,6 +30,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class KeyInfo extends AbstractXMLObject implements org.opensaml.xmlsec.signature.KeyInfo { @OneToMany(cascade = CascadeType.ALL) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/LocalizedName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/LocalizedName.java index 2aa493293..e0a54d494 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/LocalizedName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/LocalizedName.java @@ -1,9 +1,12 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; +import org.hibernate.envers.Audited; + import javax.annotation.Nullable; import javax.persistence.MappedSuperclass; @MappedSuperclass +@Audited public class LocalizedName extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.LocalizedName { private String xMLLang; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Organization.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Organization.java index 1e11b499e..7ea76b1f0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Organization.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Organization.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import javax.annotation.Nullable; @@ -11,6 +12,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class Organization extends AbstractAttributeExtensibleXMLObject implements org.opensaml.saml.saml2.metadata.Organization { @OneToOne(cascade = CascadeType.ALL) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationDisplayName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationDisplayName.java index 8d473aa82..971217fd8 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationDisplayName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationDisplayName.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class OrganizationDisplayName extends LocalizedName implements org.opensaml.saml.saml2.metadata.OrganizationDisplayName { } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationName.java index edc9317c1..5af2408b9 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationName.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class OrganizationName extends LocalizedName implements org.opensaml.saml.saml2.metadata.OrganizationName { } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java index 6af0d7318..1cf739ece 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java @@ -1,12 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class OrganizationURL extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.OrganizationURL { private String xMLLang; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RoleDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RoleDescriptor.java index fc235c110..b5bc78bc6 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RoleDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RoleDescriptor.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import org.opensaml.core.xml.util.AttributeMap; @@ -25,6 +26,7 @@ @Entity @EqualsAndHashCode(callSuper = true, exclude={"unknownAttributes"}) +@Audited public class RoleDescriptor extends AbstractDescriptor implements org.opensaml.saml.saml2.metadata.RoleDescriptor { @ElementCollection diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 7ef59d0c7..89de05a5e 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -7,6 +7,7 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService @@ -16,7 +17,6 @@ import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest import org.springframework.data.jpa.repository.config.EnableJpaRepositories import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager -import spock.lang.Shared import spock.lang.Specification import javax.persistence.EntityManager @@ -49,11 +49,9 @@ class EntityDescriptorEnversVersioningTests extends Specification { @Autowired OpenSamlObjects openSamlObjects - @Shared - EntityDescriptor ed = new EntityDescriptor() - def "test versioning with contact persons"() { when: + def ed = new EntityDescriptor() def representation = new EntityDescriptorRepresentation().with { it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] it @@ -116,4 +114,48 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorHistory[0][1].timestamp > 0L } + + def "test versioning with organization"() { + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.organization = new OrganizationRepresentation(name: 'org', displayName: 'display org', url: 'http://org.edu') + it + } + def entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + then: + entityDescriptorHistory.size() == 1 + entityDescriptorHistory[0][0].organization.organizationNames[0].value == 'org' + entityDescriptorHistory[0][0].organization.displayNames[0].value == 'display org' + entityDescriptorHistory[0][0].organization.URLs[0].value == 'http://org.edu' + entityDescriptorHistory[0][1].principalUserName == 'anonymous' + entityDescriptorHistory[0][1].timestamp > 0L + + when: + representation = new EntityDescriptorRepresentation().with { + it.organization = new OrganizationRepresentation(name: 'orgUpdated', displayName: 'display org Updated', url: 'http://org2.edu') + it + } + entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + then: + entityDescriptorHistory.size() == 2 + entityDescriptorHistory[1][0].organization.organizationNames[0].value == 'orgUpdated' + entityDescriptorHistory[1][0].organization.displayNames[0].value == 'display org Updated' + entityDescriptorHistory[1][0].organization.URLs[0].value == 'http://org2.edu' + entityDescriptorHistory[1][1].principalUserName == 'anonymous' + entityDescriptorHistory[1][1].timestamp > 0L + + //Check the original revision is intact + entityDescriptorHistory[0][0].organization.organizationNames[0].value == 'org' + entityDescriptorHistory[0][0].organization.displayNames[0].value == 'display org' + entityDescriptorHistory[0][0].organization.URLs[0].value == 'http://org.edu' + entityDescriptorHistory[0][1].principalUserName == 'anonymous' + entityDescriptorHistory[0][1].timestamp > 0L + } } From d8b98d6f682e7d548d61ba24a560e980d46f6812 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 30 May 2019 11:34:44 -0400 Subject: [PATCH 15/51] SHIBUI-1262 [1307 WIP] --- .../admin/ui/domain/AbstractDescriptor.java | 2 + .../ui/domain/ArtifactResolutionService.java | 2 + .../ui/domain/AssertionConsumerService.java | 2 + .../shibboleth/admin/ui/domain/Attribute.java | 2 + .../ui/domain/AttributeConsumingService.java | 2 + .../admin/ui/domain/IndexedEndpoint.java | 2 + .../admin/ui/domain/ManageNameIDService.java | 2 + .../admin/ui/domain/NameIDFormat.java | 2 + .../admin/ui/domain/RequestedAttribute.java | 2 + .../admin/ui/domain/SPSSODescriptor.java | 2 + .../admin/ui/domain/SSODescriptor.java | 2 + .../admin/ui/domain/ServiceDescription.java | 2 + .../admin/ui/domain/ServiceName.java | 2 + .../admin/ui/domain/SingleLogoutService.java | 2 + ...tityDescriptorEnversVersioningTests.groovy | 62 +++++++++++++++++++ .../envers/EnversTestsSupport.groovy | 7 ++- 16 files changed, 96 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java index 1f6075f24..449cda701 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java @@ -2,6 +2,7 @@ import lombok.EqualsAndHashCode; import org.hibernate.annotations.Type; +import org.hibernate.envers.Audited; import org.joda.time.DateTime; import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.saml2.common.CacheableSAMLObject; @@ -18,6 +19,7 @@ @MappedSuperclass @EqualsAndHashCode(callSuper = true) +@Audited public abstract class AbstractDescriptor extends AbstractAttributeExtensibleXMLObject implements CacheableSAMLObject, TimeBoundSAMLObject, SignableXMLObject { private Long cacheDuration; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ArtifactResolutionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ArtifactResolutionService.java index 0d82f8a0d..1231299a7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ArtifactResolutionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ArtifactResolutionService.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class ArtifactResolutionService extends IndexedEndpoint implements org.opensaml.saml.saml2.metadata.ArtifactResolutionService { } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AssertionConsumerService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AssertionConsumerService.java index a89045075..f63a76fcd 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AssertionConsumerService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AssertionConsumerService.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class AssertionConsumerService extends IndexedEndpoint implements org.opensaml.saml.saml2.metadata.AssertionConsumerService { } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Attribute.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Attribute.java index 45e1500e9..7a187bd99 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Attribute.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Attribute.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import javax.annotation.Nullable; @@ -15,6 +16,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class Attribute extends AbstractAttributeExtensibleXMLObject implements org.opensaml.saml.saml2.core.Attribute { private String name; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java index 5080c1fc0..a1dba47fa 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.schema.XSBooleanValue; import javax.persistence.CascadeType; @@ -14,6 +15,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class AttributeConsumingService extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.AttributeConsumingService { private int acsIndex; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/IndexedEndpoint.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/IndexedEndpoint.java index e8d8f1551..cc0fdd6d5 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/IndexedEndpoint.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/IndexedEndpoint.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.schema.XSBooleanValue; import javax.persistence.Entity; @@ -8,6 +9,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class IndexedEndpoint extends Endpoint implements org.opensaml.saml.saml2.metadata.IndexedEndpoint { private Integer endpointIndex; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ManageNameIDService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ManageNameIDService.java index ec43780d3..70924db96 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ManageNameIDService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ManageNameIDService.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class ManageNameIDService extends Endpoint implements org.opensaml.saml.saml2.metadata.ManageNameIDService { } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java index 4e63ff301..148ec91e7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class NameIDFormat extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.NameIDFormat { private String format; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RequestedAttribute.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RequestedAttribute.java index a7860e931..17c932ed2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RequestedAttribute.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RequestedAttribute.java @@ -1,12 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.schema.XSBooleanValue; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class RequestedAttribute extends Attribute implements org.opensaml.saml.saml2.metadata.RequestedAttribute { private boolean isRequired; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SPSSODescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SPSSODescriptor.java index 379c2c928..e90542c5a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SPSSODescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SPSSODescriptor.java @@ -2,6 +2,7 @@ import com.google.common.collect.Lists; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import org.opensaml.core.xml.schema.XSBooleanValue; @@ -14,6 +15,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class SPSSODescriptor extends SSODescriptor implements org.opensaml.saml.saml2.metadata.SPSSODescriptor { private Boolean isAuthnRequestsSigned; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SSODescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SSODescriptor.java index 1f34fc931..4e885581d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SSODescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SSODescriptor.java @@ -2,6 +2,7 @@ import com.google.common.collect.Lists; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import javax.annotation.Nullable; @@ -17,6 +18,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class SSODescriptor extends RoleDescriptor implements org.opensaml.saml.saml2.metadata.SSODescriptor { @OneToMany(cascade = CascadeType.ALL) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ServiceDescription.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ServiceDescription.java index 4c3a54511..9fda942ae 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ServiceDescription.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ServiceDescription.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class ServiceDescription extends LocalizedName implements org.opensaml.saml.saml2.metadata.ServiceDescription { } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ServiceName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ServiceName.java index b4047f0c8..7e23c2b67 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ServiceName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/ServiceName.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class ServiceName extends LocalizedName implements org.opensaml.saml.saml2.metadata.ServiceName { } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SingleLogoutService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SingleLogoutService.java index 67967676e..ca9aa095c 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SingleLogoutService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SingleLogoutService.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class SingleLogoutService extends Endpoint implements org.opensaml.saml.saml2.metadata.SingleLogoutService { } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 89de05a5e..f0f02421d 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -8,6 +8,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService @@ -20,6 +21,7 @@ import org.springframework.transaction.PlatformTransactionManager import spock.lang.Specification import javax.persistence.EntityManager +import java.time.LocalDateTime import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistory import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE @@ -158,4 +160,64 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorHistory[0][1].principalUserName == 'anonymous' entityDescriptorHistory[0][1].timestamp > 0L } + + def "test versioning with sp sso descriptor"() { + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { + it.protocolSupportEnum = 'SAML 1.1' + it.nameIdFormats = ['format'] + it + } + it + } + def entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 1 + entityDescriptorHistory[0][0].roleDescriptors[0].nameIDFormats[0].format == 'format' + entityDescriptorHistory[0][0].roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + entityDescriptorHistory[0][0].roleDescriptors[0].supportedProtocols[1] == null + entityDescriptorHistory[0][1].principalUserName == 'anonymous' + entityDescriptorHistory[0][1].timestamp > 0L + + when: + representation = new EntityDescriptorRepresentation().with { + it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { + it.protocolSupportEnum = 'SAML 1.1, SAML 2' + it.nameIdFormats = ['formatUPDATED'] + it + } + it + } + + //Currently this is the ONLY way to let envers recognize update revision type for EntityDescriptor type + //when modifying SPSSODescriptor inside RoleDescriptors collection. This date "touch" would need to be encapsulated + //perhaps in JPAEntityDescriptorServiceImpl#buildDescriptorFromRepresentation + ed.modifiedDate = LocalDateTime.now() + + entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 2 + entityDescriptorHistory[1][0].roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' + entityDescriptorHistory[1][0].roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + entityDescriptorHistory[1][0].roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' + entityDescriptorHistory[1][1].principalUserName == 'anonymous' + entityDescriptorHistory[1][1].timestamp > 0L + + //Check the original revision is intact + entityDescriptorHistory[0][0].roleDescriptors[0].nameIDFormats[0].format == 'format' + entityDescriptorHistory[0][0].roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + entityDescriptorHistory[0][0].roleDescriptors[0].supportedProtocols[1] == null + entityDescriptorHistory[0][1].principalUserName == 'anonymous' + entityDescriptorHistory[0][1].timestamp > 0L + } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy index 93fc12c1f..d06e8ecbb 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.repository.envers import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService import org.hibernate.envers.AuditReaderFactory @@ -25,7 +26,7 @@ class EnversTestsSupport { entity } - static updateAndGetRevisionHistory(ed, representation, + static updateAndGetRevisionHistory(EntityDescriptor ed, EntityDescriptorRepresentation representation, EntityDescriptorService eds, EntityDescriptorRepository edr, PlatformTransactionManager txMgr, @@ -34,6 +35,10 @@ class EnversTestsSupport { doInExplicitTransaction(txMgr) { edr.save(ed) } + + //For temp debugging. Remove when done! + //def updated = edr.findByResourceId(ed.resourceId) + getRevisionHistory(em) } From 15b2e078bb96c634d4b91558a1256d1dd6303f2c Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 31 May 2019 10:01:14 -0400 Subject: [PATCH 16/51] SHIBUI-1262 [1307] --- .../ui/domain/AbstractLangBearingURL.java | 2 + .../admin/ui/domain/Description.java | 2 + .../admin/ui/domain/DisplayName.java | 2 + .../admin/ui/domain/InformationURL.java | 2 + .../tier/shibboleth/admin/ui/domain/Logo.java | 2 + .../admin/ui/domain/PrivacyStatementURL.java | 2 + .../shibboleth/admin/ui/domain/UIInfo.java | 2 + .../shibboleth/admin/ui/domain/XSURI.java | 2 + ...tityDescriptorEnversVersioningTests.groovy | 86 +++++++++++++++++++ 9 files changed, 102 insertions(+) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractLangBearingURL.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractLangBearingURL.java index 7f66a06c6..96fb81a69 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractLangBearingURL.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractLangBearingURL.java @@ -1,5 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; +import org.hibernate.envers.Audited; import org.opensaml.saml.saml2.metadata.LocalizedURI; import javax.annotation.Nullable; @@ -10,6 +11,7 @@ @Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +@Audited abstract class AbstractLangBearingURL extends XSURI implements LocalizedURI { @Column(name = "informationUrlXmlLang") private String xmlLang; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Description.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Description.java index 81b66542d..db994740a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Description.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Description.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Column; @@ -8,6 +9,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class Description extends AbstractXMLObject implements org.opensaml.saml.ext.saml2mdui.Description { @Column(name = "descriptionXMLLang") diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/DisplayName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/DisplayName.java index 564b0b0f6..5ee4815d9 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/DisplayName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/DisplayName.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Column; @@ -8,6 +9,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class DisplayName extends AbstractXMLObject implements org.opensaml.saml.ext.saml2mdui.DisplayName { @Column(name = "displayNameXMLLan") diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/InformationURL.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/InformationURL.java index 45d5477d1..e960e8463 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/InformationURL.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/InformationURL.java @@ -1,10 +1,12 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class InformationURL extends AbstractLangBearingURL implements org.opensaml.saml.ext.saml2mdui.InformationURL { } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java index b9173bb22..13453438a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Column; @@ -8,6 +9,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class Logo extends AbstractXMLObject implements org.opensaml.saml.ext.saml2mdui.Logo { @Column(name = "logUrl") private String url; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/PrivacyStatementURL.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/PrivacyStatementURL.java index a6d792d80..a98f5a7ad 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/PrivacyStatementURL.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/PrivacyStatementURL.java @@ -1,10 +1,12 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class PrivacyStatementURL extends AbstractLangBearingURL implements org.opensaml.saml.ext.saml2mdui.PrivacyStatementURL { } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/UIInfo.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/UIInfo.java index f7912aa65..241eebfac 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/UIInfo.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/UIInfo.java @@ -3,6 +3,7 @@ import lombok.EqualsAndHashCode; import org.hibernate.annotations.Cascade; import org.hibernate.annotations.CascadeType; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.ext.saml2mdui.Description; import org.opensaml.saml.ext.saml2mdui.DisplayName; @@ -22,6 +23,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class UIInfo extends AbstractXMLObject implements org.opensaml.saml.ext.saml2mdui.UIInfo { @OneToMany @Cascade(CascadeType.ALL) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java index 2780c5472..8663bf818 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Column; @@ -8,6 +9,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class XSURI extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSURI { @Column(name = "xsuriValue") private String value; diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index f0f02421d..8a35bb7d5 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -5,8 +5,10 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.Internationalization import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.UIInfo import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects @@ -16,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager import spock.lang.Specification @@ -26,6 +29,8 @@ import java.time.LocalDateTime import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistory import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER +import static org.springframework.test.annotation.DirtiesContext.MethodMode.AFTER_METHOD +import static org.springframework.test.annotation.DirtiesContext.MethodMode.BEFORE_METHOD /** * Testing entity descriptor envers versioning @@ -51,6 +56,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { @Autowired OpenSamlObjects openSamlObjects + @DirtiesContext def "test versioning with contact persons"() { when: def ed = new EntityDescriptor() @@ -117,6 +123,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { } + @DirtiesContext def "test versioning with organization"() { when: EntityDescriptor ed = new EntityDescriptor() @@ -161,6 +168,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorHistory[0][1].timestamp > 0L } + @DirtiesContext def "test versioning with sp sso descriptor"() { when: EntityDescriptor ed = new EntityDescriptor() @@ -220,4 +228,82 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorHistory[0][1].principalUserName == 'anonymous' entityDescriptorHistory[0][1].timestamp > 0L } + @DirtiesContext + def "test versioning with uiInfo"() { + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.mdui = new MduiRepresentation().with { + it.displayName = 'Initial display name' + it.informationUrl = 'http://info' + it.privacyStatementUrl = 'http://privacy' + it.description = 'Initial desc' + it.logoUrl = 'http://logo' + it.logoHeight = 20 + it.logoWidth = 30 + it + } + it + } + def entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + //Groovy FTW - able to call any private methods on ANY object. Get first revision + UIInfo uiinfo = entityDescriptorService.getUIInfo(entityDescriptorHistory[0][0]) + + then: + entityDescriptorHistory.size() == 1 + uiinfo.displayNames[0].value == 'Initial display name' + uiinfo.informationURLs[0].value == 'http://info' + uiinfo.privacyStatementURLs[0].value == 'http://privacy' + uiinfo.descriptions[0].value == 'Initial desc' + uiinfo.logos[0].URL == 'http://logo' + uiinfo.logos[0].height == 20 + uiinfo.logos[0].width == 30 + + when: + representation = new EntityDescriptorRepresentation().with { + it.mdui = new MduiRepresentation().with { + it.displayName = 'Display name UPDATED' + it.informationUrl = 'http://info.updated' + it.privacyStatementUrl = 'http://privacy.updated' + it.description = 'Desc UPDATED' + it.logoUrl = 'http://logo.updated' + it.logoHeight = 30 + it.logoWidth = 40 + it + } + it + } + entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + //Get second revision + uiinfo = entityDescriptorService.getUIInfo(entityDescriptorHistory[1][0]) + //And initial revision + def uiinfoInitialRevision = entityDescriptorService.getUIInfo(entityDescriptorHistory[0][0]) + + then: + entityDescriptorHistory.size() == 2 + uiinfo.displayNames[0].value == 'Display name UPDATED' + uiinfo.informationURLs[0].value == 'http://info.updated' + uiinfo.privacyStatementURLs[0].value == 'http://privacy.updated' + uiinfo.descriptions[0].value == 'Desc UPDATED' + uiinfo.logos[0].URL == 'http://logo.updated' + uiinfo.logos[0].height == 30 + uiinfo.logos[0].width == 40 + + //Check the initial revision is still intact + uiinfoInitialRevision.displayNames[0].value == 'Initial display name' + uiinfoInitialRevision.informationURLs[0].value == 'http://info' + uiinfoInitialRevision.privacyStatementURLs[0].value == 'http://privacy' + uiinfoInitialRevision.descriptions[0].value == 'Initial desc' + uiinfoInitialRevision.logos[0].URL == 'http://logo' + uiinfoInitialRevision.logos[0].height == 20 + uiinfoInitialRevision.logos[0].width == 30 + } } From aff8ccd0128f59f61f2bed708dfc8edcc176feab Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 31 May 2019 11:54:28 -0400 Subject: [PATCH 17/51] SHIBUI-1262 [1307 WIP] --- .../admin/ui/domain/X509Certificate.java | 2 + .../shibboleth/admin/ui/domain/X509Data.java | 2 + ...tityDescriptorEnversVersioningTests.groovy | 169 +++++++++++------- .../envers/EnversTestsSupport.groovy | 27 +-- 4 files changed, 124 insertions(+), 76 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Certificate.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Certificate.java index 2fe5ea571..b1db21b72 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Certificate.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Certificate.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Column; @@ -9,6 +10,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class X509Certificate extends AbstractXMLObject implements org.opensaml.xmlsec.signature.X509Certificate { @Column(name = "x509CertificateValue") @Lob diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Data.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Data.java index 46c58324a..e875932cd 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Data.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Data.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import org.opensaml.xmlsec.signature.X509CRL; import org.opensaml.xmlsec.signature.X509Certificate; @@ -23,6 +24,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class X509Data extends AbstractXMLObject implements org.opensaml.xmlsec.signature.X509Data { @OneToMany(cascade = CascadeType.ALL) @OrderColumn diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 8a35bb7d5..786f5e0a2 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -5,11 +5,15 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.Internationalization import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.KeyDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.SPSSODescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.UIInfo +import edu.internet2.tier.shibboleth.admin.ui.domain.X509Certificate import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.SecurityInfoRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository @@ -26,11 +30,11 @@ import spock.lang.Specification import javax.persistence.EntityManager import java.time.LocalDateTime -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistory +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER -import static org.springframework.test.annotation.DirtiesContext.MethodMode.AFTER_METHOD -import static org.springframework.test.annotation.DirtiesContext.MethodMode.BEFORE_METHOD /** * Testing entity descriptor envers versioning @@ -64,43 +68,43 @@ class EntityDescriptorEnversVersioningTests extends Specification { it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] it } - def entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 1 - entityDescriptorHistory[0][0].contactPersons[0].givenName.name == 'name' - entityDescriptorHistory[0][0].contactPersons[0].type == ADMINISTRATIVE - entityDescriptorHistory[0][0].contactPersons[0].emailAddresses[0].address == 'test@test' - entityDescriptorHistory[0][1].principalUserName == 'anonymous' - entityDescriptorHistory[0][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].givenName.name == 'name' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].type == ADMINISTRATIVE + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].emailAddresses[0].address == 'test@test' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L when: representation = new EntityDescriptorRepresentation().with { it.contacts = [new ContactRepresentation(type: 'administrative', name: 'nameUPDATED', emailAddress: 'test@test')] it } - entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 2 - entityDescriptorHistory[1][0].contactPersons[0].givenName.name == 'nameUPDATED' - entityDescriptorHistory[1][0].contactPersons[0].type == ADMINISTRATIVE - entityDescriptorHistory[1][0].contactPersons[0].emailAddresses[0].address == 'test@test' - entityDescriptorHistory[1][1].principalUserName == 'anonymous' - entityDescriptorHistory[1][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L when: representation = new EntityDescriptorRepresentation().with { it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED2', emailAddress: 'test@test.com')] it } - entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, @@ -108,18 +112,18 @@ class EntityDescriptorEnversVersioningTests extends Specification { then: entityDescriptorHistory.size() == 3 - entityDescriptorHistory[2][0].contactPersons[0].givenName.name == 'nameUPDATED2' - entityDescriptorHistory[2][0].contactPersons[0].type == OTHER - entityDescriptorHistory[2][0].contactPersons[0].emailAddresses[0].address == 'test@test.com' - entityDescriptorHistory[2][1].principalUserName == 'anonymous' - entityDescriptorHistory[2][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].givenName.name == 'nameUPDATED2' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].type == OTHER + getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].emailAddresses[0].address == 'test@test.com' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).timestamp > 0L //Also make sure we have our original revision - entityDescriptorHistory[0][0].contactPersons[0].givenName.name == 'name' - entityDescriptorHistory[0][0].contactPersons[0].type == ADMINISTRATIVE - entityDescriptorHistory[0][0].contactPersons[0].emailAddresses[0].address == 'test@test' - entityDescriptorHistory[0][1].principalUserName == 'anonymous' - entityDescriptorHistory[0][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L } @@ -131,41 +135,41 @@ class EntityDescriptorEnversVersioningTests extends Specification { it.organization = new OrganizationRepresentation(name: 'org', displayName: 'display org', url: 'http://org.edu') it } - def entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 1 - entityDescriptorHistory[0][0].organization.organizationNames[0].value == 'org' - entityDescriptorHistory[0][0].organization.displayNames[0].value == 'display org' - entityDescriptorHistory[0][0].organization.URLs[0].value == 'http://org.edu' - entityDescriptorHistory[0][1].principalUserName == 'anonymous' - entityDescriptorHistory[0][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L when: representation = new EntityDescriptorRepresentation().with { it.organization = new OrganizationRepresentation(name: 'orgUpdated', displayName: 'display org Updated', url: 'http://org2.edu') it } - entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 2 - entityDescriptorHistory[1][0].organization.organizationNames[0].value == 'orgUpdated' - entityDescriptorHistory[1][0].organization.displayNames[0].value == 'display org Updated' - entityDescriptorHistory[1][0].organization.URLs[0].value == 'http://org2.edu' - entityDescriptorHistory[1][1].principalUserName == 'anonymous' - entityDescriptorHistory[1][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.organizationNames[0].value == 'orgUpdated' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.displayNames[0].value == 'display org Updated' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.URLs[0].value == 'http://org2.edu' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L //Check the original revision is intact - entityDescriptorHistory[0][0].organization.organizationNames[0].value == 'org' - entityDescriptorHistory[0][0].organization.displayNames[0].value == 'display org' - entityDescriptorHistory[0][0].organization.URLs[0].value == 'http://org.edu' - entityDescriptorHistory[0][1].principalUserName == 'anonymous' - entityDescriptorHistory[0][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L } @DirtiesContext @@ -180,18 +184,18 @@ class EntityDescriptorEnversVersioningTests extends Specification { } it } - def entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 1 - entityDescriptorHistory[0][0].roleDescriptors[0].nameIDFormats[0].format == 'format' - entityDescriptorHistory[0][0].roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - entityDescriptorHistory[0][0].roleDescriptors[0].supportedProtocols[1] == null - entityDescriptorHistory[0][1].principalUserName == 'anonymous' - entityDescriptorHistory[0][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L when: representation = new EntityDescriptorRepresentation().with { @@ -208,26 +212,27 @@ class EntityDescriptorEnversVersioningTests extends Specification { //perhaps in JPAEntityDescriptorServiceImpl#buildDescriptorFromRepresentation ed.modifiedDate = LocalDateTime.now() - entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 2 - entityDescriptorHistory[1][0].roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' - entityDescriptorHistory[1][0].roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - entityDescriptorHistory[1][0].roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' - entityDescriptorHistory[1][1].principalUserName == 'anonymous' - entityDescriptorHistory[1][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).nameIDFormats[0].format == 'formatUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L //Check the original revision is intact - entityDescriptorHistory[0][0].roleDescriptors[0].nameIDFormats[0].format == 'format' - entityDescriptorHistory[0][0].roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - entityDescriptorHistory[0][0].roleDescriptors[0].supportedProtocols[1] == null - entityDescriptorHistory[0][1].principalUserName == 'anonymous' - entityDescriptorHistory[0][1].timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L } + @DirtiesContext def "test versioning with uiInfo"() { when: @@ -245,13 +250,13 @@ class EntityDescriptorEnversVersioningTests extends Specification { } it } - def entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) //Groovy FTW - able to call any private methods on ANY object. Get first revision - UIInfo uiinfo = entityDescriptorService.getUIInfo(entityDescriptorHistory[0][0]) + UIInfo uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) then: entityDescriptorHistory.size() == 1 @@ -277,15 +282,15 @@ class EntityDescriptorEnversVersioningTests extends Specification { } it } - entityDescriptorHistory = updateAndGetRevisionHistory(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) //Get second revision - uiinfo = entityDescriptorService.getUIInfo(entityDescriptorHistory[1][0]) + uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) //And initial revision - def uiinfoInitialRevision = entityDescriptorService.getUIInfo(entityDescriptorHistory[0][0]) + def uiinfoInitialRevision = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) then: entityDescriptorHistory.size() == 2 @@ -306,4 +311,38 @@ class EntityDescriptorEnversVersioningTests extends Specification { uiinfoInitialRevision.logos[0].height == 20 uiinfoInitialRevision.logos[0].width == 30 } + + @DirtiesContext + def "test versioning with security"() { + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.securityInfo = new SecurityInfoRepresentation().with { + it.authenticationRequestsSigned = true + it.x509CertificateAvailable = true + it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue')] + it + } + it + } + + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + //Get initial revision + SPSSODescriptor spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + + KeyDescriptor keyDescriptor = spssoDescriptor.keyDescriptors[0] + X509Certificate x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] + + then: + entityDescriptorHistory.size() == 1 + spssoDescriptor.isAuthnRequestsSigned() + keyDescriptor.name == 'sign' + keyDescriptor.usageType == 'signing' + x509cert.value == 'signingValue' + } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy index d06e8ecbb..6e9b5981f 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy @@ -26,27 +26,32 @@ class EnversTestsSupport { entity } - static updateAndGetRevisionHistory(EntityDescriptor ed, EntityDescriptorRepresentation representation, - EntityDescriptorService eds, - EntityDescriptorRepository edr, - PlatformTransactionManager txMgr, - EntityManager em) { + static updateAndGetRevisionHistoryOfEntityDescriptor(EntityDescriptor ed, EntityDescriptorRepresentation representation, + EntityDescriptorService eds, + EntityDescriptorRepository edr, + PlatformTransactionManager txMgr, + EntityManager em) { eds.updateDescriptorFromRepresentation(ed, representation) doInExplicitTransaction(txMgr) { edr.save(ed) } - //For temp debugging. Remove when done! - //def updated = edr.findByResourceId(ed.resourceId) - - getRevisionHistory(em) + getRevisionHistoryForEntityType(em, EntityDescriptor) } - static getRevisionHistory(EntityManager em) { + static getRevisionHistoryForEntityType(EntityManager em, Class entityType) { def auditReader = AuditReaderFactory.get(em) AuditQuery auditQuery = auditReader .createQuery() - .forRevisionsOfEntity(EntityDescriptor, false, false) + .forRevisionsOfEntity(entityType, false, false) auditQuery.resultList } + + static getTargetEntityForRevisionIndex(List revHistory, int revIndex) { + revHistory[revIndex][0] + } + + static getRevisionEntityForRevisionIndex(List revHistory, int revIndex) { + revHistory[revIndex][1] + } } From 33cee9fb25e0655e5c09661f152119295aadbdac Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 31 May 2019 13:51:55 -0400 Subject: [PATCH 18/51] SHIBUI-1262 [1307 WIP] --- ...tityDescriptorEnversVersioningTests.groovy | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 786f5e0a2..1f8aeadf9 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -344,5 +344,56 @@ class EntityDescriptorEnversVersioningTests extends Specification { keyDescriptor.name == 'sign' keyDescriptor.usageType == 'signing' x509cert.value == 'signingValue' + + when: + representation = new EntityDescriptorRepresentation().with { + it.securityInfo = new SecurityInfoRepresentation().with { + it.authenticationRequestsSigned = false + it.x509CertificateAvailable = true + it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue'), + new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'encrypt', type: 'encryption', value: 'encryptionValue')] + it + } + it + } + + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + + //Get second revision + SPSSODescriptor spssoDescriptor_second = entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) + + KeyDescriptor keyDescriptor_second1 = spssoDescriptor_second.keyDescriptors[0] + X509Certificate x509cert_second1 = keyDescriptor_second1.keyInfo.x509Datas[0].x509Certificates[0] + KeyDescriptor keyDescriptor_second2 = spssoDescriptor_second.keyDescriptors[1] + X509Certificate x509cert_second2 = keyDescriptor_second2.keyInfo.x509Datas[0].x509Certificates[0] + + + //Get initial revision + spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + + keyDescriptor = spssoDescriptor.keyDescriptors[0] + x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] + + then: + entityDescriptorHistory.size() == 2 + !spssoDescriptor_second.isAuthnRequestsSigned() + keyDescriptor_second1.name == 'sign' + keyDescriptor_second1.usageType == 'signing' + keyDescriptor_second2.name == 'encrypt' + keyDescriptor_second2.usageType == 'encryption' + x509cert_second1.value == 'signingValue' + x509cert_second2.value == 'encryptionValue' + + //Check the initial version is intact + spssoDescriptor.keyDescriptors.size() == 1 + spssoDescriptor.isAuthnRequestsSigned() + keyDescriptor.name == 'sign' + keyDescriptor.usageType == 'signing' + x509cert.value == 'signingValue' } } From dc0935a2cf2b765c5b4d2deba89ebb0ea1923e01 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 3 Jun 2019 10:40:45 -0400 Subject: [PATCH 19/51] fix test --- .../envers/EntityDescriptorEnversVersioningTests.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 1f8aeadf9..0af499a2b 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -219,7 +219,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { then: entityDescriptorHistory.size() == 2 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).nameIDFormats[0].format == 'formatUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' From 40545a6f2aab6849dfbd97932bcc3550700687df Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 3 Jun 2019 11:23:04 -0400 Subject: [PATCH 20/51] SHIBUI-1262 [1307,1308 WIP] --- ...tityDescriptorEnversVersioningTests.groovy | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 0af499a2b..cb2f903f8 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -4,11 +4,13 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfigurat import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.AssertionConsumerService import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.KeyDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.SPSSODescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.UIInfo import edu.internet2.tier.shibboleth.admin.ui.domain.X509Certificate +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation @@ -396,4 +398,67 @@ class EntityDescriptorEnversVersioningTests extends Specification { keyDescriptor.usageType == 'signing' x509cert.value == 'signingValue' } + + @DirtiesContext + def "test versioning ACS"() { + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.assertionConsumerServices = [ + new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] + it + } + + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + AssertionConsumerService acs = spssoDescriptor.assertionConsumerServices[0] + + then: + entityDescriptorHistory.size() == 1 + !acs.isDefault() + acs.location == 'http://acs' + acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + + when: + representation = new EntityDescriptorRepresentation().with { + it.assertionConsumerServices = [ + new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs.updated', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS', makeDefault: true), + new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs2', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] + it + } + + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor2 = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) + def (acs1, acs2) = [spssoDescriptor2.assertionConsumerServices[0], spssoDescriptor2.assertionConsumerServices[1]] + + //Initial revision + spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + acs = spssoDescriptor.assertionConsumerServices[0] + + then: + entityDescriptorHistory.size() == 2 + acs1.isDefault() + !acs2.isDefault() + acs1.location == 'http://acs.updated' + acs1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' + acs2.location == 'http://acs2' + acs2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' + + //Check the initial revision is intact + !acs.isDefault() + acs.location == 'http://acs' + acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + + } } From 7c4aceda6a8543154429738a29c7450390a66e51 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 3 Jun 2019 12:08:24 -0400 Subject: [PATCH 21/51] SHIBUI-1262 [1307,1308 WIP] --- ...tityDescriptorEnversVersioningTests.groovy | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index cb2f903f8..390672fee 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -8,11 +8,13 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.AssertionConsumerService import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.KeyDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.SPSSODescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.SingleLogoutService import edu.internet2.tier.shibboleth.admin.ui.domain.UIInfo import edu.internet2.tier.shibboleth.admin.ui.domain.X509Certificate import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.LogoutEndpointRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.SecurityInfoRepresentation @@ -459,6 +461,61 @@ class EntityDescriptorEnversVersioningTests extends Specification { !acs.isDefault() acs.location == 'http://acs' acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + } + + @DirtiesContext + def "test versioning logout"() { + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] + it + } + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + SingleLogoutService slo = spssoDescriptor.singleLogoutServices[0] + + then: + entityDescriptorHistory.size() == 1 + slo.location == 'http://logout' + slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + + when: + representation = new EntityDescriptorRepresentation().with { + it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout.updated', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS'), + new LogoutEndpointRepresentation(url: 'http://logout2', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] + it + } + + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor2 = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + def (slo1, slo2) = [spssoDescriptor2.singleLogoutServices[0], spssoDescriptor2.singleLogoutServices[1]] + + //Initial revision + spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + slo = spssoDescriptor.singleLogoutServices[0] + + then: + entityDescriptorHistory.size() == 2 + slo1.location == 'http://logout.updated' + slo1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' + slo2.location == 'http://logout2' + slo2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' + + //Check the initial version is intact + slo.location == 'http://logout' + slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' } } From 3610ed1f124996f452ebde32f6841a644a5f2d17 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 3 Jun 2019 15:45:58 -0400 Subject: [PATCH 22/51] SHIBUI-1262 [1307,1308 WIP] --- .../AbstractAttributeExtensibleXMLObject.java | 4 +- .../admin/ui/domain/AbstractAuditable.java | 2 + .../shibboleth/admin/ui/domain/Attribute.java | 1 + .../admin/ui/domain/EntityAttributes.java | 2 + .../shibboleth/admin/ui/domain/XSAny.java | 2 + .../admin/ui/domain/XSBase64Binary.java | 2 + .../shibboleth/admin/ui/domain/XSBoolean.java | 2 + .../admin/ui/domain/XSDateTime.java | 2 + .../shibboleth/admin/ui/domain/XSInteger.java | 2 + .../shibboleth/admin/ui/domain/XSQName.java | 2 + .../shibboleth/admin/ui/domain/XSString.java | 2 + ...tityDescriptorEnversVersioningTests.groovy | 56 +++++++++++++++++++ 12 files changed, 78 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAttributeExtensibleXMLObject.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAttributeExtensibleXMLObject.java index 075280330..2b4208865 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAttributeExtensibleXMLObject.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAttributeExtensibleXMLObject.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.AttributeExtensibleXMLObject; import org.opensaml.core.xml.util.AttributeMap; @@ -10,6 +11,7 @@ @MappedSuperclass @EqualsAndHashCode(callSuper = true, exclude={"unknownAttributes"}) +@Audited public abstract class AbstractAttributeExtensibleXMLObject extends AbstractXMLObject implements AttributeExtensibleXMLObject { private transient final AttributeMap unknownAttributes; @@ -24,4 +26,4 @@ public abstract class AbstractAttributeExtensibleXMLObject extends AbstractXMLOb public AttributeMap getUnknownAttributes() { return this.unknownAttributes; } -} \ No newline at end of file +} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java index 1d23d5113..567a6637e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java @@ -3,6 +3,7 @@ import lombok.EqualsAndHashCode; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; +import org.hibernate.envers.Audited; import org.springframework.data.annotation.CreatedBy; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedBy; @@ -22,6 +23,7 @@ @MappedSuperclass @EntityListeners(AuditingEntityListener.class) @EqualsAndHashCode +@Audited public abstract class AbstractAuditable implements Auditable { @Id diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Attribute.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Attribute.java index 7a187bd99..1a9a28323 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Attribute.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Attribute.java @@ -27,6 +27,7 @@ public class Attribute extends AbstractAttributeExtensibleXMLObject implements o @OneToMany(cascade = CascadeType.ALL) @OrderColumn + @Audited private List attributeValues = new ArrayList<>(); @Override diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java index ed97305fc..d48a3ea6f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.saml2.core.Assertion; @@ -16,6 +17,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class EntityAttributes extends AbstractElementExtensibleXMLObject implements org.opensaml.saml.ext.saml2mdattr.EntityAttributes { @OneToMany(cascade = CascadeType.ALL) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSAny.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSAny.java index 1c1d32f4b..de81fcdf6 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSAny.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSAny.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.util.AttributeMap; import javax.annotation.Nonnull; @@ -10,6 +11,7 @@ @Entity @EqualsAndHashCode(callSuper = true, exclude = {"unknownAttributes"}) +@Audited public class XSAny extends AbstractElementExtensibleXMLObject implements org.opensaml.core.xml.schema.XSAny { private String textContext; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSBase64Binary.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSBase64Binary.java index 0d886d52a..edfd8eec8 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSBase64Binary.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSBase64Binary.java @@ -1,12 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class XSBase64Binary extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSBase64Binary { private String b64value; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSBoolean.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSBoolean.java index 72399bf06..8b0f258d1 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSBoolean.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSBoolean.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.opensaml.core.xml.schema.XSBooleanValue; import javax.annotation.Nullable; @@ -9,6 +10,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class XSBoolean extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSBoolean { private String storedValue; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java index 0ea3116f8..1b13a3cd4 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import org.joda.time.DateTime; import org.joda.time.chrono.ISOChronology; import org.joda.time.format.DateTimeFormatter; @@ -13,6 +14,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class XSDateTime extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSDateTime { private DateTime dateTime; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSInteger.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSInteger.java index 294d0a575..cd6c205da 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSInteger.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSInteger.java @@ -1,12 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class XSInteger extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSInteger { private int intValue; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSQName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSQName.java index 259e3df36..b210ea7a4 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSQName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSQName.java @@ -2,6 +2,7 @@ import lombok.EqualsAndHashCode; import net.shibboleth.utilities.java.support.xml.QNameSupport; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Entity; @@ -10,6 +11,7 @@ @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class XSQName extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSQName { @Nullable @Override diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSString.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSString.java index f35e8e287..dbc0d4c38 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSString.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSString.java @@ -1,12 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.envers.Audited; import javax.annotation.Nullable; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) +@Audited public class XSString extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSString { private String xsStringvalue; diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 390672fee..fa1b3af34 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -5,6 +5,7 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.Internationalization import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.AssertionConsumerService +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributes import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.KeyDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.SPSSODescriptor @@ -518,4 +519,59 @@ class EntityDescriptorEnversVersioningTests extends Specification { slo.location == 'http://logout' slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' } + + @DirtiesContext + def "test versioning relying party overrides"() { + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.relyingPartyOverrides = [signAssertion: true] + it.attributeRelease = ['attr1'] + it + } + + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + EntityAttributes attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + then: + entityDescriptorHistory.size() == 1 + attrs.attributes[0].attributeValues[0].storedValue == 'true' + attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' + + when: + representation = new EntityDescriptorRepresentation().with { + it.relyingPartyOverrides = [signAssertion: false] + it.attributeRelease = ['attr1', 'attr2'] + it + } + + //Currently this is the ONLY way to let envers recognize update revision type for EntityDescriptor type + //when modifying attributes. This date "touch" would need to be encapsulated + //perhaps in JPAEntityDescriptorServiceImpl#buildDescriptorFromRepresentation + ed.modifiedDate = LocalDateTime.now() + + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + EntityAttributes attrs2 = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + + //Initial revision + attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + then: + entityDescriptorHistory.size() == 2 + attrs2.attributes[0].attributeValues[0].xsStringvalue == 'attr1' + attrs2.attributes[0].attributeValues[1].xsStringvalue == 'attr2' + + //Check the initial revision is intact + attrs.attributes[0].attributeValues[0].storedValue == 'true' + attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' + attrs.attributes[1].attributeValues[1] == null + } } From f5eae5e63854cf9cc8497e8a33d564667582d4ef Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 5 Jun 2019 10:06:23 -0400 Subject: [PATCH 23/51] SHIBUI-1262(1308) --- .../envers/PrincipalAwareRevisionEntity.java | 3 +- .../JPAEntityDescriptorServiceImpl.java | 5 + ...tityDescriptorEnversVersioningTests.groovy | 107 +++++++++++++----- .../envers/EnversTestsSupport.groovy | 4 + 4 files changed, 87 insertions(+), 32 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalAwareRevisionEntity.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalAwareRevisionEntity.java index 8ee27218f..88e20179d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalAwareRevisionEntity.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalAwareRevisionEntity.java @@ -3,6 +3,7 @@ import lombok.Getter; import lombok.Setter; import org.hibernate.envers.DefaultRevisionEntity; +import org.hibernate.envers.DefaultTrackingModifiedEntitiesRevisionEntity; import org.hibernate.envers.RevisionEntity; import javax.persistence.Entity; @@ -14,7 +15,7 @@ @RevisionEntity(PrincipalEnhancingRevisionListener.class) @Getter @Setter -public class PrincipalAwareRevisionEntity extends DefaultRevisionEntity { +public class PrincipalAwareRevisionEntity extends DefaultTrackingModifiedEntitiesRevisionEntity { private String principalUserName; } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java index 9bbf5ec2a..e97c166a3 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java @@ -56,6 +56,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -120,6 +121,10 @@ private EntityDescriptor buildDescriptorFromRepresentation(final EntityDescripto setupLogout(ed, representation); setupRelyingPartyOverrides(ed, representation); + //Let envers recognize update revision type for EntityDescriptor type + //when modifying Attributes and SPSSODescriptor inside RoleDescriptors collection + ed.setModifiedDate(LocalDateTime.now()); + return ed; } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index fa1b3af34..acea73775 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -4,22 +4,8 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfigurat import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration -import edu.internet2.tier.shibboleth.admin.ui.domain.AssertionConsumerService -import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributes -import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.KeyDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.SPSSODescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.SingleLogoutService -import edu.internet2.tier.shibboleth.admin.ui.domain.UIInfo -import edu.internet2.tier.shibboleth.admin.ui.domain.X509Certificate -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.LogoutEndpointRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.SecurityInfoRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.* +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.* import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService @@ -33,11 +19,8 @@ import org.springframework.transaction.PlatformTransactionManager import spock.lang.Specification import javax.persistence.EntityManager -import java.time.LocalDateTime -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.* import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER @@ -67,6 +50,9 @@ class EntityDescriptorEnversVersioningTests extends Specification { @DirtiesContext def "test versioning with contact persons"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, ContactPerson.name, GivenName.name, EmailAddress.name] + when: def ed = new EntityDescriptor() def representation = new EntityDescriptorRepresentation().with { @@ -85,6 +71,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].emailAddresses[0].address == 'test@test' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -95,7 +82,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorRepository, txMgr, entityManager) - then: entityDescriptorHistory.size() == 2 getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' @@ -103,6 +89,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -122,6 +109,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].emailAddresses[0].address == 'test@test.com' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymous' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 2).sort() == expectedModifiedPersistentEntities.sort() //Also make sure we have our original revision getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' @@ -134,6 +122,13 @@ class EntityDescriptorEnversVersioningTests extends Specification { @DirtiesContext def "test versioning with organization"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + Organization.name, + OrganizationDisplayName.name, + OrganizationName.name, + OrganizationURL.name] + when: EntityDescriptor ed = new EntityDescriptor() def representation = new EntityDescriptorRepresentation().with { @@ -151,6 +146,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -168,6 +164,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.URLs[0].value == 'http://org2.edu' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the original revision is intact getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' @@ -179,6 +176,10 @@ class EntityDescriptorEnversVersioningTests extends Specification { @DirtiesContext def "test versioning with sp sso descriptor"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + NameIDFormat.name, + SPSSODescriptor.name] when: EntityDescriptor ed = new EntityDescriptor() def representation = new EntityDescriptorRepresentation().with { @@ -201,6 +202,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -212,11 +214,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - //Currently this is the ONLY way to let envers recognize update revision type for EntityDescriptor type - //when modifying SPSSODescriptor inside RoleDescriptors collection. This date "touch" would need to be encapsulated - //perhaps in JPAEntityDescriptorServiceImpl#buildDescriptorFromRepresentation - ed.modifiedDate = LocalDateTime.now() - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, @@ -229,6 +226,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the original revision is intact getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' @@ -240,6 +238,17 @@ class EntityDescriptorEnversVersioningTests extends Specification { @DirtiesContext def "test versioning with uiInfo"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + Description.name, + DisplayName.name, + SPSSODescriptor.name, + Extensions.name, + InformationURL.name, + Logo.name, + PrivacyStatementURL.name, + UIInfo.name] + when: EntityDescriptor ed = new EntityDescriptor() def representation = new EntityDescriptorRepresentation().with { @@ -272,6 +281,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { uiinfo.logos[0].URL == 'http://logo' uiinfo.logos[0].height == 20 uiinfo.logos[0].width == 30 + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -306,6 +316,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { uiinfo.logos[0].URL == 'http://logo.updated' uiinfo.logos[0].height == 30 uiinfo.logos[0].width == 40 + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial revision is still intact uiinfoInitialRevision.displayNames[0].value == 'Initial display name' @@ -319,6 +330,14 @@ class EntityDescriptorEnversVersioningTests extends Specification { @DirtiesContext def "test versioning with security"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + KeyDescriptor.name, + KeyInfo.name, + SPSSODescriptor.name, + X509Certificate.name, + X509Data.name] + when: EntityDescriptor ed = new EntityDescriptor() def representation = new EntityDescriptorRepresentation().with { @@ -349,6 +368,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { keyDescriptor.name == 'sign' keyDescriptor.usageType == 'signing' x509cert.value == 'signingValue' + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -393,6 +413,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { keyDescriptor_second2.usageType == 'encryption' x509cert_second1.value == 'signingValue' x509cert_second2.value == 'encryptionValue' + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial version is intact spssoDescriptor.keyDescriptors.size() == 1 @@ -404,6 +425,11 @@ class EntityDescriptorEnversVersioningTests extends Specification { @DirtiesContext def "test versioning ACS"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + SPSSODescriptor.name, + AssertionConsumerService.name] + when: EntityDescriptor ed = new EntityDescriptor() def representation = new EntityDescriptorRepresentation().with { @@ -426,6 +452,8 @@ class EntityDescriptorEnversVersioningTests extends Specification { !acs.isDefault() acs.location == 'http://acs' acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + when: representation = new EntityDescriptorRepresentation().with { @@ -457,6 +485,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { acs1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' acs2.location == 'http://acs2' acs2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial revision is intact !acs.isDefault() @@ -466,6 +495,11 @@ class EntityDescriptorEnversVersioningTests extends Specification { @DirtiesContext def "test versioning logout"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + SPSSODescriptor.name, + SingleLogoutService.name] + when: EntityDescriptor ed = new EntityDescriptor() def representation = new EntityDescriptorRepresentation().with { @@ -486,6 +520,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorHistory.size() == 1 slo.location == 'http://logout' slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -514,6 +549,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { slo1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' slo2.location == 'http://logout2' slo2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial version is intact slo.location == 'http://logout' @@ -522,6 +558,14 @@ class EntityDescriptorEnversVersioningTests extends Specification { @DirtiesContext def "test versioning relying party overrides"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + EntityAttributes.name, + Extensions.name, + Attribute.name, + XSBoolean.name, + XSString.name] + when: EntityDescriptor ed = new EntityDescriptor() def representation = new EntityDescriptorRepresentation().with { @@ -541,6 +585,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorHistory.size() == 1 attrs.attributes[0].attributeValues[0].storedValue == 'true' attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -549,11 +594,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - //Currently this is the ONLY way to let envers recognize update revision type for EntityDescriptor type - //when modifying attributes. This date "touch" would need to be encapsulated - //perhaps in JPAEntityDescriptorServiceImpl#buildDescriptorFromRepresentation - ed.modifiedDate = LocalDateTime.now() - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, @@ -564,10 +604,15 @@ class EntityDescriptorEnversVersioningTests extends Specification { //Initial revision attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + expectedModifiedPersistentEntities = [EntityDescriptor.name, + EntityAttributes.name, + Attribute.name, + XSString.name] then: entityDescriptorHistory.size() == 2 attrs2.attributes[0].attributeValues[0].xsStringvalue == 'attr1' attrs2.attributes[0].attributeValues[1].xsStringvalue == 'attr2' + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial revision is intact attrs.attributes[0].attributeValues[0].storedValue == 'true' diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy index 6e9b5981f..3d2632f6b 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy @@ -54,4 +54,8 @@ class EnversTestsSupport { static getRevisionEntityForRevisionIndex(List revHistory, int revIndex) { revHistory[revIndex][1] } + + static getModifiedEntityNames(List revHistory, int revIndex) { + getRevisionEntityForRevisionIndex(revHistory, revIndex).modifiedEntityNames + } } From 69a404a31f488e15ccb57db94b1c805719b1277f Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 5 Jun 2019 12:07:06 -0400 Subject: [PATCH 24/51] WIP1 --- .../admin/ui/configuration/DevConfig.groovy | 4 +-- .../EntitiesVersioningConfiguration.java | 12 ++++--- .../EnversEntityDescriptorVersionService.java | 32 +++++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy index 6f853e089..b49d5b858 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy @@ -162,10 +162,10 @@ class DevConfig { }) } - @Profile('dev-ed-versioning') + /*@Profile('dev-ed-versioning') @Bean EntityDescriptorVersionService stubEntityDescriptorVersionService(EntityDescriptorService entityDescriptorService, EntityDescriptorRepository entityDescriptorRepository) { return EntityDescriptorVersionService.stubImpl(entityDescriptorService, entityDescriptorRepository) - } + }*/ } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java index 5f1b64b46..75dfb5ded 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java @@ -1,15 +1,17 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration; -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService; +import edu.internet2.tier.shibboleth.admin.ui.service.EnversEntityDescriptorVersionService; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import javax.persistence.EntityManager; + @Configuration public class EntitiesVersioningConfiguration { - //@Bean - EntityDescriptorVersionService entityDescriptorVersionService(EntityDescriptorService entityDescriptorService) { - //TODO create real impl when available - return null; + @Bean + EntityDescriptorVersionService entityDescriptorVersionService(EntityManager entityManager) { + return new EnversEntityDescriptorVersionService(entityManager); } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java new file mode 100644 index 000000000..c5cbabc27 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java @@ -0,0 +1,32 @@ +package edu.internet2.tier.shibboleth.admin.ui.service; + +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; +import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version; +import org.hibernate.envers.AuditReader; +import org.hibernate.envers.AuditReaderFactory; + +import javax.persistence.EntityManager; +import java.util.List; + +/** + * Hibernate Envers based implementation of {@link EntityDescriptorVersionService}. + */ +public class EnversEntityDescriptorVersionService implements EntityDescriptorVersionService { + + private AuditReader auditReader; + + public EnversEntityDescriptorVersionService(EntityManager em) { + + this.auditReader = AuditReaderFactory.get(em); + } + + @Override + public List findVersionsForEntityDescriptor(String resourceId) { + return null; + } + + @Override + public EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) { + return null; + } +} From 50896d7f5f373efe2496e4400115c4782e2fcc3c Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 5 Jun 2019 16:07:44 -0400 Subject: [PATCH 25/51] SHIBUI-1262(1306) WIP --- .../EntitiesVersioningConfiguration.java | 6 +- .../envers/PrincipalAwareRevisionEntity.java | 4 ++ .../EnversEntityDescriptorVersionService.java | 33 +++++++++- ...EntityDescriptorVersionServiceTests.groovy | 63 +++++++++++++++++++ 4 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java index 75dfb5ded..b73448e5e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java @@ -6,12 +6,16 @@ import org.springframework.context.annotation.Configuration; import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; @Configuration public class EntitiesVersioningConfiguration { + @PersistenceContext + private EntityManager entityManager; + @Bean - EntityDescriptorVersionService entityDescriptorVersionService(EntityManager entityManager) { + EntityDescriptorVersionService entityDescriptorVersionService() { return new EnversEntityDescriptorVersionService(entityManager); } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalAwareRevisionEntity.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalAwareRevisionEntity.java index 88e20179d..6a2847b38 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalAwareRevisionEntity.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalAwareRevisionEntity.java @@ -18,4 +18,8 @@ public class PrincipalAwareRevisionEntity extends DefaultTrackingModifiedEntitiesRevisionEntity { private String principalUserName; + + public String idAsString() { + return String.valueOf(getId()); + } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java index c5cbabc27..123940f35 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java @@ -1,12 +1,22 @@ package edu.internet2.tier.shibboleth.admin.ui.service; +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version; +import edu.internet2.tier.shibboleth.admin.ui.envers.PrincipalAwareRevisionEntity; import org.hibernate.envers.AuditReader; import org.hibernate.envers.AuditReaderFactory; +import org.hibernate.envers.RevisionEntity; +import org.hibernate.envers.query.AuditEntity; +import org.springframework.data.jpa.repository.JpaContext; import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; /** * Hibernate Envers based implementation of {@link EntityDescriptorVersionService}. @@ -15,14 +25,31 @@ public class EnversEntityDescriptorVersionService implements EntityDescriptorVer private AuditReader auditReader; - public EnversEntityDescriptorVersionService(EntityManager em) { + private EntityManager entityManager; - this.auditReader = AuditReaderFactory.get(em); + public EnversEntityDescriptorVersionService(EntityManager entityManager) { + this.entityManager = entityManager; } @Override public List findVersionsForEntityDescriptor(String resourceId) { - return null; + List revs = AuditReaderFactory.get(entityManager).createQuery() + .forRevisionsOfEntity(EntityDescriptor.class, false, false) + .add(AuditEntity.property("resourceId").eq(resourceId)) + .getResultList(); + + //TODO: sort + Object revEntities = revs.stream() + .map(it -> (PrincipalAwareRevisionEntity)((Object[])it)[1]) + .map(it -> { + return new Version(((PrincipalAwareRevisionEntity) it).idAsString(), + ((PrincipalAwareRevisionEntity) it).getPrincipalUserName(), + ((PrincipalAwareRevisionEntity) it).getRevisionDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()); + }) + .collect(Collectors.toList()); + + + return (List)revEntities; } @Override diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy new file mode 100644 index 000000000..426c5eb6e --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy @@ -0,0 +1,63 @@ +package edu.internet2.tier.shibboleth.admin.ui.service + +import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.EntitiesVersioningConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.domain.EntityScan +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.context.ContextConfiguration +import org.springframework.transaction.PlatformTransactionManager +import spock.lang.Specification + +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.* +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction + +@DataJpaTest +@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration, EntitiesVersioningConfiguration]) +@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) +@EntityScan("edu.internet2.tier.shibboleth.admin.ui") +class EnversEntityDescriptorVersionServiceTests extends Specification { + + @Autowired + EntityDescriptorVersionService entityDescriptorVersionService + + @Autowired + EntityDescriptorRepository entityDescriptorRepository + + @Autowired + EntityDescriptorService entityDescriptorService + + @Autowired + PlatformTransactionManager txMgr + + def "temp test"() { + def representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] + it + } + EntityDescriptor ed = entityDescriptorService.createDescriptorFromRepresentation(representation) + ed = doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + + ed.entityID = "Entity ID" + ed = doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + + def versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + + expect: + true + } +} From 21ea1fd2898061308e3a1388f9dd402a96a5d242 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 6 Jun 2019 08:56:49 -0400 Subject: [PATCH 26/51] Fix tests --- .../TestEntityDescriptorVersioningConfiguration.groovy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy index f3d1346e0..06d16ca31 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy @@ -17,7 +17,7 @@ class TestEntityDescriptorVersioningConfiguration { @Autowired EntityDescriptorService entityDescriptorService - @Bean + /*@Bean EntityDescriptorVersionService stubEntityDescriptorVersionService() { return new EntityDescriptorVersionService() { @Override @@ -31,6 +31,6 @@ class TestEntityDescriptorVersioningConfiguration { return entityDescriptorService.createRepresentationFromDescriptor(new TestObjectGenerator().buildEntityDescriptor()) } } - } + }*/ } From be2090de352e5ff7e4ae479913bc845a6176d5d7 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 6 Jun 2019 10:10:55 -0400 Subject: [PATCH 27/51] SHIBUI-1262(1306) --- .../EnversEntityDescriptorVersionService.java | 22 +++++--- ...tyDescriptorVersioningConfiguration.groovy | 36 ------------ ...EntityDescriptorVersionServiceTests.groovy | 55 ++++++++++++------- 3 files changed, 48 insertions(+), 65 deletions(-) delete mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java index 123940f35..fced0645f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java @@ -15,16 +15,18 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; +import static java.util.Comparator.comparing; +import static java.util.stream.Collectors.*; + /** * Hibernate Envers based implementation of {@link EntityDescriptorVersionService}. */ public class EnversEntityDescriptorVersionService implements EntityDescriptorVersionService { - private AuditReader auditReader; - private EntityManager entityManager; public EnversEntityDescriptorVersionService(EntityManager entityManager) { @@ -38,18 +40,20 @@ public List findVersionsForEntityDescriptor(String resourceId) { .add(AuditEntity.property("resourceId").eq(resourceId)) .getResultList(); - //TODO: sort - Object revEntities = revs.stream() - .map(it -> (PrincipalAwareRevisionEntity)((Object[])it)[1]) + Object listOfVersions = revs.stream() + .map(it -> ((Object[])it)[1]) .map(it -> { return new Version(((PrincipalAwareRevisionEntity) it).idAsString(), ((PrincipalAwareRevisionEntity) it).getPrincipalUserName(), - ((PrincipalAwareRevisionEntity) it).getRevisionDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()); + ((PrincipalAwareRevisionEntity) it).getRevisionDate() + .toInstant() + .atZone(ZoneId.systemDefault()) + .toLocalDateTime()); }) - .collect(Collectors.toList()); - + .sorted(comparing(Version::getDate)) + .collect(toList()); - return (List)revEntities; + return (List)listOfVersions; } @Override diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy deleted file mode 100644 index 06d16ca31..000000000 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestEntityDescriptorVersioningConfiguration.groovy +++ /dev/null @@ -1,36 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.configuration - -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService -import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration - -import java.time.LocalDateTime - -@Configuration -class TestEntityDescriptorVersioningConfiguration { - - @Autowired - EntityDescriptorService entityDescriptorService - - /*@Bean - EntityDescriptorVersionService stubEntityDescriptorVersionService() { - return new EntityDescriptorVersionService() { - @Override - List findVersionsForEntityDescriptor(String resourceId) { - return [new Version(id: '1', creator: 'kramer', date: LocalDateTime.now().minusDays(3)), - new Version(id: '2', creator: 'newman', date: LocalDateTime.now())] - } - - @Override - EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) { - return entityDescriptorService.createRepresentationFromDescriptor(new TestObjectGenerator().buildEntityDescriptor()) - } - } - }*/ - -} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy index 426c5eb6e..0114e2ffb 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy @@ -1,24 +1,19 @@ package edu.internet2.tier.shibboleth.admin.ui.service -import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.EntitiesVersioningConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.* import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository -import edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager import spock.lang.Specification -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.* +import java.time.LocalDateTime + import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction @DataJpaTest @@ -39,25 +34,45 @@ class EnversEntityDescriptorVersionServiceTests extends Specification { @Autowired PlatformTransactionManager txMgr - def "temp test"() { - def representation = new EntityDescriptorRepresentation().with { - it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] - it - } - EntityDescriptor ed = entityDescriptorService.createDescriptorFromRepresentation(representation) + @DirtiesContext + def "versioning service returns correct number of versions sorted by modified date in natural order"() { + when: 'Initial version' + EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1') ed = doInExplicitTransaction(txMgr) { entityDescriptorRepository.save(ed) } - entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + def versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) - ed.entityID = "Entity ID" + then: + versions.size() == 1 + versions[0].id + versions[0].creator + versions[0].date < LocalDateTime.now() + + when: 'Third version' + ed.serviceProviderName = 'SP2' ed = doInExplicitTransaction(txMgr) { entityDescriptorRepository.save(ed) } + versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) - def versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + then: + versions.size() == 2 + versions[0].id && versions[1].id + versions[0].creator && versions[1].creator + versions[0].date < versions[1].date + + when: 'Third version' + ed.serviceProviderName = 'SP3' + ed = doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) - expect: - true + then: + versions.size() == 3 + versions[0].id && versions[1].id && versions[2].id + versions[0].creator && versions[1].creator && versions[2].creator + (versions[0].date < versions[1].date) && (versions[1].date < versions[2].date) } } From 812d90e2fdc73246d370bf373bbfbbcc77876e12 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 6 Jun 2019 10:11:59 -0400 Subject: [PATCH 28/51] Polishing --- .../ui/service/EnversEntityDescriptorVersionServiceTests.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy index 0114e2ffb..adc723b83 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy @@ -49,7 +49,7 @@ class EnversEntityDescriptorVersionServiceTests extends Specification { versions[0].creator versions[0].date < LocalDateTime.now() - when: 'Third version' + when: 'Second version' ed.serviceProviderName = 'SP2' ed = doInExplicitTransaction(txMgr) { entityDescriptorRepository.save(ed) From 5e16afa3c5d94fff3af0cd3ad18cfa9dd28e6e51 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 7 Jun 2019 11:04:12 -0400 Subject: [PATCH 29/51] Fixing tests --- .../EntityDescriptorController.java | 4 ---- .../admin/ui/domain/EntityDescriptor.java | 8 ++++++- .../JPAEntityDescriptorServiceImpl.java | 2 +- ...EntityDescriptorVersionServiceTests.groovy | 2 ++ ...JPAEntityDescriptorServiceImplTests.groovy | 22 +++---------------- 5 files changed, 13 insertions(+), 25 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java index 6690d4520..8bb0da84f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java @@ -6,8 +6,6 @@ import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository; import edu.internet2.tier.shibboleth.admin.ui.security.model.User; -import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository; -import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository; import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService; import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService; @@ -34,11 +32,9 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import javax.annotation.PostConstruct; -import javax.xml.ws.Response; import java.net.URI; import java.util.List; import java.util.stream.Collectors; -import java.util.stream.Stream; @RestController @RequestMapping("/api") diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java index b2054d362..dc036fa7f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityDescriptor.java @@ -26,7 +26,7 @@ @Entity -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode(callSuper = true, exclude={"versionModifiedTimestamp"}) @Audited public class EntityDescriptor extends AbstractDescriptor implements org.opensaml.saml.saml2.metadata.EntityDescriptor { private String localId; @@ -39,6 +39,8 @@ public class EntityDescriptor extends AbstractDescriptor implements org.opensaml private String resourceId; + private Long versionModifiedTimestamp; + @OneToOne(cascade = CascadeType.ALL) private Organization organization; @@ -77,6 +79,10 @@ public EntityDescriptor() { this.resourceId = UUID.randomUUID().toString(); } + public void setVersionModifiedTimestamp(Long versionModifiedTimestamp) { + this.versionModifiedTimestamp = versionModifiedTimestamp; + } + //getters and setters @Override public String getID() { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java index e97c166a3..ca7a8659e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java @@ -123,7 +123,7 @@ private EntityDescriptor buildDescriptorFromRepresentation(final EntityDescripto //Let envers recognize update revision type for EntityDescriptor type //when modifying Attributes and SPSSODescriptor inside RoleDescriptors collection - ed.setModifiedDate(LocalDateTime.now()); + ed.setVersionModifiedTimestamp(System.currentTimeMillis()); return ed; } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy index adc723b83..7a28fcd7b 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy @@ -10,6 +10,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager +import spock.lang.Ignore import spock.lang.Specification import java.time.LocalDateTime @@ -20,6 +21,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTes @ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration, EntitiesVersioningConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") +@Ignore class EnversEntityDescriptorVersionServiceTests extends Specification { @Autowired diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy index eeb22048e..38dfb821e 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy @@ -4,22 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.ShibbolethUiApplication import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.CustomPropertiesConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.TestEntityDescriptorVersioningConfiguration -import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.SPSSODescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.XSAny -import edu.internet2.tier.shibboleth.admin.ui.domain.XSAnyBuilder -import edu.internet2.tier.shibboleth.admin.ui.domain.XSBoolean -import edu.internet2.tier.shibboleth.admin.ui.domain.XSBooleanBuilder -import edu.internet2.tier.shibboleth.admin.ui.domain.XSStringBuilder -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.LogoutEndpointRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.SecurityInfoRepresentation -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.* +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.* import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository @@ -27,7 +13,6 @@ import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService import edu.internet2.tier.shibboleth.admin.ui.util.RandomGenerator import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator import edu.internet2.tier.shibboleth.admin.util.AttributeUtility -import groovy.json.JsonOutput import org.skyscreamer.jsonassert.JSONAssert import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest @@ -38,10 +23,9 @@ import org.xmlunit.builder.DiffBuilder import org.xmlunit.builder.Input import org.xmlunit.diff.DefaultNodeMatcher import org.xmlunit.diff.ElementSelectors -import spock.lang.Ignore import spock.lang.Specification -@ContextConfiguration(classes=[CoreShibUiConfiguration, CustomPropertiesConfiguration, TestEntityDescriptorVersioningConfiguration]) +@ContextConfiguration(classes=[CoreShibUiConfiguration, CustomPropertiesConfiguration]) @SpringBootTest(classes = ShibbolethUiApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) @PropertySource("classpath:application.yml") class JPAEntityDescriptorServiceImplTests extends Specification { From a179f369c00cc8b786813cb6817bde0eebf0b9eb Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 7 Jun 2019 11:31:32 -0400 Subject: [PATCH 30/51] SHIBUI-1262 - disable ntity desc versioning tests as they are expencive and cuse OOM - for now --- .../envers/EntityDescriptorEnversVersioningTests.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index acea73775..c71cd55a8 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -16,6 +16,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager +import spock.lang.Ignore import spock.lang.Specification import javax.persistence.EntityManager @@ -31,6 +32,7 @@ import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHE @ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") +@Ignore class EntityDescriptorEnversVersioningTests extends Specification { @Autowired From 4678866c1e5a3c9d108d09a873a679326fdfc140 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 7 Jun 2019 15:02:45 -0400 Subject: [PATCH 31/51] SHIBUI-1262 optimize tests --- .../EntityDescriptorEnversVersioningTests.groovy | 11 +---------- .../ui/repository/envers/EnversTestsSupport.groovy | 6 ++++-- .../EnversEntityDescriptorVersionServiceTests.groovy | 3 +-- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index c71cd55a8..af2047eae 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -16,7 +16,6 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager -import spock.lang.Ignore import spock.lang.Specification import javax.persistence.EntityManager @@ -32,7 +31,7 @@ import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHE @ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") -@Ignore +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) class EntityDescriptorEnversVersioningTests extends Specification { @Autowired @@ -50,7 +49,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { @Autowired OpenSamlObjects openSamlObjects - @DirtiesContext def "test versioning with contact persons"() { setup: def expectedModifiedPersistentEntities = [EntityDescriptor.name, ContactPerson.name, GivenName.name, EmailAddress.name] @@ -122,7 +120,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { } - @DirtiesContext def "test versioning with organization"() { setup: def expectedModifiedPersistentEntities = [EntityDescriptor.name, @@ -176,7 +173,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L } - @DirtiesContext def "test versioning with sp sso descriptor"() { setup: def expectedModifiedPersistentEntities = [EntityDescriptor.name, @@ -238,7 +234,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L } - @DirtiesContext def "test versioning with uiInfo"() { setup: def expectedModifiedPersistentEntities = [EntityDescriptor.name, @@ -330,7 +325,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { uiinfoInitialRevision.logos[0].width == 30 } - @DirtiesContext def "test versioning with security"() { setup: def expectedModifiedPersistentEntities = [EntityDescriptor.name, @@ -425,7 +419,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { x509cert.value == 'signingValue' } - @DirtiesContext def "test versioning ACS"() { setup: def expectedModifiedPersistentEntities = [EntityDescriptor.name, @@ -495,7 +488,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' } - @DirtiesContext def "test versioning logout"() { setup: def expectedModifiedPersistentEntities = [EntityDescriptor.name, @@ -558,7 +550,6 @@ class EntityDescriptorEnversVersioningTests extends Specification { slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' } - @DirtiesContext def "test versioning relying party overrides"() { setup: def expectedModifiedPersistentEntities = [EntityDescriptor.name, diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy index 3d2632f6b..ca447e7f0 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EnversTestsSupport.groovy @@ -5,6 +5,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRe import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService import org.hibernate.envers.AuditReaderFactory +import org.hibernate.envers.query.AuditEntity import org.hibernate.envers.query.AuditQuery import org.springframework.transaction.PlatformTransactionManager import org.springframework.transaction.support.DefaultTransactionDefinition @@ -36,14 +37,15 @@ class EnversTestsSupport { edr.save(ed) } - getRevisionHistoryForEntityType(em, EntityDescriptor) + getRevisionHistoryForEntityType(em, EntityDescriptor, ed.resourceId) } - static getRevisionHistoryForEntityType(EntityManager em, Class entityType) { + static getRevisionHistoryForEntityType(EntityManager em, Class entityType, String resourceId) { def auditReader = AuditReaderFactory.get(em) AuditQuery auditQuery = auditReader .createQuery() .forRevisionsOfEntity(entityType, false, false) + .add(AuditEntity.property("resourceId").eq(resourceId)) auditQuery.resultList } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy index 7a28fcd7b..37e6113a0 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy @@ -6,6 +6,7 @@ import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorReposit import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.boot.test.context.SpringBootTest import org.springframework.data.jpa.repository.config.EnableJpaRepositories import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration @@ -21,7 +22,6 @@ import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTes @ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration, EntitiesVersioningConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") -@Ignore class EnversEntityDescriptorVersionServiceTests extends Specification { @Autowired @@ -36,7 +36,6 @@ class EnversEntityDescriptorVersionServiceTests extends Specification { @Autowired PlatformTransactionManager txMgr - @DirtiesContext def "versioning service returns correct number of versions sorted by modified date in natural order"() { when: 'Initial version' EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1') From 3ab91cd4487d9cbc4d36f61fc4109fdcf61f7594 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 7 Jun 2019 15:53:57 -0400 Subject: [PATCH 32/51] tests optimization --- .../envers/EntityDescriptorEnversVersioningTests.groovy | 2 ++ .../ui/service/EnversEntityDescriptorVersionServiceTests.groovy | 1 + 2 files changed, 3 insertions(+) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index af2047eae..5f833de03 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -16,6 +16,7 @@ import org.springframework.data.jpa.repository.config.EnableJpaRepositories import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager +import spock.lang.Ignore import spock.lang.Specification import javax.persistence.EntityManager @@ -32,6 +33,7 @@ import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHE @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) +//@Ignore class EntityDescriptorEnversVersioningTests extends Specification { @Autowired diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy index 37e6113a0..c59834bda 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy @@ -22,6 +22,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTes @ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration, EntitiesVersioningConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") +//@Ignore class EnversEntityDescriptorVersionServiceTests extends Specification { @Autowired From 23d5799b76af88e9acd7632b4b86353a7854393f Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 7 Jun 2019 15:55:53 -0400 Subject: [PATCH 33/51] tests optimization --- .../envers/EntityDescriptorEnversVersioningTests.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 5f833de03..659b51c3c 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -32,7 +32,7 @@ import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHE @ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) +//@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) //@Ignore class EntityDescriptorEnversVersioningTests extends Specification { From ee914e269c775144b41bcae43469e18738bd7b64 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 7 Jun 2019 16:51:44 -0400 Subject: [PATCH 34/51] Disable versioning test for now --- .../envers/EntityDescriptorEnversVersioningTests.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 659b51c3c..81d5ad7ab 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -33,7 +33,7 @@ import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHE @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") //@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) -//@Ignore +@Ignore class EntityDescriptorEnversVersioningTests extends Specification { @Autowired From 7dab3e402569fb02ea6c38e760d686a62d1d2b4c Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Fri, 7 Jun 2019 22:40:59 -0400 Subject: [PATCH 35/51] Refactor tests to optimize and fix performance issues cause by versioning tests --- ...ityDescriptorEnversVersioningTestsX.groovy | 617 ++++++++++++++++++ ...EntityDescriptorVersionServiceTests.groovy | 2 +- envers-tests-module/build.gradle | 34 + ....ui.envers-tests-module.main.kotlin_module | Bin 0 -> 16 bytes ...tityDescriptorEnversVersioningTests.groovy | 5 +- settings.gradle | 2 +- 6 files changed, 656 insertions(+), 4 deletions(-) create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTestsX.groovy create mode 100644 envers-tests-module/build.gradle create mode 100644 envers-tests-module/out/test/classes/META-INF/edu.internet2.tier.shibboleth.admin.ui.envers-tests-module.main.kotlin_module rename {backend => envers-tests-module}/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy (99%) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTestsX.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTestsX.groovy new file mode 100644 index 000000000..a95ded149 --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTestsX.groovy @@ -0,0 +1,617 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository.envers + +import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.* +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.* +import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.domain.EntityScan +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.ContextConfiguration +import org.springframework.transaction.PlatformTransactionManager +import spock.lang.Ignore +import spock.lang.Specification + +import javax.persistence.EntityManager + +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.* +import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE +import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER + +/** + * Testing entity descriptor envers versioning + */ +@DataJpaTest +@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration]) +@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) +@EntityScan("edu.internet2.tier.shibboleth.admin.ui") +//@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) +@Ignore +class EntityDescriptorEnversVersioningTestsX extends Specification { + + @Autowired + EntityDescriptorRepository entityDescriptorRepository + + @Autowired + EntityDescriptorService entityDescriptorService + + @Autowired + EntityManager entityManager + + @Autowired + PlatformTransactionManager txMgr + + @Autowired + OpenSamlObjects openSamlObjects + + def "test versioning with contact persons"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, ContactPerson.name, GivenName.name, EmailAddress.name] + + when: + def ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] + it + } + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 1 + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].givenName.name == 'name' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].type == ADMINISTRATIVE + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].emailAddresses[0].address == 'test@test' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'administrative', name: 'nameUPDATED', emailAddress: 'test@test')] + it + } + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + then: + entityDescriptorHistory.size() == 2 + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED2', emailAddress: 'test@test.com')] + it + } + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, + entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 3 + getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].givenName.name == 'nameUPDATED2' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].type == OTHER + getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].emailAddresses[0].address == 'test@test.com' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 2).sort() == expectedModifiedPersistentEntities.sort() + + //Also make sure we have our original revision + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + + } + + def "test versioning with organization"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + Organization.name, + OrganizationDisplayName.name, + OrganizationName.name, + OrganizationURL.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.organization = new OrganizationRepresentation(name: 'org', displayName: 'display org', url: 'http://org.edu') + it + } + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + then: + entityDescriptorHistory.size() == 1 + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.organization = new OrganizationRepresentation(name: 'orgUpdated', displayName: 'display org Updated', url: 'http://org2.edu') + it + } + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + then: + entityDescriptorHistory.size() == 2 + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.organizationNames[0].value == 'orgUpdated' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.displayNames[0].value == 'display org Updated' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.URLs[0].value == 'http://org2.edu' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the original revision is intact + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + } + + def "test versioning with sp sso descriptor"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + NameIDFormat.name, + SPSSODescriptor.name] + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { + it.protocolSupportEnum = 'SAML 1.1' + it.nameIdFormats = ['format'] + it + } + it + } + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 1 + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { + it.protocolSupportEnum = 'SAML 1.1, SAML 2' + it.nameIdFormats = ['formatUPDATED'] + it + } + it + } + + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 2 + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the original revision is intact + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + } + + def "test versioning with uiInfo"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + Description.name, + DisplayName.name, + SPSSODescriptor.name, + Extensions.name, + InformationURL.name, + Logo.name, + PrivacyStatementURL.name, + UIInfo.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.mdui = new MduiRepresentation().with { + it.displayName = 'Initial display name' + it.informationUrl = 'http://info' + it.privacyStatementUrl = 'http://privacy' + it.description = 'Initial desc' + it.logoUrl = 'http://logo' + it.logoHeight = 20 + it.logoWidth = 30 + it + } + it + } + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + //Groovy FTW - able to call any private methods on ANY object. Get first revision + UIInfo uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + then: + entityDescriptorHistory.size() == 1 + uiinfo.displayNames[0].value == 'Initial display name' + uiinfo.informationURLs[0].value == 'http://info' + uiinfo.privacyStatementURLs[0].value == 'http://privacy' + uiinfo.descriptions[0].value == 'Initial desc' + uiinfo.logos[0].URL == 'http://logo' + uiinfo.logos[0].height == 20 + uiinfo.logos[0].width == 30 + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.mdui = new MduiRepresentation().with { + it.displayName = 'Display name UPDATED' + it.informationUrl = 'http://info.updated' + it.privacyStatementUrl = 'http://privacy.updated' + it.description = 'Desc UPDATED' + it.logoUrl = 'http://logo.updated' + it.logoHeight = 30 + it.logoWidth = 40 + it + } + it + } + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + //Get second revision + uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + //And initial revision + def uiinfoInitialRevision = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + then: + entityDescriptorHistory.size() == 2 + uiinfo.displayNames[0].value == 'Display name UPDATED' + uiinfo.informationURLs[0].value == 'http://info.updated' + uiinfo.privacyStatementURLs[0].value == 'http://privacy.updated' + uiinfo.descriptions[0].value == 'Desc UPDATED' + uiinfo.logos[0].URL == 'http://logo.updated' + uiinfo.logos[0].height == 30 + uiinfo.logos[0].width == 40 + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial revision is still intact + uiinfoInitialRevision.displayNames[0].value == 'Initial display name' + uiinfoInitialRevision.informationURLs[0].value == 'http://info' + uiinfoInitialRevision.privacyStatementURLs[0].value == 'http://privacy' + uiinfoInitialRevision.descriptions[0].value == 'Initial desc' + uiinfoInitialRevision.logos[0].URL == 'http://logo' + uiinfoInitialRevision.logos[0].height == 20 + uiinfoInitialRevision.logos[0].width == 30 + } + + def "test versioning with security"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + KeyDescriptor.name, + KeyInfo.name, + SPSSODescriptor.name, + X509Certificate.name, + X509Data.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.securityInfo = new SecurityInfoRepresentation().with { + it.authenticationRequestsSigned = true + it.x509CertificateAvailable = true + it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue')] + it + } + it + } + + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + //Get initial revision + SPSSODescriptor spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + + KeyDescriptor keyDescriptor = spssoDescriptor.keyDescriptors[0] + X509Certificate x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] + + then: + entityDescriptorHistory.size() == 1 + spssoDescriptor.isAuthnRequestsSigned() + keyDescriptor.name == 'sign' + keyDescriptor.usageType == 'signing' + x509cert.value == 'signingValue' + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.securityInfo = new SecurityInfoRepresentation().with { + it.authenticationRequestsSigned = false + it.x509CertificateAvailable = true + it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue'), + new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'encrypt', type: 'encryption', value: 'encryptionValue')] + it + } + it + } + + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + + //Get second revision + SPSSODescriptor spssoDescriptor_second = entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) + + KeyDescriptor keyDescriptor_second1 = spssoDescriptor_second.keyDescriptors[0] + X509Certificate x509cert_second1 = keyDescriptor_second1.keyInfo.x509Datas[0].x509Certificates[0] + KeyDescriptor keyDescriptor_second2 = spssoDescriptor_second.keyDescriptors[1] + X509Certificate x509cert_second2 = keyDescriptor_second2.keyInfo.x509Datas[0].x509Certificates[0] + + + //Get initial revision + spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + + keyDescriptor = spssoDescriptor.keyDescriptors[0] + x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] + + then: + entityDescriptorHistory.size() == 2 + !spssoDescriptor_second.isAuthnRequestsSigned() + keyDescriptor_second1.name == 'sign' + keyDescriptor_second1.usageType == 'signing' + keyDescriptor_second2.name == 'encrypt' + keyDescriptor_second2.usageType == 'encryption' + x509cert_second1.value == 'signingValue' + x509cert_second2.value == 'encryptionValue' + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial version is intact + spssoDescriptor.keyDescriptors.size() == 1 + spssoDescriptor.isAuthnRequestsSigned() + keyDescriptor.name == 'sign' + keyDescriptor.usageType == 'signing' + x509cert.value == 'signingValue' + } + + def "test versioning ACS"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + SPSSODescriptor.name, + AssertionConsumerService.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.assertionConsumerServices = [ + new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] + it + } + + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + AssertionConsumerService acs = spssoDescriptor.assertionConsumerServices[0] + + then: + entityDescriptorHistory.size() == 1 + !acs.isDefault() + acs.location == 'http://acs' + acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + + when: + representation = new EntityDescriptorRepresentation().with { + it.assertionConsumerServices = [ + new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs.updated', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS', makeDefault: true), + new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs2', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] + it + } + + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor2 = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) + def (acs1, acs2) = [spssoDescriptor2.assertionConsumerServices[0], spssoDescriptor2.assertionConsumerServices[1]] + + //Initial revision + spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + acs = spssoDescriptor.assertionConsumerServices[0] + + then: + entityDescriptorHistory.size() == 2 + acs1.isDefault() + !acs2.isDefault() + acs1.location == 'http://acs.updated' + acs1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' + acs2.location == 'http://acs2' + acs2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial revision is intact + !acs.isDefault() + acs.location == 'http://acs' + acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + } + + def "test versioning logout"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + SPSSODescriptor.name, + SingleLogoutService.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] + it + } + + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + SingleLogoutService slo = spssoDescriptor.singleLogoutServices[0] + + then: + entityDescriptorHistory.size() == 1 + slo.location == 'http://logout' + slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout.updated', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS'), + new LogoutEndpointRepresentation(url: 'http://logout2', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] + it + } + + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor2 = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + def (slo1, slo2) = [spssoDescriptor2.singleLogoutServices[0], spssoDescriptor2.singleLogoutServices[1]] + + //Initial revision + spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + slo = spssoDescriptor.singleLogoutServices[0] + + then: + entityDescriptorHistory.size() == 2 + slo1.location == 'http://logout.updated' + slo1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' + slo2.location == 'http://logout2' + slo2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial version is intact + slo.location == 'http://logout' + slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + } + + def "test versioning relying party overrides"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + EntityAttributes.name, + Extensions.name, + Attribute.name, + XSBoolean.name, + XSString.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.relyingPartyOverrides = [signAssertion: true] + it.attributeRelease = ['attr1'] + it + } + + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + EntityAttributes attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + then: + entityDescriptorHistory.size() == 1 + attrs.attributes[0].attributeValues[0].storedValue == 'true' + attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.relyingPartyOverrides = [signAssertion: false] + it.attributeRelease = ['attr1', 'attr2'] + it + } + + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + EntityAttributes attrs2 = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + + //Initial revision + attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + expectedModifiedPersistentEntities = [EntityDescriptor.name, + EntityAttributes.name, + Attribute.name, + XSString.name] + then: + entityDescriptorHistory.size() == 2 + attrs2.attributes[0].attributeValues[0].xsStringvalue == 'attr1' + attrs2.attributes[0].attributeValues[1].xsStringvalue == 'attr2' + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial revision is intact + attrs.attributes[0].attributeValues[0].storedValue == 'true' + attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' + attrs.attributes[1].attributeValues[1] == null + } +} diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy index c59834bda..ce6ad7cc6 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy @@ -22,7 +22,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTes @ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration, EntitiesVersioningConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") -//@Ignore +@Ignore class EnversEntityDescriptorVersionServiceTests extends Specification { @Autowired diff --git a/envers-tests-module/build.gradle b/envers-tests-module/build.gradle new file mode 100644 index 000000000..975da5e36 --- /dev/null +++ b/envers-tests-module/build.gradle @@ -0,0 +1,34 @@ +plugins { + id 'groovy' + id 'jacoco' + id 'org.springframework.boot' version '2.0.0.RELEASE' apply false + id 'io.spring.dependency-management' version '1.0.6.RELEASE' +} + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +repositories { + jcenter() + maven { + url 'https://build.shibboleth.net/nexus/content/groups/public' + artifactUrls = ['https://build.shibboleth.net/nexus/content/repositories/thirdparty-snapshots'] + } +} + +dependencyManagement { + imports { + mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES + } +} + +dependencies { + + compile project(':backend') + //testCompile project(':backend') + testCompile project(':backend').sourceSets.test.output + //testCompile "org.springframework.boot:spring-boot-starter-data-jpa" + testCompile "org.springframework.boot:spring-boot-starter-test" + testCompile "org.spockframework:spock-core:1.1-groovy-2.4" + testCompile "org.spockframework:spock-spring:1.1-groovy-2.4" +} diff --git a/envers-tests-module/out/test/classes/META-INF/edu.internet2.tier.shibboleth.admin.ui.envers-tests-module.main.kotlin_module b/envers-tests-module/out/test/classes/META-INF/edu.internet2.tier.shibboleth.admin.ui.envers-tests-module.main.kotlin_module new file mode 100644 index 0000000000000000000000000000000000000000..2983af70661ad375cc499ebc4da5a68ca46c532e GIT binary patch literal 16 RcmZQzU|?ooU|@t|egFVe02KfL literal 0 HcmV?d00001 diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy similarity index 99% rename from backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy rename to envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 81d5ad7ab..c1c8e8fd3 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -12,6 +12,7 @@ import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest + import org.springframework.data.jpa.repository.config.EnableJpaRepositories import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration @@ -29,11 +30,11 @@ import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHE * Testing entity descriptor envers versioning */ @DataJpaTest -@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration]) +@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, SearchConfiguration, TestConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") //@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) -@Ignore +//@Ignore class EntityDescriptorEnversVersioningTests extends Specification { @Autowired diff --git a/settings.gradle b/settings.gradle index 8fae26617..ba298e3de 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include 'backend', 'ui', 'pac4j-module' \ No newline at end of file +include 'backend', 'ui', 'pac4j-module', 'envers-tests-module' From 91ac793f2db25e6833e9159240d9f12d2e472cde Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Sat, 8 Jun 2019 09:35:38 -0400 Subject: [PATCH 36/51] Optimize tests by separating envers tests into a separate module --- ...ityDescriptorEnversVersioningTestsX.groovy | 617 ------------------ ...tityDescriptorEnversVersioningTests.groovy | 5 - ...verEntityBasicEnversVersioningTests.groovy | 0 ...EntityDescriptorVersionServiceTests.groovy | 8 +- 4 files changed, 3 insertions(+), 627 deletions(-) delete mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTestsX.groovy rename {backend => envers-tests-module}/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy (100%) rename {backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service => envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers}/EnversEntityDescriptorVersionServiceTests.groovy (93%) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTestsX.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTestsX.groovy deleted file mode 100644 index a95ded149..000000000 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTestsX.groovy +++ /dev/null @@ -1,617 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.repository.envers - -import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration -import edu.internet2.tier.shibboleth.admin.ui.domain.* -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.* -import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects -import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.domain.EntityScan -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest -import org.springframework.data.jpa.repository.config.EnableJpaRepositories -import org.springframework.test.annotation.DirtiesContext -import org.springframework.test.context.ContextConfiguration -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.Ignore -import spock.lang.Specification - -import javax.persistence.EntityManager - -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.* -import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE -import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER - -/** - * Testing entity descriptor envers versioning - */ -@DataJpaTest -@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration]) -@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) -@EntityScan("edu.internet2.tier.shibboleth.admin.ui") -//@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) -@Ignore -class EntityDescriptorEnversVersioningTestsX extends Specification { - - @Autowired - EntityDescriptorRepository entityDescriptorRepository - - @Autowired - EntityDescriptorService entityDescriptorService - - @Autowired - EntityManager entityManager - - @Autowired - PlatformTransactionManager txMgr - - @Autowired - OpenSamlObjects openSamlObjects - - def "test versioning with contact persons"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, ContactPerson.name, GivenName.name, EmailAddress.name] - - when: - def ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] - it - } - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - then: - entityDescriptorHistory.size() == 1 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].givenName.name == 'name' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].type == ADMINISTRATIVE - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].emailAddresses[0].address == 'test@test' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.contacts = [new ContactRepresentation(type: 'administrative', name: 'nameUPDATED', emailAddress: 'test@test')] - it - } - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - then: - entityDescriptorHistory.size() == 2 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED2', emailAddress: 'test@test.com')] - it - } - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, - entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - then: - entityDescriptorHistory.size() == 3 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].givenName.name == 'nameUPDATED2' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].type == OTHER - getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].emailAddresses[0].address == 'test@test.com' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 2).sort() == expectedModifiedPersistentEntities.sort() - - //Also make sure we have our original revision - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - - } - - def "test versioning with organization"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - Organization.name, - OrganizationDisplayName.name, - OrganizationName.name, - OrganizationURL.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.organization = new OrganizationRepresentation(name: 'org', displayName: 'display org', url: 'http://org.edu') - it - } - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - then: - entityDescriptorHistory.size() == 1 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.organization = new OrganizationRepresentation(name: 'orgUpdated', displayName: 'display org Updated', url: 'http://org2.edu') - it - } - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - then: - entityDescriptorHistory.size() == 2 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.organizationNames[0].value == 'orgUpdated' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.displayNames[0].value == 'display org Updated' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.URLs[0].value == 'http://org2.edu' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the original revision is intact - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - } - - def "test versioning with sp sso descriptor"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - NameIDFormat.name, - SPSSODescriptor.name] - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { - it.protocolSupportEnum = 'SAML 1.1' - it.nameIdFormats = ['format'] - it - } - it - } - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - then: - entityDescriptorHistory.size() == 1 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { - it.protocolSupportEnum = 'SAML 1.1, SAML 2' - it.nameIdFormats = ['formatUPDATED'] - it - } - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - then: - entityDescriptorHistory.size() == 2 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the original revision is intact - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - } - - def "test versioning with uiInfo"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - Description.name, - DisplayName.name, - SPSSODescriptor.name, - Extensions.name, - InformationURL.name, - Logo.name, - PrivacyStatementURL.name, - UIInfo.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.mdui = new MduiRepresentation().with { - it.displayName = 'Initial display name' - it.informationUrl = 'http://info' - it.privacyStatementUrl = 'http://privacy' - it.description = 'Initial desc' - it.logoUrl = 'http://logo' - it.logoHeight = 20 - it.logoWidth = 30 - it - } - it - } - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - //Groovy FTW - able to call any private methods on ANY object. Get first revision - UIInfo uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - - then: - entityDescriptorHistory.size() == 1 - uiinfo.displayNames[0].value == 'Initial display name' - uiinfo.informationURLs[0].value == 'http://info' - uiinfo.privacyStatementURLs[0].value == 'http://privacy' - uiinfo.descriptions[0].value == 'Initial desc' - uiinfo.logos[0].URL == 'http://logo' - uiinfo.logos[0].height == 20 - uiinfo.logos[0].width == 30 - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.mdui = new MduiRepresentation().with { - it.displayName = 'Display name UPDATED' - it.informationUrl = 'http://info.updated' - it.privacyStatementUrl = 'http://privacy.updated' - it.description = 'Desc UPDATED' - it.logoUrl = 'http://logo.updated' - it.logoHeight = 30 - it.logoWidth = 40 - it - } - it - } - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - //Get second revision - uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) - //And initial revision - def uiinfoInitialRevision = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - - then: - entityDescriptorHistory.size() == 2 - uiinfo.displayNames[0].value == 'Display name UPDATED' - uiinfo.informationURLs[0].value == 'http://info.updated' - uiinfo.privacyStatementURLs[0].value == 'http://privacy.updated' - uiinfo.descriptions[0].value == 'Desc UPDATED' - uiinfo.logos[0].URL == 'http://logo.updated' - uiinfo.logos[0].height == 30 - uiinfo.logos[0].width == 40 - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial revision is still intact - uiinfoInitialRevision.displayNames[0].value == 'Initial display name' - uiinfoInitialRevision.informationURLs[0].value == 'http://info' - uiinfoInitialRevision.privacyStatementURLs[0].value == 'http://privacy' - uiinfoInitialRevision.descriptions[0].value == 'Initial desc' - uiinfoInitialRevision.logos[0].URL == 'http://logo' - uiinfoInitialRevision.logos[0].height == 20 - uiinfoInitialRevision.logos[0].width == 30 - } - - def "test versioning with security"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - KeyDescriptor.name, - KeyInfo.name, - SPSSODescriptor.name, - X509Certificate.name, - X509Data.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.securityInfo = new SecurityInfoRepresentation().with { - it.authenticationRequestsSigned = true - it.x509CertificateAvailable = true - it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue')] - it - } - it - } - - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - //Get initial revision - SPSSODescriptor spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) - - KeyDescriptor keyDescriptor = spssoDescriptor.keyDescriptors[0] - X509Certificate x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] - - then: - entityDescriptorHistory.size() == 1 - spssoDescriptor.isAuthnRequestsSigned() - keyDescriptor.name == 'sign' - keyDescriptor.usageType == 'signing' - x509cert.value == 'signingValue' - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.securityInfo = new SecurityInfoRepresentation().with { - it.authenticationRequestsSigned = false - it.x509CertificateAvailable = true - it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue'), - new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'encrypt', type: 'encryption', value: 'encryptionValue')] - it - } - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - - //Get second revision - SPSSODescriptor spssoDescriptor_second = entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) - - KeyDescriptor keyDescriptor_second1 = spssoDescriptor_second.keyDescriptors[0] - X509Certificate x509cert_second1 = keyDescriptor_second1.keyInfo.x509Datas[0].x509Certificates[0] - KeyDescriptor keyDescriptor_second2 = spssoDescriptor_second.keyDescriptors[1] - X509Certificate x509cert_second2 = keyDescriptor_second2.keyInfo.x509Datas[0].x509Certificates[0] - - - //Get initial revision - spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) - - keyDescriptor = spssoDescriptor.keyDescriptors[0] - x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] - - then: - entityDescriptorHistory.size() == 2 - !spssoDescriptor_second.isAuthnRequestsSigned() - keyDescriptor_second1.name == 'sign' - keyDescriptor_second1.usageType == 'signing' - keyDescriptor_second2.name == 'encrypt' - keyDescriptor_second2.usageType == 'encryption' - x509cert_second1.value == 'signingValue' - x509cert_second2.value == 'encryptionValue' - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial version is intact - spssoDescriptor.keyDescriptors.size() == 1 - spssoDescriptor.isAuthnRequestsSigned() - keyDescriptor.name == 'sign' - keyDescriptor.usageType == 'signing' - x509cert.value == 'signingValue' - } - - def "test versioning ACS"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - SPSSODescriptor.name, - AssertionConsumerService.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.assertionConsumerServices = [ - new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] - it - } - - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - SPSSODescriptor spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) - AssertionConsumerService acs = spssoDescriptor.assertionConsumerServices[0] - - then: - entityDescriptorHistory.size() == 1 - !acs.isDefault() - acs.location == 'http://acs' - acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - - when: - representation = new EntityDescriptorRepresentation().with { - it.assertionConsumerServices = [ - new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs.updated', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS', makeDefault: true), - new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs2', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - SPSSODescriptor spssoDescriptor2 = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) - def (acs1, acs2) = [spssoDescriptor2.assertionConsumerServices[0], spssoDescriptor2.assertionConsumerServices[1]] - - //Initial revision - spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) - acs = spssoDescriptor.assertionConsumerServices[0] - - then: - entityDescriptorHistory.size() == 2 - acs1.isDefault() - !acs2.isDefault() - acs1.location == 'http://acs.updated' - acs1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' - acs2.location == 'http://acs2' - acs2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial revision is intact - !acs.isDefault() - acs.location == 'http://acs' - acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - } - - def "test versioning logout"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - SPSSODescriptor.name, - SingleLogoutService.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] - it - } - - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - SPSSODescriptor spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - SingleLogoutService slo = spssoDescriptor.singleLogoutServices[0] - - then: - entityDescriptorHistory.size() == 1 - slo.location == 'http://logout' - slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout.updated', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS'), - new LogoutEndpointRepresentation(url: 'http://logout2', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - SPSSODescriptor spssoDescriptor2 = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) - def (slo1, slo2) = [spssoDescriptor2.singleLogoutServices[0], spssoDescriptor2.singleLogoutServices[1]] - - //Initial revision - spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - slo = spssoDescriptor.singleLogoutServices[0] - - then: - entityDescriptorHistory.size() == 2 - slo1.location == 'http://logout.updated' - slo1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' - slo2.location == 'http://logout2' - slo2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial version is intact - slo.location == 'http://logout' - slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - } - - def "test versioning relying party overrides"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - EntityAttributes.name, - Extensions.name, - Attribute.name, - XSBoolean.name, - XSString.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.relyingPartyOverrides = [signAssertion: true] - it.attributeRelease = ['attr1'] - it - } - - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - EntityAttributes attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - - then: - entityDescriptorHistory.size() == 1 - attrs.attributes[0].attributeValues[0].storedValue == 'true' - attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.relyingPartyOverrides = [signAssertion: false] - it.attributeRelease = ['attr1', 'attr2'] - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - EntityAttributes attrs2 = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) - - //Initial revision - attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - - expectedModifiedPersistentEntities = [EntityDescriptor.name, - EntityAttributes.name, - Attribute.name, - XSString.name] - then: - entityDescriptorHistory.size() == 2 - attrs2.attributes[0].attributeValues[0].xsStringvalue == 'attr1' - attrs2.attributes[0].attributeValues[1].xsStringvalue == 'attr2' - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial revision is intact - attrs.attributes[0].attributeValues[0].storedValue == 'true' - attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' - attrs.attributes[1].attributeValues[1] == null - } -} diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index c1c8e8fd3..b2bcd517e 100644 --- a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -12,12 +12,9 @@ import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest - import org.springframework.data.jpa.repository.config.EnableJpaRepositories -import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager -import spock.lang.Ignore import spock.lang.Specification import javax.persistence.EntityManager @@ -33,8 +30,6 @@ import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHE @ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, SearchConfiguration, TestConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") -//@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) -//@Ignore class EntityDescriptorEnversVersioningTests extends Specification { @Autowired diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy similarity index 100% rename from backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy rename to envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy similarity index 93% rename from backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy rename to envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy index ce6ad7cc6..ce1b918e7 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionServiceTests.groovy +++ b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy @@ -1,17 +1,16 @@ -package edu.internet2.tier.shibboleth.admin.ui.service +package edu.internet2.tier.shibboleth.admin.ui.service.envers import edu.internet2.tier.shibboleth.admin.ui.configuration.* import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest -import org.springframework.boot.test.context.SpringBootTest import org.springframework.data.jpa.repository.config.EnableJpaRepositories -import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.transaction.PlatformTransactionManager -import spock.lang.Ignore import spock.lang.Specification import java.time.LocalDateTime @@ -22,7 +21,6 @@ import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTes @ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration, EntitiesVersioningConfiguration]) @EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) @EntityScan("edu.internet2.tier.shibboleth.admin.ui") -@Ignore class EnversEntityDescriptorVersionServiceTests extends Specification { @Autowired From 8f1c64a338a51bdd8b2ca6726103f0d805730fce Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 10 Jun 2019 15:46:06 -0400 Subject: [PATCH 37/51] SHIBUI-1262(1306,1309) --- .../tier/shibboleth/admin/ui/ShibbolethUiApplication.java | 2 +- .../admin/ui/envers/PrincipalEnhancingRevisionListener.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java index 2bd90bcc3..42e7901e7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java @@ -23,7 +23,7 @@ @SpringBootApplication @ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "edu.internet2.tier.shibboleth.admin.ui.configuration.auto.*")) -@EntityScan(basePackages = {"edu.internet2.tier.shibboleth.admin.ui.domain", "edu.internet2.tier.shibboleth.admin.ui.security.model"}) +@EntityScan(basePackages = {"edu.internet2.tier.shibboleth.admin.ui.domain", "edu.internet2.tier.shibboleth.admin.ui.envers", "edu.internet2.tier.shibboleth.admin.ui.security.model"}) @EnableJpaAuditing @EnableScheduling @EnableWebSecurity diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalEnhancingRevisionListener.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalEnhancingRevisionListener.java index 12af196ed..c1895b052 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalEnhancingRevisionListener.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/envers/PrincipalEnhancingRevisionListener.java @@ -9,7 +9,7 @@ */ public class PrincipalEnhancingRevisionListener implements RevisionListener { - private static final String ANONYMOUS = "anonymous"; + private static final String ANONYMOUS = "anonymousUser"; @Override public void newRevision(Object revisionEntity) { From 6de2a1563e782b6e1f09caa0f4d261ce26333e14 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Mon, 10 Jun 2019 16:04:51 -0400 Subject: [PATCH 38/51] Fix tests --- ...tityDescriptorEnversVersioningTests.groovy | 20 +++++++++---------- ...verEntityBasicEnversVersioningTests.groovy | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index b2bcd517e..795875962 100644 --- a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -67,7 +67,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].givenName.name == 'name' getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].type == ADMINISTRATIVE getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].emailAddresses[0].address == 'test@test' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() @@ -85,7 +85,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() @@ -105,7 +105,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].givenName.name == 'nameUPDATED2' getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].type == OTHER getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].emailAddresses[0].address == 'test@test.com' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).timestamp > 0L getModifiedEntityNames(entityDescriptorHistory, 2).sort() == expectedModifiedPersistentEntities.sort() @@ -113,7 +113,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L } @@ -141,7 +141,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() @@ -159,7 +159,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.organizationNames[0].value == 'orgUpdated' getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.displayNames[0].value == 'display org Updated' getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.URLs[0].value == 'http://org2.edu' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() @@ -167,7 +167,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L } @@ -196,7 +196,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() @@ -220,7 +220,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() @@ -228,7 +228,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymous' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L } diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy index c4f70dbcd..226df4476 100644 --- a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy +++ b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy @@ -55,7 +55,7 @@ class MetadataResolverEntityBasicEnversVersioningTests extends Specification { def rev = metadataResolverHistory[0] then: - rev[1].principalUserName == 'anonymous' + rev[1].principalUserName == 'anonymousUser' when: mdr.name = 'Updated' From 079f6455172a2cdb05e5616426b44052c3a4bd83 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Jun 2019 11:23:09 -0400 Subject: [PATCH 39/51] SHIBUI-1262(1310) --- .../admin/ui/configuration/DevConfig.groovy | 7 -- ...lerVersionEndpointsIntegrationTests.groovy | 81 +++++++++++++++++++ 2 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy index b49d5b858..f748de09f 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy @@ -161,11 +161,4 @@ class DevConfig { it }) } - - /*@Profile('dev-ed-versioning') - @Bean - EntityDescriptorVersionService stubEntityDescriptorVersionService(EntityDescriptorService entityDescriptorService, - EntityDescriptorRepository entityDescriptorRepository) { - return EntityDescriptorVersionService.stubImpl(entityDescriptorService, entityDescriptorRepository) - }*/ } diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy new file mode 100644 index 000000000..550604777 --- /dev/null +++ b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy @@ -0,0 +1,81 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller + +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository +import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator +import edu.internet2.tier.shibboleth.admin.util.AttributeUtility +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.test.web.client.TestRestTemplate +import org.springframework.test.context.ActiveProfiles +import spock.lang.Specification + +/** + * @author Dmitriy Kopylenko + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles(['no-auth', 'dev']) +class EntityDescriptorControllerVersionEndpointsIntegrationTests extends Specification { + + @Autowired + private TestRestTemplate restTemplate + + @Autowired + EntityDescriptorRepository entityDescriptorRepository + + static BASE_URI = '/api/EntityDescriptor' + + static ALL_VERSIONS_URI = "$BASE_URI/%s/Versions" + + def "GET /api/EntityDescriptor/{resourceId}/Versions with non-existent entity descriptor"() { + when: + def result = getAllEntityDescriptorVersions('non-existent-ed-id', String) + + then: + result.statusCodeValue == 404 + } + + def "GET /api/EntityDescriptor{resourceId}/Versions with 1 entity descriptor version"() { + given: + EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser') + entityDescriptorRepository.save(ed) + + when: + def result = getAllEntityDescriptorVersions(ed.resourceId, List) + + then: + result.statusCodeValue == 200 + result.body.size == 1 + result.body[0].id && result.body[0].creator && result.body[0].date + } + + def "GET /api/EntityDescriptor{resourceId}/Versions with 2 entity descriptor versions"() { + given: + EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser') + ed = entityDescriptorRepository.save(ed) + //Will created a second version for UPDATE revision + ed.serviceEnabled = true + entityDescriptorRepository.save(ed) + + when: + def result = getAllEntityDescriptorVersions(ed.resourceId, List) + + then: + result.statusCodeValue == 200 + result.body.size == 2 + result.body[0].id < result.body[1].id + result.body[0].date < result.body[1].date + } + + + + private getAllEntityDescriptorVersions(String resourceId, responseType) { + this.restTemplate.getForEntity(resourceUriFor(ALL_VERSIONS_URI, resourceId), responseType) + } + + + private static resourceUriFor(String uriTemplate, String resourceId) { + String.format(uriTemplate, resourceId) + } +} From 17e10a0d8c07bd9a542047f52aded677c0711b98 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Tue, 11 Jun 2019 16:40:03 -0400 Subject: [PATCH 40/51] SHIBUI-1262(1315, 1316) --- .../EntitiesVersioningConfiguration.java | 5 ++- .../EntityDescriptorVersionService.java | 24 ----------- .../EnversEntityDescriptorVersionService.java | 18 ++++++++- ...lerVersionEndpointsIntegrationTests.groovy | 40 +++++++++++++++++++ ...EntityDescriptorVersionServiceTests.groovy | 38 ++++++++++++++++++ 5 files changed, 97 insertions(+), 28 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java index b73448e5e..b190f2f5d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/EntitiesVersioningConfiguration.java @@ -1,5 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration; +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService; import edu.internet2.tier.shibboleth.admin.ui.service.EnversEntityDescriptorVersionService; import org.springframework.context.annotation.Bean; @@ -15,7 +16,7 @@ public class EntitiesVersioningConfiguration { private EntityManager entityManager; @Bean - EntityDescriptorVersionService entityDescriptorVersionService() { - return new EnversEntityDescriptorVersionService(entityManager); + EntityDescriptorVersionService entityDescriptorVersionService(EntityDescriptorService entityDescriptorService) { + return new EnversEntityDescriptorVersionService(entityManager, entityDescriptorService); } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java index e53072f99..6803796fa 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java @@ -17,28 +17,4 @@ public interface EntityDescriptorVersionService { List findVersionsForEntityDescriptor(String resourceId); EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId); - - /* Factory method to return stub impl for dev and testing purposes */ - static EntityDescriptorVersionService stubImpl(final EntityDescriptorService entityDescriptorService, - final EntityDescriptorRepository entityDescriptorRepository) { - return new EntityDescriptorVersionService() { - @Override - public List findVersionsForEntityDescriptor(String resourceId) { - return Arrays.asList( - new Version("1", "kramer", LocalDateTime.now().minusDays(10)), - new Version("2", "newman", LocalDateTime.now().minusDays(5)) - ); - } - - @Override - public EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) { - EntityDescriptor ed = new EntityDescriptor(); - ed.setID("1"); - ed.setEntityID("http://versioning/stub"); - ed.setCreatedBy("kramer"); - ed.setCreatedDate(LocalDateTime.now().minusDays(10)); - return entityDescriptorService.createRepresentationFromDescriptor(ed); - } - }; - } } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java index fced0645f..ec1e8ceb8 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java @@ -11,6 +11,7 @@ import org.springframework.data.jpa.repository.JpaContext; import javax.persistence.EntityManager; +import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import java.time.LocalDateTime; import java.time.ZoneId; @@ -29,8 +30,11 @@ public class EnversEntityDescriptorVersionService implements EntityDescriptorVer private EntityManager entityManager; - public EnversEntityDescriptorVersionService(EntityManager entityManager) { + private EntityDescriptorService entityDescriptorService; + + public EnversEntityDescriptorVersionService(EntityManager entityManager, EntityDescriptorService entityDescriptorService) { this.entityManager = entityManager; + this.entityDescriptorService = entityDescriptorService; } @Override @@ -58,6 +62,16 @@ public List findVersionsForEntityDescriptor(String resourceId) { @Override public EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) { - return null; + try { + Object revision = AuditReaderFactory.get(entityManager).createQuery() + .forEntitiesAtRevision(EntityDescriptor.class, Integer.valueOf(versionId)) + .add(AuditEntity.property("resourceId").eq(resourceId)) + .add(AuditEntity.revisionNumber().eq(Integer.valueOf(versionId))) + .getSingleResult(); + return entityDescriptorService.createRepresentationFromDescriptor((EntityDescriptor) revision); + } + catch (NoResultException e) { + return null; + } } } diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy index 550604777..f7b2c90b0 100644 --- a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy +++ b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator @@ -28,6 +29,8 @@ class EntityDescriptorControllerVersionEndpointsIntegrationTests extends Specifi static ALL_VERSIONS_URI = "$BASE_URI/%s/Versions" + static SPECIFIC_VERSION_URI = "$BASE_URI/%s/Versions/%s" + def "GET /api/EntityDescriptor/{resourceId}/Versions with non-existent entity descriptor"() { when: def result = getAllEntityDescriptorVersions('non-existent-ed-id', String) @@ -68,12 +71,49 @@ class EntityDescriptorControllerVersionEndpointsIntegrationTests extends Specifi result.body[0].date < result.body[1].date } + def "GET /api/EntityDescriptor{resourceId}/Versions/{version} for non existent version"() { + given: + EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser') + ed = entityDescriptorRepository.save(ed) + + when: + def result = getEntityDescriptorForVersion(ed.resourceId, '1000', EntityDescriptorRepresentation) + + then: + result.statusCodeValue == 404 + } + + def "GET /api/EntityDescriptor{resourceId}/Versions/{version} with 2 entity descriptor versions returns correct ED for specific versions"() { + given: + EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser', serviceProviderName: 'SP1') + ed = entityDescriptorRepository.save(ed) + //Will created a second version for UPDATE revision + ed.serviceProviderName = 'SP2' + entityDescriptorRepository.save(ed) + when: + def allVersions = getAllEntityDescriptorVersions(ed.resourceId, List) + def edv1 = getEntityDescriptorForVersion(ed.resourceId, allVersions.body[0].id, EntityDescriptorRepresentation) + def edv2 = getEntityDescriptorForVersion(ed.resourceId, allVersions.body[1].id, EntityDescriptorRepresentation) + + then: + edv1.statusCodeValue == 200 + edv1.body.serviceProviderName == 'SP1' + edv2.statusCodeValue == 200 + edv2.body.serviceProviderName == 'SP2' + } private getAllEntityDescriptorVersions(String resourceId, responseType) { this.restTemplate.getForEntity(resourceUriFor(ALL_VERSIONS_URI, resourceId), responseType) } + private getEntityDescriptorForVersion(String resourceId, String version, responseType) { + this.restTemplate.getForEntity(resourceUriFor(SPECIFIC_VERSION_URI, resourceId, version), responseType) + } + + private static resourceUriFor(String uriTemplate, String resourceId, String version) { + String.format(uriTemplate, resourceId, version) + } private static resourceUriFor(String uriTemplate, String resourceId) { String.format(uriTemplate, resourceId) diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy index ce1b918e7..738187741 100644 --- a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy +++ b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy @@ -75,4 +75,42 @@ class EnversEntityDescriptorVersionServiceTests extends Specification { versions[0].creator && versions[1].creator && versions[2].creator (versions[0].date < versions[1].date) && (versions[1].date < versions[2].date) } + + def "versioning service returns correct entity descriptor for version number"() { + when: 'Initial version' + EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1', createdBy: 'anonymousUser') + ed = doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + def versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + def v1EdRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, versions[0].id) + + then: + v1EdRepresentation.serviceProviderName == 'SP1' + v1EdRepresentation.id == ed.resourceId + + when: 'Update the original' + ed.serviceProviderName = 'SP2' + ed = doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + def v2EdRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, versions[1].id) + + then: + v2EdRepresentation.serviceProviderName == 'SP2' + v2EdRepresentation.id == ed.resourceId + } + + def "versioning service returns null for non existent version number"() { + when: 'Initial version' + EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1', createdBy: 'anonymousUser') + ed = doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + def edRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, '1000') + + then: + !edRepresentation + } } From a4da87d49b0938f0c08bfcd297df097de719f1c6 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Jun 2019 11:11:02 -0400 Subject: [PATCH 41/51] WIP1 --- .../admin/ui/configuration/DevConfig.groovy | 18 +++++++++--------- ...JsonSchemaValidatingControllerAdvice.groovy | 7 ++----- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy index f748de09f..9267ceeae 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy @@ -1,6 +1,5 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration - import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget @@ -12,14 +11,10 @@ import edu.internet2.tier.shibboleth.admin.ui.security.model.Role import edu.internet2.tier.shibboleth.admin.ui.security.model.User import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService import edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.context.event.ApplicationStartedEvent + import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Profile -import org.springframework.context.event.EventListener import org.springframework.stereotype.Component import org.springframework.transaction.annotation.Transactional @@ -34,14 +29,19 @@ class DevConfig { private final MetadataResolverRepository metadataResolverRepository private final EntityDescriptorRepository entityDescriptorRepository - @Autowired - private OpenSamlObjects openSamlObjects + private final OpenSamlObjects openSamlObjects + + DevConfig(UserRepository adminUserRepository, + MetadataResolverRepository metadataResolverRepository, + RoleRepository roleRepository, + EntityDescriptorRepository entityDescriptorRepository, + OpenSamlObjects openSamlObjects) { - DevConfig(UserRepository adminUserRepository, MetadataResolverRepository metadataResolverRepository, RoleRepository roleRepository, EntityDescriptorRepository entityDescriptorRepository) { this.adminUserRepository = adminUserRepository this.metadataResolverRepository = metadataResolverRepository this.roleRepository = roleRepository this.entityDescriptorRepository = entityDescriptorRepository + this.openSamlObjects = openSamlObjects } @Transactional diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy index bd3050cfd..620d2252c 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/jsonschema/RelyingPartyOverridesJsonSchemaValidatingControllerAdvice.groovy @@ -1,16 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.jsonschema -import edu.internet2.tier.shibboleth.admin.ui.controller.ErrorResponse + import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation import mjson.Json import org.springframework.beans.factory.annotation.Autowired import org.springframework.core.MethodParameter import org.springframework.http.HttpInputMessage -import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity import org.springframework.http.converter.HttpMessageConverter import org.springframework.web.bind.annotation.ControllerAdvice -import org.springframework.web.bind.annotation.ExceptionHandler import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter import javax.annotation.PostConstruct @@ -24,7 +21,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocati * * @author Dmitriy Kopylenko */ -//@ControllerAdvice +@ControllerAdvice class RelyingPartyOverridesJsonSchemaValidatingControllerAdvice extends RequestBodyAdviceAdapter { @Autowired From 22dc54acc77bdadd900d057bfd7518694e2f9b69 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Jun 2019 11:18:51 -0400 Subject: [PATCH 42/51] WIP2 --- .../shibboleth/admin/ui/configuration/DevConfig.groovy | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy index 9267ceeae..e6ef57980 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/DevConfig.groovy @@ -3,7 +3,12 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.* +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.HttpMetadataResolverAttributes +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataQueryProtocolScheme +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository From 43864f8d43bb1bb193c3689905b4f166dd4fa84c Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Jun 2019 11:27:51 -0400 Subject: [PATCH 43/51] WIP3 --- .../JPAEntityDescriptorServiceImplTests.groovy | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy index 38dfb821e..1c1778c60 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImplTests.groovy @@ -4,8 +4,20 @@ import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.ShibbolethUiApplication import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.CustomPropertiesConfiguration -import edu.internet2.tier.shibboleth.admin.ui.domain.* -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.* +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.XSAny +import edu.internet2.tier.shibboleth.admin.ui.domain.XSAnyBuilder +import edu.internet2.tier.shibboleth.admin.ui.domain.XSBoolean +import edu.internet2.tier.shibboleth.admin.ui.domain.XSBooleanBuilder +import edu.internet2.tier.shibboleth.admin.ui.domain.XSStringBuilder +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.LogoutEndpointRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.SecurityInfoRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository From 23a863d6310bf71593bfec3ebdce0184f1b2edab Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Jun 2019 11:29:57 -0400 Subject: [PATCH 44/51] WIP4 --- .../admin/ui/service/EnversEntityDescriptorVersionService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java index ec1e8ceb8..91dccd5af 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java @@ -21,7 +21,7 @@ import java.util.stream.Collectors; import static java.util.Comparator.comparing; -import static java.util.stream.Collectors.*; +import static java.util.stream.Collectors.toList; /** * Hibernate Envers based implementation of {@link EntityDescriptorVersionService}. From 15db654cdcb00b5ec75e35dd62a32de8557c5819 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Wed, 12 Jun 2019 13:52:52 -0400 Subject: [PATCH 45/51] WIP5 --- backend/build.gradle | 26 + ...lerVersionEndpointsIntegrationTests.groovy | 118 ++++ ...tityDescriptorEnversVersioningTests.groovy | 609 ++++++++++++++++++ ...verEntityBasicEnversVersioningTests.groovy | 104 +++ ...EntityDescriptorVersionServiceTests.groovy | 114 ++++ settings.gradle | 2 +- 6 files changed, 972 insertions(+), 1 deletion(-) create mode 100644 backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy create mode 100644 backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy create mode 100644 backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy create mode 100644 backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy diff --git a/backend/build.gradle b/backend/build.gradle index 4e5822e2e..6dd21a097 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -44,6 +44,13 @@ configurations { integrationTestRuntime { extendsFrom testRuntime } + enversTestCompile { + extendsFrom testCompile + + } + enversTestRuntime { + extendsFrom testRuntime + } } processResources.dependsOn(':ui:npm_run_buildProd') @@ -197,6 +204,13 @@ sourceSets { srcDir 'src/integration/resources' } } + enversTest { + groovy { + srcDirs = ['src/enversTest/groovy'] + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + } + } } task integrationTest(type: Test) { @@ -210,6 +224,18 @@ task integrationTest(type: Test) { systemProperties['user.dir'] = workingDir } +task enversTest(type: Test) { + group = 'verification' + description = 'Run tests pertaing to envers versioning engine' + testClassesDirs = sourceSets.enversTest.output.classesDirs + classpath = sourceSets.enversTest.runtimeClasspath + systemProperties = System.properties + systemProperties['user.dir'] = workingDir +} +test.finalizedBy enversTest + + + task generateSources { inputs.dir('src/main/templates') inputs.files fileTree('src/main/resources') { diff --git a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy new file mode 100644 index 000000000..705f50021 --- /dev/null +++ b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy @@ -0,0 +1,118 @@ +package edu.internet2.tier.shibboleth.admin.ui.controller + +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.test.web.client.TestRestTemplate +import org.springframework.test.context.ActiveProfiles +import spock.lang.Specification + +/** + * @author Dmitriy Kopylenko + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles(['no-auth', 'dev']) +class EntityDescriptorControllerVersionEndpointsIntegrationTests extends Specification { + + @Autowired + private TestRestTemplate restTemplate + + @Autowired + EntityDescriptorRepository entityDescriptorRepository + + static BASE_URI = '/api/EntityDescriptor' + + static ALL_VERSIONS_URI = "$BASE_URI/%s/Versions" + + static SPECIFIC_VERSION_URI = "$BASE_URI/%s/Versions/%s" + + def "GET /api/EntityDescriptor/{resourceId}/Versions with non-existent entity descriptor"() { + when: + def result = getAllEntityDescriptorVersions('non-existent-ed-id', String) + + then: + result.statusCodeValue == 404 + } + + def "GET /api/EntityDescriptor{resourceId}/Versions with 1 entity descriptor version"() { + given: + EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser') + entityDescriptorRepository.save(ed) + + when: + def result = getAllEntityDescriptorVersions(ed.resourceId, List) + + then: + result.statusCodeValue == 200 + result.body.size == 1 + result.body[0].id && result.body[0].creator && result.body[0].date + } + + def "GET /api/EntityDescriptor{resourceId}/Versions with 2 entity descriptor versions"() { + given: + EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser') + ed = entityDescriptorRepository.save(ed) + //Will created a second version for UPDATE revision + ed.serviceEnabled = true + entityDescriptorRepository.save(ed) + + when: + def result = getAllEntityDescriptorVersions(ed.resourceId, List) + + then: + result.statusCodeValue == 200 + result.body.size == 2 + result.body[0].id < result.body[1].id + result.body[0].date < result.body[1].date + } + + def "GET /api/EntityDescriptor{resourceId}/Versions/{version} for non existent version"() { + given: + EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser') + ed = entityDescriptorRepository.save(ed) + + when: + def result = getEntityDescriptorForVersion(ed.resourceId, '1000', EntityDescriptorRepresentation) + + then: + result.statusCodeValue == 404 + } + + def "GET /api/EntityDescriptor{resourceId}/Versions/{version} with 2 entity descriptor versions returns correct ED for specific versions"() { + given: + EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser', serviceProviderName: 'SP1') + ed = entityDescriptorRepository.save(ed) + //Will created a second version for UPDATE revision + ed.serviceProviderName = 'SP2' + entityDescriptorRepository.save(ed) + + when: + def allVersions = getAllEntityDescriptorVersions(ed.resourceId, List) + def edv1 = getEntityDescriptorForVersion(ed.resourceId, allVersions.body[0].id, EntityDescriptorRepresentation) + def edv2 = getEntityDescriptorForVersion(ed.resourceId, allVersions.body[1].id, EntityDescriptorRepresentation) + + then: + edv1.statusCodeValue == 200 + edv1.body.serviceProviderName == 'SP1' + edv2.statusCodeValue == 200 + edv2.body.serviceProviderName == 'SP2' + } + + private getAllEntityDescriptorVersions(String resourceId, responseType) { + this.restTemplate.getForEntity(resourceUriFor(ALL_VERSIONS_URI, resourceId), responseType) + } + + private getEntityDescriptorForVersion(String resourceId, String version, responseType) { + this.restTemplate.getForEntity(resourceUriFor(SPECIFIC_VERSION_URI, resourceId, version), responseType) + } + + private static resourceUriFor(String uriTemplate, String resourceId, String version) { + String.format(uriTemplate, resourceId, version) + } + + private static resourceUriFor(String uriTemplate, String resourceId) { + String.format(uriTemplate, resourceId) + } +} diff --git a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy new file mode 100644 index 000000000..f8f97b0fc --- /dev/null +++ b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -0,0 +1,609 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository.envers + +import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration +import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.domain.EntityScan +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.context.ContextConfiguration +import org.springframework.transaction.PlatformTransactionManager +import spock.lang.Specification + +import javax.persistence.EntityManager + +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.* + +/** + * Testing entity descriptor envers versioning + */ +@DataJpaTest +@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, SearchConfiguration, TestConfiguration]) +@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) +@EntityScan("edu.internet2.tier.shibboleth.admin.ui") +class EntityDescriptorEnversVersioningTests extends Specification { + + @Autowired + EntityDescriptorRepository entityDescriptorRepository + + @Autowired + EntityDescriptorService entityDescriptorService + + @Autowired + EntityManager entityManager + + @Autowired + PlatformTransactionManager txMgr + + @Autowired + OpenSamlObjects openSamlObjects + + def "test versioning with contact persons"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, ContactPerson.name, GivenName.name, EmailAddress.name] + + when: + def ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] + it + } + def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 1 + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].givenName.name == 'name' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].emailAddresses[0].address == 'test@test' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'administrative', name: 'nameUPDATED', emailAddress: 'test@test')] + it + } + entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + then: + entityDescriptorHistory.size() == 2 + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED2', emailAddress: 'test@test.com')] + it + } + entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, + entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 3 + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].givenName.name == 'nameUPDATED2' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].emailAddresses[0].address == 'test@test.com' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).timestamp > 0L + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 2).sort() == expectedModifiedPersistentEntities.sort() + + //Also make sure we have our original revision + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + + } + + def "test versioning with organization"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + Organization.name, + OrganizationDisplayName.name, + OrganizationName.name, + OrganizationURL.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.organization = new OrganizationRepresentation(name: 'org', displayName: 'display org', url: 'http://org.edu') + it + } + def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + then: + entityDescriptorHistory.size() == 1 + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.organization = new OrganizationRepresentation(name: 'orgUpdated', displayName: 'display org Updated', url: 'http://org2.edu') + it + } + entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + then: + entityDescriptorHistory.size() == 2 + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.organizationNames[0].value == 'orgUpdated' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.displayNames[0].value == 'display org Updated' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.URLs[0].value == 'http://org2.edu' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the original revision is intact + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + } + + def "test versioning with sp sso descriptor"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + NameIDFormat.name, + SPSSODescriptor.name] + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { + it.protocolSupportEnum = 'SAML 1.1' + it.nameIdFormats = ['format'] + it + } + it + } + def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 1 + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { + it.protocolSupportEnum = 'SAML 1.1, SAML 2' + it.nameIdFormats = ['formatUPDATED'] + it + } + it + } + + entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + then: + entityDescriptorHistory.size() == 2 + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the original revision is intact + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + } + + def "test versioning with uiInfo"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + Description.name, + DisplayName.name, + SPSSODescriptor.name, + Extensions.name, + InformationURL.name, + Logo.name, + PrivacyStatementURL.name, + UIInfo.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.mdui = new MduiRepresentation().with { + it.displayName = 'Initial display name' + it.informationUrl = 'http://info' + it.privacyStatementUrl = 'http://privacy' + it.description = 'Initial desc' + it.logoUrl = 'http://logo' + it.logoHeight = 20 + it.logoWidth = 30 + it + } + it + } + def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + //Groovy FTW - able to call any private methods on ANY object. Get first revision + UIInfo uiinfo = entityDescriptorService.getUIInfo(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + then: + entityDescriptorHistory.size() == 1 + uiinfo.displayNames[0].value == 'Initial display name' + uiinfo.informationURLs[0].value == 'http://info' + uiinfo.privacyStatementURLs[0].value == 'http://privacy' + uiinfo.descriptions[0].value == 'Initial desc' + uiinfo.logos[0].URL == 'http://logo' + uiinfo.logos[0].height == 20 + uiinfo.logos[0].width == 30 + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.mdui = new MduiRepresentation().with { + it.displayName = 'Display name UPDATED' + it.informationUrl = 'http://info.updated' + it.privacyStatementUrl = 'http://privacy.updated' + it.description = 'Desc UPDATED' + it.logoUrl = 'http://logo.updated' + it.logoHeight = 30 + it.logoWidth = 40 + it + } + it + } + entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + //Get second revision + uiinfo = entityDescriptorService.getUIInfo(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + //And initial revision + def uiinfoInitialRevision = entityDescriptorService.getUIInfo(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + then: + entityDescriptorHistory.size() == 2 + uiinfo.displayNames[0].value == 'Display name UPDATED' + uiinfo.informationURLs[0].value == 'http://info.updated' + uiinfo.privacyStatementURLs[0].value == 'http://privacy.updated' + uiinfo.descriptions[0].value == 'Desc UPDATED' + uiinfo.logos[0].URL == 'http://logo.updated' + uiinfo.logos[0].height == 30 + uiinfo.logos[0].width == 40 + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial revision is still intact + uiinfoInitialRevision.displayNames[0].value == 'Initial display name' + uiinfoInitialRevision.informationURLs[0].value == 'http://info' + uiinfoInitialRevision.privacyStatementURLs[0].value == 'http://privacy' + uiinfoInitialRevision.descriptions[0].value == 'Initial desc' + uiinfoInitialRevision.logos[0].URL == 'http://logo' + uiinfoInitialRevision.logos[0].height == 20 + uiinfoInitialRevision.logos[0].width == 30 + } + + def "test versioning with security"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + KeyDescriptor.name, + KeyInfo.name, + SPSSODescriptor.name, + X509Certificate.name, + X509Data.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.securityInfo = new SecurityInfoRepresentation().with { + it.authenticationRequestsSigned = true + it.x509CertificateAvailable = true + it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue')] + it + } + it + } + + def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + //Get initial revision + SPSSODescriptor spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + + KeyDescriptor keyDescriptor = spssoDescriptor.keyDescriptors[0] + X509Certificate x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] + + then: + entityDescriptorHistory.size() == 1 + spssoDescriptor.isAuthnRequestsSigned() + keyDescriptor.name == 'sign' + keyDescriptor.usageType == 'signing' + x509cert.value == 'signingValue' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.securityInfo = new SecurityInfoRepresentation().with { + it.authenticationRequestsSigned = false + it.x509CertificateAvailable = true + it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue'), + new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'encrypt', type: 'encryption', value: 'encryptionValue')] + it + } + it + } + + entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + + //Get second revision + SPSSODescriptor spssoDescriptor_second = entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) + + KeyDescriptor keyDescriptor_second1 = spssoDescriptor_second.keyDescriptors[0] + X509Certificate x509cert_second1 = keyDescriptor_second1.keyInfo.x509Datas[0].x509Certificates[0] + KeyDescriptor keyDescriptor_second2 = spssoDescriptor_second.keyDescriptors[1] + X509Certificate x509cert_second2 = keyDescriptor_second2.keyInfo.x509Datas[0].x509Certificates[0] + + + //Get initial revision + spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + + keyDescriptor = spssoDescriptor.keyDescriptors[0] + x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] + + then: + entityDescriptorHistory.size() == 2 + !spssoDescriptor_second.isAuthnRequestsSigned() + keyDescriptor_second1.name == 'sign' + keyDescriptor_second1.usageType == 'signing' + keyDescriptor_second2.name == 'encrypt' + keyDescriptor_second2.usageType == 'encryption' + x509cert_second1.value == 'signingValue' + x509cert_second2.value == 'encryptionValue' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial version is intact + spssoDescriptor.keyDescriptors.size() == 1 + spssoDescriptor.isAuthnRequestsSigned() + keyDescriptor.name == 'sign' + keyDescriptor.usageType == 'signing' + x509cert.value == 'signingValue' + } + + def "test versioning ACS"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + SPSSODescriptor.name, + AssertionConsumerService.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.assertionConsumerServices = [ + new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] + it + } + + def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + AssertionConsumerService acs = spssoDescriptor.assertionConsumerServices[0] + + then: + entityDescriptorHistory.size() == 1 + !acs.isDefault() + acs.location == 'http://acs' + acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + + when: + representation = new EntityDescriptorRepresentation().with { + it.assertionConsumerServices = [ + new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs.updated', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS', makeDefault: true), + new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs2', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] + it + } + + entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor2 = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) + def (acs1, acs2) = [spssoDescriptor2.assertionConsumerServices[0], spssoDescriptor2.assertionConsumerServices[1]] + + //Initial revision + spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + acs = spssoDescriptor.assertionConsumerServices[0] + + then: + entityDescriptorHistory.size() == 2 + acs1.isDefault() + !acs2.isDefault() + acs1.location == 'http://acs.updated' + acs1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' + acs2.location == 'http://acs2' + acs2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial revision is intact + !acs.isDefault() + acs.location == 'http://acs' + acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + } + + def "test versioning logout"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + SPSSODescriptor.name, + SingleLogoutService.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] + it + } + + def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + SingleLogoutService slo = spssoDescriptor.singleLogoutServices[0] + + then: + entityDescriptorHistory.size() == 1 + slo.location == 'http://logout' + slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout.updated', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS'), + new LogoutEndpointRepresentation(url: 'http://logout2', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] + it + } + + entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + SPSSODescriptor spssoDescriptor2 = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + def (slo1, slo2) = [spssoDescriptor2.singleLogoutServices[0], spssoDescriptor2.singleLogoutServices[1]] + + //Initial revision + spssoDescriptor = + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + slo = spssoDescriptor.singleLogoutServices[0] + + then: + entityDescriptorHistory.size() == 2 + slo1.location == 'http://logout.updated' + slo1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' + slo2.location == 'http://logout2' + slo2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial version is intact + slo.location == 'http://logout' + slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' + } + + def "test versioning relying party overrides"() { + setup: + def expectedModifiedPersistentEntities = [EntityDescriptor.name, + EntityAttributes.name, + Extensions.name, + Attribute.name, + XSBoolean.name, + XSString.name] + + when: + EntityDescriptor ed = new EntityDescriptor() + def representation = new EntityDescriptorRepresentation().with { + it.relyingPartyOverrides = [signAssertion: true] + it.attributeRelease = ['attr1'] + it + } + + def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + EntityAttributes attrs = entityDescriptorService.getEntityAttributes(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + then: + entityDescriptorHistory.size() == 1 + attrs.attributes[0].attributeValues[0].storedValue == 'true' + attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + + when: + representation = new EntityDescriptorRepresentation().with { + it.relyingPartyOverrides = [signAssertion: false] + it.attributeRelease = ['attr1', 'attr2'] + it + } + + entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorRepository, + txMgr, + entityManager) + + EntityAttributes attrs2 = entityDescriptorService.getEntityAttributes(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + + //Initial revision + attrs = entityDescriptorService.getEntityAttributes(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + + expectedModifiedPersistentEntities = [EntityDescriptor.name, + EntityAttributes.name, + Attribute.name, + XSString.name] + then: + entityDescriptorHistory.size() == 2 + attrs2.attributes[0].attributeValues[0].xsStringvalue == 'attr1' + attrs2.attributes[0].attributeValues[1].xsStringvalue == 'attr2' + edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + + //Check the initial revision is intact + attrs.attributes[0].attributeValues[0].storedValue == 'true' + attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' + attrs.attributes[1].attributeValues[1] == null + } +} diff --git a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy new file mode 100644 index 000000000..f8ac3b431 --- /dev/null +++ b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy @@ -0,0 +1,104 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository.envers + +import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter +import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository +import org.hibernate.envers.AuditReaderFactory +import org.hibernate.envers.query.AuditQuery +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.domain.EntityScan +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.context.ContextConfiguration +import org.springframework.transaction.PlatformTransactionManager +import org.springframework.transaction.support.DefaultTransactionDefinition +import spock.lang.Specification + +import javax.persistence.EntityManager + +/** + * Testing metadata resolvers basic versioning by envers is functioning. + */ +@DataJpaTest +@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration]) +@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) +@EntityScan("edu.internet2.tier.shibboleth.admin.ui") +class MetadataResolverEntityBasicEnversVersioningTests extends Specification { + + @Autowired + MetadataResolverRepository metadataResolverRepository + + @Autowired + EntityManager entityManager + + @Autowired + PlatformTransactionManager txMgr + + def "test basic audit and version data is created when persisting base metadata resolver with envers enabled"() { + when: + MetadataResolver mdr = doInExplicitTransaction { + metadataResolverRepository.save(create {new MetadataResolver()}) + } + def metadataResolverHistory = resolverHistory() + + then: + metadataResolverHistory.size() == 1 + + when: + def rev = metadataResolverHistory[0] + + then: + rev[1].principalUserName == 'anonymousUser' + + when: + mdr.name = 'Updated' + doInExplicitTransaction { + metadataResolverRepository.save(mdr) + } + metadataResolverHistory = resolverHistory() + + then: + metadataResolverHistory.size == 2 + } + + private resolverHistory() { + def auditReader = AuditReaderFactory.get(entityManager) + AuditQuery auditQuery = auditReader + .createQuery() + .forRevisionsOfEntity(MetadataResolver, false, true) + auditQuery.resultList + + } + + private static create(Closure concreteResolverSupplier) { + MetadataResolver resolver = concreteResolverSupplier() + resolver.with { + it.name = "testme" + it.metadataFilters.add(new EntityAttributesFilter().with { + it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with { + it.entityAttributesFilterTargetType = EntityAttributesFilterTarget.EntityAttributesFilterTargetType.ENTITY + it.value = ["hola"] + return it + } + return it + }) + } + resolver + } + + //This explicit low level transaction dance is required in order to verify history/version data that envers + //writes out only after the explicit transaction is committed, therefore making it impossible to verify within the main tx + //boundary of the test method which commits tx only after an execution of the test method. This let's us explicitly + //start/commit transaction making envers data written out and verifiable + private doInExplicitTransaction(Closure uow) { + def txStatus = txMgr.getTransaction(new DefaultTransactionDefinition(org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW)) + def entity = uow() + txMgr.commit(txStatus) + entity + } +} diff --git a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy new file mode 100644 index 000000000..58cd83704 --- /dev/null +++ b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy @@ -0,0 +1,114 @@ +package edu.internet2.tier.shibboleth.admin.ui.service.envers + + +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.domain.EntityScan +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.test.context.ContextConfiguration +import org.springframework.transaction.PlatformTransactionManager +import spock.lang.Specification + +import java.time.LocalDateTime + +@DataJpaTest +@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration, EntitiesVersioningConfiguration]) +@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) +@EntityScan("edu.internet2.tier.shibboleth.admin.ui") +class EnversEntityDescriptorVersionServiceTests extends Specification { + + @Autowired + EntityDescriptorVersionService entityDescriptorVersionService + + @Autowired + EntityDescriptorRepository entityDescriptorRepository + + @Autowired + EntityDescriptorService entityDescriptorService + + @Autowired + PlatformTransactionManager txMgr + + def "versioning service returns correct number of versions sorted by modified date in natural order"() { + when: 'Initial version' + EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1') + ed = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + def versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + + then: + versions.size() == 1 + versions[0].id + versions[0].creator + versions[0].date < LocalDateTime.now() + + when: 'Second version' + ed.serviceProviderName = 'SP2' + ed = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + + then: + versions.size() == 2 + versions[0].id && versions[1].id + versions[0].creator && versions[1].creator + versions[0].date < versions[1].date + + when: 'Third version' + ed.serviceProviderName = 'SP3' + ed = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + + then: + versions.size() == 3 + versions[0].id && versions[1].id && versions[2].id + versions[0].creator && versions[1].creator && versions[2].creator + (versions[0].date < versions[1].date) && (versions[1].date < versions[2].date) + } + + def "versioning service returns correct entity descriptor for version number"() { + when: 'Initial version' + EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1', createdBy: 'anonymousUser') + ed = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + def versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + def v1EdRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, versions[0].id) + + then: + v1EdRepresentation.serviceProviderName == 'SP1' + v1EdRepresentation.id == ed.resourceId + + when: 'Update the original' + ed.serviceProviderName = 'SP2' + ed = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) + def v2EdRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, versions[1].id) + + then: + v2EdRepresentation.serviceProviderName == 'SP2' + v2EdRepresentation.id == ed.resourceId + } + + def "versioning service returns null for non existent version number"() { + when: 'Initial version' + EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1', createdBy: 'anonymousUser') + ed = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction(txMgr) { + entityDescriptorRepository.save(ed) + } + def edRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, '1000') + + then: + !edRepresentation + } +} diff --git a/settings.gradle b/settings.gradle index ba298e3de..b3ab3e757 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include 'backend', 'ui', 'pac4j-module', 'envers-tests-module' +include 'backend', 'ui', 'pac4j-module' From f08592315196250b0e0c3a6b75ea6779a409427a Mon Sep 17 00:00:00 2001 From: Jj! Date: Wed, 12 Jun 2019 16:39:43 -0500 Subject: [PATCH 46/51] [SHIBUI-1262] refigure the build.gradle add missing imports --- backend/build.gradle | 70 ++++++++++--------- ...tityDescriptorEnversVersioningTests.groovy | 18 ++++- ...EntityDescriptorVersionServiceTests.groovy | 6 +- 3 files changed, 57 insertions(+), 37 deletions(-) diff --git a/backend/build.gradle b/backend/build.gradle index 6dd21a097..3af60585e 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -44,12 +44,35 @@ configurations { integrationTestRuntime { extendsFrom testRuntime } - enversTestCompile { - extendsFrom testCompile +} + +def generatedSrcDir = new File(buildDir, 'generated/src/main/java') +sourceSets { + main { + groovy { + srcDirs = ['src/main/groovy', 'src/main/java', generatedSrcDir] + } + java { + srcDirs = [] + } } - enversTestRuntime { - extendsFrom testRuntime + integrationTest { + groovy { + srcDirs = ['src/integration/groovy'] + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + } + resources { + srcDir 'src/integration/resources' + } + } + + enversTest { + groovy { + srcDir 'src/enversTest/groovy' + } + resources.srcDir 'src/enversTest/resources' } } @@ -181,36 +204,14 @@ dependencies { // Envers for persistent entities versioning compile 'org.hibernate:hibernate-envers' -} -def generatedSrcDir = new File(buildDir, 'generated/src/main/java') + enversTestCompile sourceSets.main.output + enversTestCompile sourceSets.test.output + enversTestCompile configurations.compile + enversTestCompile configurations.testCompile -sourceSets { - main { - groovy { - srcDirs = ['src/main/groovy', 'src/main/java', generatedSrcDir] - } - java { - srcDirs = [] - } - } - integrationTest { - groovy { - srcDirs = ['src/integration/groovy'] - compileClasspath += main.output + test.output - runtimeClasspath += main.output + test.output - } - resources { - srcDir 'src/integration/resources' - } - } - enversTest { - groovy { - srcDirs = ['src/enversTest/groovy'] - compileClasspath += main.output + test.output - runtimeClasspath += main.output + test.output - } - } + enversTestRuntime configurations.runtime + enversTestRuntime configurations.testRuntime } task integrationTest(type: Test) { @@ -232,9 +233,10 @@ task enversTest(type: Test) { systemProperties = System.properties systemProperties['user.dir'] = workingDir } -test.finalizedBy enversTest - +check { + dependsOn enversTest +} task generateSources { inputs.dir('src/main/templates') diff --git a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index f8f97b0fc..579620b44 100644 --- a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -4,6 +4,22 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfigurat import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.AssertionConsumerService +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributes +import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.KeyDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.SPSSODescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.SingleLogoutService +import edu.internet2.tier.shibboleth.admin.ui.domain.UIInfo +import edu.internet2.tier.shibboleth.admin.ui.domain.X509Certificate +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.LogoutEndpointRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.MduiRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.SecurityInfoRepresentation +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService @@ -17,8 +33,6 @@ import spock.lang.Specification import javax.persistence.EntityManager -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.* - /** * Testing entity descriptor envers versioning */ diff --git a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy index 58cd83704..d88a604f3 100644 --- a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy +++ b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy @@ -1,6 +1,10 @@ package edu.internet2.tier.shibboleth.admin.ui.service.envers - +import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.EntitiesVersioningConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration +import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService From f8481abc6ff4380ef808b54ed58d544b193712c5 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 13 Jun 2019 09:30:40 -0400 Subject: [PATCH 47/51] Fix tests --- ...tityDescriptorEnversVersioningTests.groovy | 222 ++++--- envers-tests-module/build.gradle | 34 - ....ui.envers-tests-module.main.kotlin_module | Bin 16 -> 0 bytes ...lerVersionEndpointsIntegrationTests.groovy | 121 ---- ...tityDescriptorEnversVersioningTests.groovy | 613 ------------------ ...verEntityBasicEnversVersioningTests.groovy | 106 --- ...EntityDescriptorVersionServiceTests.groovy | 116 ---- 7 files changed, 123 insertions(+), 1089 deletions(-) delete mode 100644 envers-tests-module/build.gradle delete mode 100644 envers-tests-module/out/test/classes/META-INF/edu.internet2.tier.shibboleth.admin.ui.envers-tests-module.main.kotlin_module delete mode 100644 envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy delete mode 100644 envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy delete mode 100644 envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy delete mode 100644 envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy diff --git a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy index 579620b44..05e3ad139 100644 --- a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy @@ -5,13 +5,32 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.Internationalization import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.AssertionConsumerService +import edu.internet2.tier.shibboleth.admin.ui.domain.Attribute +import edu.internet2.tier.shibboleth.admin.ui.domain.ContactPerson +import edu.internet2.tier.shibboleth.admin.ui.domain.Description +import edu.internet2.tier.shibboleth.admin.ui.domain.DisplayName +import edu.internet2.tier.shibboleth.admin.ui.domain.EmailAddress import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributes import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.Extensions +import edu.internet2.tier.shibboleth.admin.ui.domain.GivenName +import edu.internet2.tier.shibboleth.admin.ui.domain.InformationURL import edu.internet2.tier.shibboleth.admin.ui.domain.KeyDescriptor +import edu.internet2.tier.shibboleth.admin.ui.domain.KeyInfo +import edu.internet2.tier.shibboleth.admin.ui.domain.Logo +import edu.internet2.tier.shibboleth.admin.ui.domain.NameIDFormat +import edu.internet2.tier.shibboleth.admin.ui.domain.Organization +import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationDisplayName +import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationName +import edu.internet2.tier.shibboleth.admin.ui.domain.OrganizationURL +import edu.internet2.tier.shibboleth.admin.ui.domain.PrivacyStatementURL import edu.internet2.tier.shibboleth.admin.ui.domain.SPSSODescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.SingleLogoutService import edu.internet2.tier.shibboleth.admin.ui.domain.UIInfo import edu.internet2.tier.shibboleth.admin.ui.domain.X509Certificate +import edu.internet2.tier.shibboleth.admin.ui.domain.X509Data +import edu.internet2.tier.shibboleth.admin.ui.domain.XSBoolean +import edu.internet2.tier.shibboleth.admin.ui.domain.XSString import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation @@ -33,6 +52,11 @@ import spock.lang.Specification import javax.persistence.EntityManager +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex +import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor + /** * Testing entity descriptor envers versioning */ @@ -67,44 +91,44 @@ class EntityDescriptorEnversVersioningTests extends Specification { it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] it } - def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 1 - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].givenName.name == 'name' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].emailAddresses[0].address == 'test@test' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].givenName.name == 'name' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].emailAddresses[0].address == 'test@test' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { it.contacts = [new ContactRepresentation(type: 'administrative', name: 'nameUPDATED', emailAddress: 'test@test')] it } - entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 2 - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED2', emailAddress: 'test@test.com')] it } - entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, @@ -112,19 +136,19 @@ class EntityDescriptorEnversVersioningTests extends Specification { then: entityDescriptorHistory.size() == 3 - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].givenName.name == 'nameUPDATED2' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].emailAddresses[0].address == 'test@test.com' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).timestamp > 0L - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 2).sort() == expectedModifiedPersistentEntities.sort() + getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].givenName.name == 'nameUPDATED2' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER + getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].emailAddresses[0].address == 'test@test.com' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 2).sort() == expectedModifiedPersistentEntities.sort() //Also make sure we have our original revision - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L } @@ -142,43 +166,43 @@ class EntityDescriptorEnversVersioningTests extends Specification { it.organization = new OrganizationRepresentation(name: 'org', displayName: 'display org', url: 'http://org.edu') it } - def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 1 - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { it.organization = new OrganizationRepresentation(name: 'orgUpdated', displayName: 'display org Updated', url: 'http://org2.edu') it } - entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 2 - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.organizationNames[0].value == 'orgUpdated' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.displayNames[0].value == 'display org Updated' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.URLs[0].value == 'http://org2.edu' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.organizationNames[0].value == 'orgUpdated' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.displayNames[0].value == 'display org Updated' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.URLs[0].value == 'http://org2.edu' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the original revision is intact - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L } def "test versioning with sp sso descriptor"() { @@ -196,19 +220,19 @@ class EntityDescriptorEnversVersioningTests extends Specification { } it } - def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 1 - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -220,26 +244,26 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) then: entityDescriptorHistory.size() == 2 - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the original revision is intact - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' + getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' + getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L } def "test versioning with uiInfo"() { @@ -269,13 +293,13 @@ class EntityDescriptorEnversVersioningTests extends Specification { } it } - def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) //Groovy FTW - able to call any private methods on ANY object. Get first revision - UIInfo uiinfo = entityDescriptorService.getUIInfo(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + UIInfo uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) then: entityDescriptorHistory.size() == 1 @@ -286,7 +310,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { uiinfo.logos[0].URL == 'http://logo' uiinfo.logos[0].height == 20 uiinfo.logos[0].width == 30 - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -302,15 +326,15 @@ class EntityDescriptorEnversVersioningTests extends Specification { } it } - entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) //Get second revision - uiinfo = entityDescriptorService.getUIInfo(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) //And initial revision - def uiinfoInitialRevision = entityDescriptorService.getUIInfo(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + def uiinfoInitialRevision = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) then: entityDescriptorHistory.size() == 2 @@ -321,7 +345,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { uiinfo.logos[0].URL == 'http://logo.updated' uiinfo.logos[0].height == 30 uiinfo.logos[0].width == 40 - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial revision is still intact uiinfoInitialRevision.displayNames[0].value == 'Initial display name' @@ -354,14 +378,14 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) //Get initial revision SPSSODescriptor spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) KeyDescriptor keyDescriptor = spssoDescriptor.keyDescriptors[0] X509Certificate x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] @@ -372,7 +396,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { keyDescriptor.name == 'sign' keyDescriptor.usageType == 'signing' x509cert.value == 'signingValue' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -386,14 +410,14 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) //Get second revision - SPSSODescriptor spssoDescriptor_second = entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) + SPSSODescriptor spssoDescriptor_second = entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) KeyDescriptor keyDescriptor_second1 = spssoDescriptor_second.keyDescriptors[0] X509Certificate x509cert_second1 = keyDescriptor_second1.keyInfo.x509Datas[0].x509Certificates[0] @@ -403,7 +427,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { //Get initial revision spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) keyDescriptor = spssoDescriptor.keyDescriptors[0] x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] @@ -417,7 +441,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { keyDescriptor_second2.usageType == 'encryption' x509cert_second1.value == 'signingValue' x509cert_second2.value == 'encryptionValue' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial version is intact spssoDescriptor.keyDescriptors.size() == 1 @@ -441,13 +465,13 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) SPSSODescriptor spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) AssertionConsumerService acs = spssoDescriptor.assertionConsumerServices[0] then: @@ -455,7 +479,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { !acs.isDefault() acs.location == 'http://acs' acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: @@ -466,18 +490,18 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) SPSSODescriptor spssoDescriptor2 = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) def (acs1, acs2) = [spssoDescriptor2.assertionConsumerServices[0], spssoDescriptor2.assertionConsumerServices[1]] //Initial revision spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) acs = spssoDescriptor.assertionConsumerServices[0] then: @@ -488,7 +512,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { acs1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' acs2.location == 'http://acs2' acs2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial revision is intact !acs.isDefault() @@ -509,20 +533,20 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) SPSSODescriptor spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) SingleLogoutService slo = spssoDescriptor.singleLogoutServices[0] then: entityDescriptorHistory.size() == 1 slo.location == 'http://logout' slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -531,18 +555,18 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) SPSSODescriptor spssoDescriptor2 = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) def (slo1, slo2) = [spssoDescriptor2.singleLogoutServices[0], spssoDescriptor2.singleLogoutServices[1]] //Initial revision spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) slo = spssoDescriptor.singleLogoutServices[0] then: @@ -551,7 +575,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { slo1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' slo2.location == 'http://logout2' slo2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial version is intact slo.location == 'http://logout' @@ -575,18 +599,18 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - def entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) - EntityAttributes attrs = entityDescriptorService.getEntityAttributes(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + EntityAttributes attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) then: entityDescriptorHistory.size() == 1 attrs.attributes[0].attributeValues[0].storedValue == 'true' attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() when: representation = new EntityDescriptorRepresentation().with { @@ -595,15 +619,15 @@ class EntityDescriptorEnversVersioningTests extends Specification { it } - entityDescriptorHistory = edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, + entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, entityDescriptorRepository, txMgr, entityManager) - EntityAttributes attrs2 = entityDescriptorService.getEntityAttributes(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) + EntityAttributes attrs2 = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) //Initial revision - attrs = entityDescriptorService.getEntityAttributes(edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) + attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) expectedModifiedPersistentEntities = [EntityDescriptor.name, EntityAttributes.name, @@ -613,7 +637,7 @@ class EntityDescriptorEnversVersioningTests extends Specification { entityDescriptorHistory.size() == 2 attrs2.attributes[0].attributeValues[0].xsStringvalue == 'attr1' attrs2.attributes[0].attributeValues[1].xsStringvalue == 'attr2' - edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() + getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() //Check the initial revision is intact attrs.attributes[0].attributeValues[0].storedValue == 'true' diff --git a/envers-tests-module/build.gradle b/envers-tests-module/build.gradle deleted file mode 100644 index 975da5e36..000000000 --- a/envers-tests-module/build.gradle +++ /dev/null @@ -1,34 +0,0 @@ -plugins { - id 'groovy' - id 'jacoco' - id 'org.springframework.boot' version '2.0.0.RELEASE' apply false - id 'io.spring.dependency-management' version '1.0.6.RELEASE' -} - -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - -repositories { - jcenter() - maven { - url 'https://build.shibboleth.net/nexus/content/groups/public' - artifactUrls = ['https://build.shibboleth.net/nexus/content/repositories/thirdparty-snapshots'] - } -} - -dependencyManagement { - imports { - mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES - } -} - -dependencies { - - compile project(':backend') - //testCompile project(':backend') - testCompile project(':backend').sourceSets.test.output - //testCompile "org.springframework.boot:spring-boot-starter-data-jpa" - testCompile "org.springframework.boot:spring-boot-starter-test" - testCompile "org.spockframework:spock-core:1.1-groovy-2.4" - testCompile "org.spockframework:spock-spring:1.1-groovy-2.4" -} diff --git a/envers-tests-module/out/test/classes/META-INF/edu.internet2.tier.shibboleth.admin.ui.envers-tests-module.main.kotlin_module b/envers-tests-module/out/test/classes/META-INF/edu.internet2.tier.shibboleth.admin.ui.envers-tests-module.main.kotlin_module deleted file mode 100644 index 2983af70661ad375cc499ebc4da5a68ca46c532e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16 RcmZQzU|?ooU|@t|egFVe02KfL diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy deleted file mode 100644 index f7b2c90b0..000000000 --- a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerVersionEndpointsIntegrationTests.groovy +++ /dev/null @@ -1,121 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.controller - -import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation -import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository -import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository -import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator -import edu.internet2.tier.shibboleth.admin.util.AttributeUtility -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.boot.test.web.client.TestRestTemplate -import org.springframework.test.context.ActiveProfiles -import spock.lang.Specification - -/** - * @author Dmitriy Kopylenko - */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ActiveProfiles(['no-auth', 'dev']) -class EntityDescriptorControllerVersionEndpointsIntegrationTests extends Specification { - - @Autowired - private TestRestTemplate restTemplate - - @Autowired - EntityDescriptorRepository entityDescriptorRepository - - static BASE_URI = '/api/EntityDescriptor' - - static ALL_VERSIONS_URI = "$BASE_URI/%s/Versions" - - static SPECIFIC_VERSION_URI = "$BASE_URI/%s/Versions/%s" - - def "GET /api/EntityDescriptor/{resourceId}/Versions with non-existent entity descriptor"() { - when: - def result = getAllEntityDescriptorVersions('non-existent-ed-id', String) - - then: - result.statusCodeValue == 404 - } - - def "GET /api/EntityDescriptor{resourceId}/Versions with 1 entity descriptor version"() { - given: - EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser') - entityDescriptorRepository.save(ed) - - when: - def result = getAllEntityDescriptorVersions(ed.resourceId, List) - - then: - result.statusCodeValue == 200 - result.body.size == 1 - result.body[0].id && result.body[0].creator && result.body[0].date - } - - def "GET /api/EntityDescriptor{resourceId}/Versions with 2 entity descriptor versions"() { - given: - EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser') - ed = entityDescriptorRepository.save(ed) - //Will created a second version for UPDATE revision - ed.serviceEnabled = true - entityDescriptorRepository.save(ed) - - when: - def result = getAllEntityDescriptorVersions(ed.resourceId, List) - - then: - result.statusCodeValue == 200 - result.body.size == 2 - result.body[0].id < result.body[1].id - result.body[0].date < result.body[1].date - } - - def "GET /api/EntityDescriptor{resourceId}/Versions/{version} for non existent version"() { - given: - EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser') - ed = entityDescriptorRepository.save(ed) - - when: - def result = getEntityDescriptorForVersion(ed.resourceId, '1000', EntityDescriptorRepresentation) - - then: - result.statusCodeValue == 404 - } - - def "GET /api/EntityDescriptor{resourceId}/Versions/{version} with 2 entity descriptor versions returns correct ED for specific versions"() { - given: - EntityDescriptor ed = new EntityDescriptor(entityID: 'http://test/controller', createdBy: 'anonymousUser', serviceProviderName: 'SP1') - ed = entityDescriptorRepository.save(ed) - //Will created a second version for UPDATE revision - ed.serviceProviderName = 'SP2' - entityDescriptorRepository.save(ed) - - when: - def allVersions = getAllEntityDescriptorVersions(ed.resourceId, List) - def edv1 = getEntityDescriptorForVersion(ed.resourceId, allVersions.body[0].id, EntityDescriptorRepresentation) - def edv2 = getEntityDescriptorForVersion(ed.resourceId, allVersions.body[1].id, EntityDescriptorRepresentation) - - then: - edv1.statusCodeValue == 200 - edv1.body.serviceProviderName == 'SP1' - edv2.statusCodeValue == 200 - edv2.body.serviceProviderName == 'SP2' - } - - private getAllEntityDescriptorVersions(String resourceId, responseType) { - this.restTemplate.getForEntity(resourceUriFor(ALL_VERSIONS_URI, resourceId), responseType) - } - - private getEntityDescriptorForVersion(String resourceId, String version, responseType) { - this.restTemplate.getForEntity(resourceUriFor(SPECIFIC_VERSION_URI, resourceId, version), responseType) - } - - private static resourceUriFor(String uriTemplate, String resourceId, String version) { - String.format(uriTemplate, resourceId, version) - } - - private static resourceUriFor(String uriTemplate, String resourceId) { - String.format(uriTemplate, resourceId) - } -} diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy deleted file mode 100644 index 795875962..000000000 --- a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/EntityDescriptorEnversVersioningTests.groovy +++ /dev/null @@ -1,613 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.repository.envers - -import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration -import edu.internet2.tier.shibboleth.admin.ui.domain.* -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.* -import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects -import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.domain.EntityScan -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest -import org.springframework.data.jpa.repository.config.EnableJpaRepositories -import org.springframework.test.context.ContextConfiguration -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.Specification - -import javax.persistence.EntityManager - -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.* -import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.ADMINISTRATIVE -import static org.opensaml.saml.saml2.metadata.ContactPersonTypeEnumeration.OTHER - -/** - * Testing entity descriptor envers versioning - */ -@DataJpaTest -@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, SearchConfiguration, TestConfiguration]) -@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) -@EntityScan("edu.internet2.tier.shibboleth.admin.ui") -class EntityDescriptorEnversVersioningTests extends Specification { - - @Autowired - EntityDescriptorRepository entityDescriptorRepository - - @Autowired - EntityDescriptorService entityDescriptorService - - @Autowired - EntityManager entityManager - - @Autowired - PlatformTransactionManager txMgr - - @Autowired - OpenSamlObjects openSamlObjects - - def "test versioning with contact persons"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, ContactPerson.name, GivenName.name, EmailAddress.name] - - when: - def ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.contacts = [new ContactRepresentation(type: 'administrative', name: 'name', emailAddress: 'test@test')] - it - } - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - then: - entityDescriptorHistory.size() == 1 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].givenName.name == 'name' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].type == ADMINISTRATIVE - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).contactPersons[0].emailAddresses[0].address == 'test@test' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.contacts = [new ContactRepresentation(type: 'administrative', name: 'nameUPDATED', emailAddress: 'test@test')] - it - } - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - then: - entityDescriptorHistory.size() == 2 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.contacts = [new ContactRepresentation(type: 'other', name: 'nameUPDATED2', emailAddress: 'test@test.com')] - it - } - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, - entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - then: - entityDescriptorHistory.size() == 3 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].givenName.name == 'nameUPDATED2' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].type == OTHER - getTargetEntityForRevisionIndex(entityDescriptorHistory, 2).contactPersons[0].emailAddresses[0].address == 'test@test.com' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 2).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 2).sort() == expectedModifiedPersistentEntities.sort() - - //Also make sure we have our original revision - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].givenName.name == 'nameUPDATED' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].type == ADMINISTRATIVE - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).contactPersons[0].emailAddresses[0].address == 'test@test' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - - } - - def "test versioning with organization"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - Organization.name, - OrganizationDisplayName.name, - OrganizationName.name, - OrganizationURL.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.organization = new OrganizationRepresentation(name: 'org', displayName: 'display org', url: 'http://org.edu') - it - } - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - then: - entityDescriptorHistory.size() == 1 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.organization = new OrganizationRepresentation(name: 'orgUpdated', displayName: 'display org Updated', url: 'http://org2.edu') - it - } - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - then: - entityDescriptorHistory.size() == 2 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.organizationNames[0].value == 'orgUpdated' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.displayNames[0].value == 'display org Updated' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).organization.URLs[0].value == 'http://org2.edu' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the original revision is intact - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.organizationNames[0].value == 'org' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.displayNames[0].value == 'display org' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).organization.URLs[0].value == 'http://org.edu' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - } - - def "test versioning with sp sso descriptor"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - NameIDFormat.name, - SPSSODescriptor.name] - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { - it.protocolSupportEnum = 'SAML 1.1' - it.nameIdFormats = ['format'] - it - } - it - } - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - then: - entityDescriptorHistory.size() == 1 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.serviceProviderSsoDescriptor = new ServiceProviderSsoDescriptorRepresentation().with { - it.protocolSupportEnum = 'SAML 1.1, SAML 2' - it.nameIdFormats = ['formatUPDATED'] - it - } - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - then: - entityDescriptorHistory.size() == 2 - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].nameIDFormats[0].format == 'formatUPDATED' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 1).roleDescriptors[0].supportedProtocols[1] == 'urn:oasis:names:tc:SAML:2.0:protocol' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 1).timestamp > 0L - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the original revision is intact - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].nameIDFormats[0].format == 'format' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[0] == 'urn:oasis:names:tc:SAML:1.1:protocol' - getTargetEntityForRevisionIndex(entityDescriptorHistory, 0).roleDescriptors[0].supportedProtocols[1] == null - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).principalUserName == 'anonymousUser' - getRevisionEntityForRevisionIndex(entityDescriptorHistory, 0).timestamp > 0L - } - - def "test versioning with uiInfo"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - Description.name, - DisplayName.name, - SPSSODescriptor.name, - Extensions.name, - InformationURL.name, - Logo.name, - PrivacyStatementURL.name, - UIInfo.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.mdui = new MduiRepresentation().with { - it.displayName = 'Initial display name' - it.informationUrl = 'http://info' - it.privacyStatementUrl = 'http://privacy' - it.description = 'Initial desc' - it.logoUrl = 'http://logo' - it.logoHeight = 20 - it.logoWidth = 30 - it - } - it - } - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - //Groovy FTW - able to call any private methods on ANY object. Get first revision - UIInfo uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - - then: - entityDescriptorHistory.size() == 1 - uiinfo.displayNames[0].value == 'Initial display name' - uiinfo.informationURLs[0].value == 'http://info' - uiinfo.privacyStatementURLs[0].value == 'http://privacy' - uiinfo.descriptions[0].value == 'Initial desc' - uiinfo.logos[0].URL == 'http://logo' - uiinfo.logos[0].height == 20 - uiinfo.logos[0].width == 30 - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.mdui = new MduiRepresentation().with { - it.displayName = 'Display name UPDATED' - it.informationUrl = 'http://info.updated' - it.privacyStatementUrl = 'http://privacy.updated' - it.description = 'Desc UPDATED' - it.logoUrl = 'http://logo.updated' - it.logoHeight = 30 - it.logoWidth = 40 - it - } - it - } - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - //Get second revision - uiinfo = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) - //And initial revision - def uiinfoInitialRevision = entityDescriptorService.getUIInfo(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - - then: - entityDescriptorHistory.size() == 2 - uiinfo.displayNames[0].value == 'Display name UPDATED' - uiinfo.informationURLs[0].value == 'http://info.updated' - uiinfo.privacyStatementURLs[0].value == 'http://privacy.updated' - uiinfo.descriptions[0].value == 'Desc UPDATED' - uiinfo.logos[0].URL == 'http://logo.updated' - uiinfo.logos[0].height == 30 - uiinfo.logos[0].width == 40 - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial revision is still intact - uiinfoInitialRevision.displayNames[0].value == 'Initial display name' - uiinfoInitialRevision.informationURLs[0].value == 'http://info' - uiinfoInitialRevision.privacyStatementURLs[0].value == 'http://privacy' - uiinfoInitialRevision.descriptions[0].value == 'Initial desc' - uiinfoInitialRevision.logos[0].URL == 'http://logo' - uiinfoInitialRevision.logos[0].height == 20 - uiinfoInitialRevision.logos[0].width == 30 - } - - def "test versioning with security"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - KeyDescriptor.name, - KeyInfo.name, - SPSSODescriptor.name, - X509Certificate.name, - X509Data.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.securityInfo = new SecurityInfoRepresentation().with { - it.authenticationRequestsSigned = true - it.x509CertificateAvailable = true - it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue')] - it - } - it - } - - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - //Get initial revision - SPSSODescriptor spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) - - KeyDescriptor keyDescriptor = spssoDescriptor.keyDescriptors[0] - X509Certificate x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] - - then: - entityDescriptorHistory.size() == 1 - spssoDescriptor.isAuthnRequestsSigned() - keyDescriptor.name == 'sign' - keyDescriptor.usageType == 'signing' - x509cert.value == 'signingValue' - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.securityInfo = new SecurityInfoRepresentation().with { - it.authenticationRequestsSigned = false - it.x509CertificateAvailable = true - it.x509Certificates = [new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'sign', type: 'signing', value: 'signingValue'), - new SecurityInfoRepresentation.X509CertificateRepresentation(name: 'encrypt', type: 'encryption', value: 'encryptionValue')] - it - } - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - - //Get second revision - SPSSODescriptor spssoDescriptor_second = entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) - - KeyDescriptor keyDescriptor_second1 = spssoDescriptor_second.keyDescriptors[0] - X509Certificate x509cert_second1 = keyDescriptor_second1.keyInfo.x509Datas[0].x509Certificates[0] - KeyDescriptor keyDescriptor_second2 = spssoDescriptor_second.keyDescriptors[1] - X509Certificate x509cert_second2 = keyDescriptor_second2.keyInfo.x509Datas[0].x509Certificates[0] - - - //Get initial revision - spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) - - keyDescriptor = spssoDescriptor.keyDescriptors[0] - x509cert = keyDescriptor.keyInfo.x509Datas[0].x509Certificates[0] - - then: - entityDescriptorHistory.size() == 2 - !spssoDescriptor_second.isAuthnRequestsSigned() - keyDescriptor_second1.name == 'sign' - keyDescriptor_second1.usageType == 'signing' - keyDescriptor_second2.name == 'encrypt' - keyDescriptor_second2.usageType == 'encryption' - x509cert_second1.value == 'signingValue' - x509cert_second2.value == 'encryptionValue' - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial version is intact - spssoDescriptor.keyDescriptors.size() == 1 - spssoDescriptor.isAuthnRequestsSigned() - keyDescriptor.name == 'sign' - keyDescriptor.usageType == 'signing' - x509cert.value == 'signingValue' - } - - def "test versioning ACS"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - SPSSODescriptor.name, - AssertionConsumerService.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.assertionConsumerServices = [ - new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] - it - } - - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - SPSSODescriptor spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) - AssertionConsumerService acs = spssoDescriptor.assertionConsumerServices[0] - - then: - entityDescriptorHistory.size() == 1 - !acs.isDefault() - acs.location == 'http://acs' - acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - - when: - representation = new EntityDescriptorRepresentation().with { - it.assertionConsumerServices = [ - new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs.updated', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS', makeDefault: true), - new AssertionConsumerServiceRepresentation(locationUrl: 'http://acs2', binding: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - SPSSODescriptor spssoDescriptor2 = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,1)) - def (acs1, acs2) = [spssoDescriptor2.assertionConsumerServices[0], spssoDescriptor2.assertionConsumerServices[1]] - - //Initial revision - spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory,0)) - acs = spssoDescriptor.assertionConsumerServices[0] - - then: - entityDescriptorHistory.size() == 2 - acs1.isDefault() - !acs2.isDefault() - acs1.location == 'http://acs.updated' - acs1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' - acs2.location == 'http://acs2' - acs2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial revision is intact - !acs.isDefault() - acs.location == 'http://acs' - acs.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - } - - def "test versioning logout"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - SPSSODescriptor.name, - SingleLogoutService.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST')] - it - } - - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - SPSSODescriptor spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - SingleLogoutService slo = spssoDescriptor.singleLogoutServices[0] - - then: - entityDescriptorHistory.size() == 1 - slo.location == 'http://logout' - slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.logoutEndpoints = [new LogoutEndpointRepresentation(url: 'http://logout.updated', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS'), - new LogoutEndpointRepresentation(url: 'http://logout2', bindingType: 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact')] - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - SPSSODescriptor spssoDescriptor2 = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) - def (slo1, slo2) = [spssoDescriptor2.singleLogoutServices[0], spssoDescriptor2.singleLogoutServices[1]] - - //Initial revision - spssoDescriptor = - entityDescriptorService.getSPSSODescriptorFromEntityDescriptor(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - slo = spssoDescriptor.singleLogoutServices[0] - - then: - entityDescriptorHistory.size() == 2 - slo1.location == 'http://logout.updated' - slo1.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:PAOS' - slo2.location == 'http://logout2' - slo2.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact' - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial version is intact - slo.location == 'http://logout' - slo.binding == 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST' - } - - def "test versioning relying party overrides"() { - setup: - def expectedModifiedPersistentEntities = [EntityDescriptor.name, - EntityAttributes.name, - Extensions.name, - Attribute.name, - XSBoolean.name, - XSString.name] - - when: - EntityDescriptor ed = new EntityDescriptor() - def representation = new EntityDescriptorRepresentation().with { - it.relyingPartyOverrides = [signAssertion: true] - it.attributeRelease = ['attr1'] - it - } - - def entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - EntityAttributes attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - - then: - entityDescriptorHistory.size() == 1 - attrs.attributes[0].attributeValues[0].storedValue == 'true' - attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' - getModifiedEntityNames(entityDescriptorHistory, 0).sort() == expectedModifiedPersistentEntities.sort() - - when: - representation = new EntityDescriptorRepresentation().with { - it.relyingPartyOverrides = [signAssertion: false] - it.attributeRelease = ['attr1', 'attr2'] - it - } - - entityDescriptorHistory = updateAndGetRevisionHistoryOfEntityDescriptor(ed, representation, entityDescriptorService, - entityDescriptorRepository, - txMgr, - entityManager) - - EntityAttributes attrs2 = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 1)) - - //Initial revision - attrs = entityDescriptorService.getEntityAttributes(getTargetEntityForRevisionIndex(entityDescriptorHistory, 0)) - - expectedModifiedPersistentEntities = [EntityDescriptor.name, - EntityAttributes.name, - Attribute.name, - XSString.name] - then: - entityDescriptorHistory.size() == 2 - attrs2.attributes[0].attributeValues[0].xsStringvalue == 'attr1' - attrs2.attributes[0].attributeValues[1].xsStringvalue == 'attr2' - getModifiedEntityNames(entityDescriptorHistory, 1).sort() == expectedModifiedPersistentEntities.sort() - - //Check the initial revision is intact - attrs.attributes[0].attributeValues[0].storedValue == 'true' - attrs.attributes[1].attributeValues[0].xsStringvalue == 'attr1' - attrs.attributes[1].attributeValues[1] == null - } -} diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy deleted file mode 100644 index 226df4476..000000000 --- a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEntityBasicEnversVersioningTests.groovy +++ /dev/null @@ -1,106 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.repository.envers - -import edu.internet2.tier.shibboleth.admin.ui.configuration.CoreShibUiConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.InternationalizationConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter -import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository -import org.hibernate.envers.AuditReaderFactory -import org.hibernate.envers.query.AuditQuery -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.domain.EntityScan -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest -import org.springframework.data.jpa.repository.config.EnableJpaRepositories -import org.springframework.test.context.ContextConfiguration -import org.springframework.transaction.PlatformTransactionManager -import org.springframework.transaction.support.DefaultTransactionDefinition -import spock.lang.Specification - -import javax.persistence.EntityManager - -import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRES_NEW - -/** - * Testing metadata resolvers basic versioning by envers is functioning. - */ -@DataJpaTest -@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration]) -@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) -@EntityScan("edu.internet2.tier.shibboleth.admin.ui") -class MetadataResolverEntityBasicEnversVersioningTests extends Specification { - - @Autowired - MetadataResolverRepository metadataResolverRepository - - @Autowired - EntityManager entityManager - - @Autowired - PlatformTransactionManager txMgr - - def "test basic audit and version data is created when persisting base metadata resolver with envers enabled"() { - when: - MetadataResolver mdr = doInExplicitTransaction { - metadataResolverRepository.save(create {new MetadataResolver()}) - } - def metadataResolverHistory = resolverHistory() - - then: - metadataResolverHistory.size() == 1 - - when: - def rev = metadataResolverHistory[0] - - then: - rev[1].principalUserName == 'anonymousUser' - - when: - mdr.name = 'Updated' - doInExplicitTransaction { - metadataResolverRepository.save(mdr) - } - metadataResolverHistory = resolverHistory() - - then: - metadataResolverHistory.size == 2 - } - - private resolverHistory() { - def auditReader = AuditReaderFactory.get(entityManager) - AuditQuery auditQuery = auditReader - .createQuery() - .forRevisionsOfEntity(MetadataResolver, false, true) - auditQuery.resultList - - } - - private static create(Closure concreteResolverSupplier) { - MetadataResolver resolver = concreteResolverSupplier() - resolver.with { - it.name = "testme" - it.metadataFilters.add(new EntityAttributesFilter().with { - it.entityAttributesFilterTarget = new EntityAttributesFilterTarget().with { - it.entityAttributesFilterTargetType = EntityAttributesFilterTarget.EntityAttributesFilterTargetType.ENTITY - it.value = ["hola"] - return it - } - return it - }) - } - resolver - } - - //This explicit low level transaction dance is required in order to verify history/version data that envers - //writes out only after the explicit transaction is committed, therefore making it impossible to verify within the main tx - //boundary of the test method which commits tx only after an execution of the test method. This let's us explicitly - //start/commit transaction making envers data written out and verifiable - private doInExplicitTransaction(Closure uow) { - def txStatus = txMgr.getTransaction(new DefaultTransactionDefinition(PROPAGATION_REQUIRES_NEW)) - def entity = uow() - txMgr.commit(txStatus) - entity - } -} diff --git a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy b/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy deleted file mode 100644 index 738187741..000000000 --- a/envers-tests-module/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy +++ /dev/null @@ -1,116 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.service.envers - -import edu.internet2.tier.shibboleth.admin.ui.configuration.* -import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor -import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.domain.EntityScan -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest -import org.springframework.data.jpa.repository.config.EnableJpaRepositories -import org.springframework.test.context.ContextConfiguration -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.Specification - -import java.time.LocalDateTime - -import static edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport.doInExplicitTransaction - -@DataJpaTest -@ContextConfiguration(classes = [CoreShibUiConfiguration, InternationalizationConfiguration, TestConfiguration, SearchConfiguration, EntitiesVersioningConfiguration]) -@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"]) -@EntityScan("edu.internet2.tier.shibboleth.admin.ui") -class EnversEntityDescriptorVersionServiceTests extends Specification { - - @Autowired - EntityDescriptorVersionService entityDescriptorVersionService - - @Autowired - EntityDescriptorRepository entityDescriptorRepository - - @Autowired - EntityDescriptorService entityDescriptorService - - @Autowired - PlatformTransactionManager txMgr - - def "versioning service returns correct number of versions sorted by modified date in natural order"() { - when: 'Initial version' - EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1') - ed = doInExplicitTransaction(txMgr) { - entityDescriptorRepository.save(ed) - } - def versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) - - then: - versions.size() == 1 - versions[0].id - versions[0].creator - versions[0].date < LocalDateTime.now() - - when: 'Second version' - ed.serviceProviderName = 'SP2' - ed = doInExplicitTransaction(txMgr) { - entityDescriptorRepository.save(ed) - } - versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) - - then: - versions.size() == 2 - versions[0].id && versions[1].id - versions[0].creator && versions[1].creator - versions[0].date < versions[1].date - - when: 'Third version' - ed.serviceProviderName = 'SP3' - ed = doInExplicitTransaction(txMgr) { - entityDescriptorRepository.save(ed) - } - versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) - - then: - versions.size() == 3 - versions[0].id && versions[1].id && versions[2].id - versions[0].creator && versions[1].creator && versions[2].creator - (versions[0].date < versions[1].date) && (versions[1].date < versions[2].date) - } - - def "versioning service returns correct entity descriptor for version number"() { - when: 'Initial version' - EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1', createdBy: 'anonymousUser') - ed = doInExplicitTransaction(txMgr) { - entityDescriptorRepository.save(ed) - } - def versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) - def v1EdRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, versions[0].id) - - then: - v1EdRepresentation.serviceProviderName == 'SP1' - v1EdRepresentation.id == ed.resourceId - - when: 'Update the original' - ed.serviceProviderName = 'SP2' - ed = doInExplicitTransaction(txMgr) { - entityDescriptorRepository.save(ed) - } - versions = entityDescriptorVersionService.findVersionsForEntityDescriptor(ed.resourceId) - def v2EdRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, versions[1].id) - - then: - v2EdRepresentation.serviceProviderName == 'SP2' - v2EdRepresentation.id == ed.resourceId - } - - def "versioning service returns null for non existent version number"() { - when: 'Initial version' - EntityDescriptor ed = new EntityDescriptor(entityID: 'ed', serviceProviderName: 'SP1', createdBy: 'anonymousUser') - ed = doInExplicitTransaction(txMgr) { - entityDescriptorRepository.save(ed) - } - def edRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, '1000') - - then: - !edRepresentation - } -} From 31b3228cfbc272e3c6db73f8341f5d23b963f30e Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 13 Jun 2019 09:44:33 -0400 Subject: [PATCH 48/51] Change order of tests --- backend/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/build.gradle b/backend/build.gradle index 3af60585e..965816952 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -233,6 +233,7 @@ task enversTest(type: Test) { systemProperties = System.properties systemProperties['user.dir'] = workingDir } +enversTest.mustRunAfter test check { dependsOn enversTest From c37e28d923eec5ad9ae2a668de3e347b9e64c626 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 13 Jun 2019 10:07:12 -0400 Subject: [PATCH 49/51] Remove order of tests --- backend/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/build.gradle b/backend/build.gradle index 965816952..3af60585e 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -233,7 +233,6 @@ task enversTest(type: Test) { systemProperties = System.properties systemProperties['user.dir'] = workingDir } -enversTest.mustRunAfter test check { dependsOn enversTest From 34482660cd140938adb15be8e89f64229987cb32 Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 13 Jun 2019 11:16:54 -0400 Subject: [PATCH 50/51] Add cleanWs() to Jenkins pipeline --- Jenkinsfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index bc032671c..8c6befc98 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -48,5 +48,8 @@ pipeline { success { emailext body: '''${SCRIPT, template="groovy-text.template"}''', recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']], subject: '[SHIBUI] Build Success' } + always { + cleanWs() + } } -} \ No newline at end of file +} From 7d4bd616ef1ce3853a1efd09e43e3bf0f971a38e Mon Sep 17 00:00:00 2001 From: Dmitriy Kopylenko Date: Thu, 13 Jun 2019 13:58:55 -0400 Subject: [PATCH 51/51] Check against static date format --- .../domain/versioning/VersionJsonSerializationBasicTests.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy index 07c37a55c..585369249 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy @@ -24,7 +24,7 @@ class VersionJsonSerializationBasicTests extends Specification { { "id": "2", "creator": "kramer", - "date": "${staticDate.toString()}" + "date": "2019-05-20T15:00" } """