Skip to content

Commit

Permalink
SHIBUI-1788
Browse files Browse the repository at this point in the history
Adding testing to validate callback to the configuration is updated
properly when the definitions are changed
  • Loading branch information
chasegawa committed Jun 8, 2021
1 parent 2b4c374 commit d670d3a
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import edu.internet2.tier.shibboleth.admin.ui.domain.IRelyingPartyOverrideProperty;
import edu.internet2.tier.shibboleth.admin.ui.domain.RelyingPartyOverrideProperty;
import edu.internet2.tier.shibboleth.admin.ui.service.CustomEntityAttributesDefinitionService;
import edu.internet2.tier.shibboleth.admin.ui.service.ICustomEntityAttributesDefinitionListener;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
Expand All @@ -18,7 +18,7 @@

@Configuration
@ConfigurationProperties(prefix = "custom")
public class CustomPropertiesConfiguration {
public class CustomPropertiesConfiguration implements ICustomEntityAttributesDefinitionListener {
private List<? extends Map<String, String>> attributes = new ArrayList<>();

private CustomEntityAttributesDefinitionService ceadService;
Expand All @@ -27,22 +27,53 @@ public class CustomPropertiesConfiguration {

private List<RelyingPartyOverrideProperty> overridesFromConfigFile = new ArrayList<>();

public List<? extends Map<String, String>> getAttributes() {
return attributes;
private void buildRelyingPartyOverrides() {
// Start over with a clean map and get the CustomEntityAttributesDefinitions from the DB
overrides = new HashMap<>();
ceadService.getAllDefinitions().forEach(def -> overrides.put(def.getName(), def));

// We only want to add to an override from the config file if the incoming override (by name) isn't already in
// the list of overrides (ie DB > file config)
for(RelyingPartyOverrideProperty rpop : this.overridesFromConfigFile) {
if (!this.overrides.containsKey(rpop.getName())) {
this.overrides.put(rpop.getName(), rpop);
}
}
}

/**
* We don't know what change occurred, so the easiest thing to do is just rebuild our map of overrides.
* (especially since the small occurrence of this and number of items makes doing this ok perf-wise).
*/
@Override
public void customEntityAttributesDefinitionChangeOccurred() {
buildRelyingPartyOverrides();
}

public List<? extends Map<String, String>> getAttributes() {
return attributes;
}

public List<IRelyingPartyOverrideProperty> getOverrides() {
return new ArrayList<>(overrides.values());
}

@PostConstruct
public void postConstruct() {
// Register with service to get the updates when changes are made to the DB definitions
ceadService.addCustomEntityAttributesDefinitionListener(this);

// Make sure we have the right data
buildRelyingPartyOverrides();
}

public void setAttributes(List<? extends Map<String, String>> attributes) {
this.attributes = attributes;
}
}

@Autowired
public void setCeadService(CustomEntityAttributesDefinitionService ceadService) {
this.ceadService = ceadService;

}

/**
Expand All @@ -51,20 +82,4 @@ public void setCeadService(CustomEntityAttributesDefinitionService ceadService)
public void setOverrides(List<RelyingPartyOverrideProperty> overridesFromConfigFile) {
this.overridesFromConfigFile = overridesFromConfigFile;
}

@PostConstruct
public void postConstruct() {
// Register with service to get the updates when changes are made to the DB definitions
// ceadService.setCustomPropertiesConfiguration(this);
buildRelyingPartyOverrides();
}

private void buildRelyingPartyOverrides() {
// We only want to add to an override if the incoming override (by name) isn't already in the list of overrides
for(RelyingPartyOverrideProperty rpop : this.overridesFromConfigFile) {
if (!this.overrides.containsKey(rpop.getName())) {
this.overrides.put(rpop.getName(), rpop);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

public interface CustomEntityAttributesDefinitionService {

void addCustomEntityAttributesDefinitionListener(ICustomEntityAttributesDefinitionListener listener);

CustomEntityAttributeDefinition createOrUpdateDefinition(CustomEntityAttributeDefinition definition);

void deleteDefinition(CustomEntityAttributeDefinition definition);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package edu.internet2.tier.shibboleth.admin.ui.service;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import edu.internet2.tier.shibboleth.admin.ui.domain.CustomEntityAttributeDefinition;
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.CustomEntityAttributeFilterValue;
Expand All @@ -16,21 +18,32 @@
@Service
@Primary
public class CustomEntityAttributesDefinitionServiceImpl implements CustomEntityAttributesDefinitionService {
@Autowired
private CustomEntityAttributeDefinitionRepository repository;

@Autowired
CustomEntityAttributeFilterValueRepository customEntityAttributeFilterValueRepository;

@Autowired
EntityManager entityManager;

private List<ICustomEntityAttributesDefinitionListener> listeners = new ArrayList<>();

@Autowired
private CustomEntityAttributeDefinitionRepository repository;

@Override
public CustomEntityAttributeDefinition createOrUpdateDefinition(CustomEntityAttributeDefinition definition) {
return repository.save(definition);
public void addCustomEntityAttributesDefinitionListener(ICustomEntityAttributesDefinitionListener listener) {
listeners.add(listener);
}

@Override
@Transactional
public CustomEntityAttributeDefinition createOrUpdateDefinition(CustomEntityAttributeDefinition definition) {
CustomEntityAttributeDefinition result = repository.save(definition);
notifyListeners();
return result;
}

@Override
@Transactional
public void deleteDefinition(CustomEntityAttributeDefinition definition) {
// must remove any CustomEntityAttributeFilterValues first to avoid integrity constraint issues
List<CustomEntityAttributeFilterValue> customEntityValues = customEntityAttributeFilterValueRepository.findAllByCustomEntityAttributeDefinition(definition);
Expand All @@ -41,6 +54,7 @@ public void deleteDefinition(CustomEntityAttributeDefinition definition) {
});
CustomEntityAttributeDefinition entityToRemove = repository.findByName(definition.getName());
repository.delete(entityToRemove);
notifyListeners();
}

@Override
Expand All @@ -53,4 +67,7 @@ public List<CustomEntityAttributeDefinition> getAllDefinitions() {
return repository.findAll();
}

private void notifyListeners() {
listeners.forEach(l -> l.customEntityAttributesDefinitionChangeOccurred());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package edu.internet2.tier.shibboleth.admin.ui.service;

public interface ICustomEntityAttributesDefinitionListener {
void customEntityAttributesDefinitionChangeOccurred();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package edu.internet2.tier.shibboleth.admin.ui.configuration

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.domain.CustomEntityAttributeDefinition
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects
import edu.internet2.tier.shibboleth.admin.ui.repository.CustomEntityAttributeDefinitionRepository
import edu.internet2.tier.shibboleth.admin.ui.repository.CustomEntityAttributeFilterValueRepository
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.CustomEntityAttributesDefinitionService
import edu.internet2.tier.shibboleth.admin.ui.service.CustomEntityAttributesDefinitionServiceImpl

import javax.persistence.EntityManager

import org.opensaml.saml.metadata.resolver.MetadataResolver
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
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.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.ContextConfiguration

import spock.lang.Specification

/**
* Tests for <code>edu.internet2.tier.shibboleth.admin.ui.configuration.CustomPropertiesConfiguration</code>
*/
@DataJpaTest
@ContextConfiguration(classes=[CoreShibUiConfiguration, InternationalizationConfiguration, SearchConfiguration, edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration])
@EnableJpaRepositories(basePackages = ["edu.internet2.tier.shibboleth.admin.ui"])
@EntityScan("edu.internet2.tier.shibboleth.admin.ui")
class CustomPropertiesConfigurationTests extends Specification {

@Autowired
@Qualifier(value="customPropertiesConfiguration")
CustomPropertiesConfiguration configUnderTest

@Autowired
CustomEntityAttributesDefinitionService ceadService

@Autowired
CustomEntityAttributeDefinitionRepository repository;

@Autowired
EntityManager entityManager

def "Updating Custom Entity Attribute Definitions will update the CustomPropertiesConfiguration automatically"() {
given: 'Test defaults loaded (ie no CEADs in DB)'

expect:
ceadService.getAllDefinitions().size() == 0
configUnderTest.getOverrides().size() == 10

def ca = new CustomEntityAttributeDefinition().with {
it.name = "newDefName"
it.attributeType = "STRING"
it.defaultValue = "foobar"
it
}

ceadService.createOrUpdateDefinition(ca)
entityManager.flush()

ceadService.getAllDefinitions().size() == 1
configUnderTest.getOverrides().size() == 11

def ca2 = new CustomEntityAttributeDefinition().with {
it.name = "newDefName2"
it.attributeType = "STRING"
it.defaultValue = "foobar2"
it
}

ceadService.createOrUpdateDefinition(ca2)
entityManager.flush()

ceadService.getAllDefinitions().size() == 2
configUnderTest.getOverrides().size() == 12

ceadService.deleteDefinition(ca)
entityManager.flush()

ceadService.getAllDefinitions().size() == 1
configUnderTest.getOverrides().size() == 11
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ import org.springframework.data.domain.AuditorAware
import org.springframework.mail.javamail.JavaMailSender
import org.springframework.mail.javamail.JavaMailSenderImpl

/**
* NOT A TEST - this is configuration FOR tests
*/
@Configuration
class TestConfiguration {
@Autowired
Expand Down

0 comments on commit d670d3a

Please sign in to comment.