Skip to content

Commit

Permalink
SHIBUI-522: refactor entity attributes filter persistance and represe…
Browse files Browse the repository at this point in the history
…ntation conversion nuances
  • Loading branch information
dima767 committed Jun 12, 2018
1 parent ae67752 commit 0e37753
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,61 +47,11 @@ public class MetadataResolverConfiguration {
public MetadataResolver metadataResolver() throws ResolverException, ComponentInitializationException {
ChainingMetadataResolver metadataResolver = new ChainingMetadataResolver();
metadataResolver.setId("chain");

List<MetadataResolver> resolvers = new ArrayList<>();

// TODO: remove this later when we allow for creation of arbitrary metadata resolvers
FileBackedHTTPMetadataResolver incommonMR = new FileBackedHTTPMetadataResolver(HttpClients.createMinimal(), "http://md.incommon.org/InCommon/InCommon-metadata.xml", "/tmp/incommonmd.xml"){
@Override
protected void initMetadataResolver() throws ComponentInitializationException {
super.initMetadataResolver();

for (String entityId: this.getBackingStore().getIndexedDescriptors().keySet()) {
Document document = new Document();
document.add(new StringField("id", entityId, Field.Store.YES));
document.add(new TextField("content", entityId, Field.Store.YES)); // TODO: change entityId to be content of entity descriptor block
try {
indexWriter.addDocument(document);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
try {
indexWriter.commit();
} catch (IOException e) {
throw new ComponentInitializationException(e);
}
}

// TODO: this is probably not the best way to do this
@Nullable
@Override
public DateTime getLastRefresh() {
return null;
}

// TODO: this is probably not the best way to do this
@Override
protected void processConditionalRetrievalHeaders(HttpResponse response) {
// let's do nothing 'cause we want to allow a refresh
}
};
incommonMR.setId("incommonmd");
incommonMR.setParserPool(openSamlObjects.getParserPool());
incommonMR.setMetadataFilter(new MetadataFilterChain());
incommonMR.initialize();


resolvers.add(incommonMR);

if (!metadataResolverRepository.findAll().iterator().hasNext()) {
edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr = new edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver();
mr.setName("incommonmd");
metadataResolverRepository.save(mr);
}

metadataResolver.setResolvers(resolvers);

metadataResolver.initialize();

return metadataResolver;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.net.URI;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RestController
@RequestMapping("/api/MetadataResolver/{metadataResolverId}")
Expand Down Expand Up @@ -64,23 +65,29 @@ public ResponseEntity<?> create(@PathVariable String metadataResolverId, @Reques
MetadataResolver metadataResolver = repository.findAll().iterator().next();
metadataResolver.getMetadataFilters().add(createdFilter);

//convert before saving into database
if(createdFilter instanceof EntityAttributesFilter) {
EntityAttributesFilter.class.cast(createdFilter).fromTransientRepresentation();
}
MetadataResolver persistedMr = repository.save(metadataResolver);

// we reload the filters here after save
metadataResolverService.reloadFilters(persistedMr.getName());

MetadataFilter persistedFilter =
convertIntoTransientRepresentationIfNecessary(persistedMr.getMetadataFilters().stream(), createdFilter.getResourceId());

return ResponseEntity
.created(getResourceUriFor(persistedMr, createdFilter.getResourceId()))
.body(persistedMr.getMetadataFilters()
.stream()
.filter(filter -> filter.getResourceId().equals(createdFilter.getResourceId()))
.collect(Collectors.toList())
.get(0)); // "There can be only one!!!"
.body(persistedFilter);

}

@PutMapping("/Filters/{resourceId}")
public ResponseEntity<?> update(@PathVariable String metadataResolverId, @RequestBody MetadataFilter updatedFilter) {
public ResponseEntity<?> update(@PathVariable String metadataResolverId,
@PathVariable String resourceId,
@RequestBody MetadataFilter updatedFilter) {

//TODO: replace with get by metadataResolverId once we have more than one
MetadataResolver metadataResolver = repository.findAll().iterator().next();

Expand All @@ -105,14 +112,31 @@ public ResponseEntity<?> update(@PathVariable String metadataResolverId, @Reques
filterTobeUpdated.setFilterEnabled(updatedFilter.isFilterEnabled());
updateConcreteFilterTypeData(filterTobeUpdated, updatedFilter);

//convert before saving into database
if(filterTobeUpdated instanceof EntityAttributesFilter) {
EntityAttributesFilter.class.cast(filterTobeUpdated).fromTransientRepresentation();
}

MetadataResolver persistedMr = repository.save(metadataResolver);

metadataResolverService.reloadFilters(persistedMr.getName());

return ResponseEntity.ok()
.body(persistedMr.getMetadataFilters().stream()
.filter(f -> f.getResourceId().equals(updatedFilter.getResourceId()))
.collect(Collectors.toList()).get(0));
MetadataFilter persistedFilter =
convertIntoTransientRepresentationIfNecessary(persistedMr.getMetadataFilters().stream(), updatedFilter.getResourceId());

return ResponseEntity.ok().body(persistedFilter);
}

private MetadataFilter convertIntoTransientRepresentationIfNecessary(Stream<MetadataFilter> filters, final String filterResourceId) {
MetadataFilter persistedFilter = filters
.filter(f -> f.getResourceId().equals(filterResourceId))
.collect(Collectors.toList()).get(0);

//convert before saving into database
if(persistedFilter instanceof EntityAttributesFilter) {
EntityAttributesFilter.class.cast(persistedFilter).intoTransientRepresentation();
}
return persistedFilter;
}

/**
Expand All @@ -126,7 +150,6 @@ private void updateConcreteFilterTypeData(MetadataFilter filterToBeUpdated, Meta
toFilter.setEntityAttributesFilterTarget(fromFilter.getEntityAttributesFilterTarget());
toFilter.setRelyingPartyOverrides(fromFilter.getRelyingPartyOverrides());
toFilter.setAttributeRelease(fromFilter.getAttributeRelease());
toFilter.intoTransientRepresentation();
}
else if(filterWithUpdatedData instanceof EntityRoleWhiteListFilter) {
EntityRoleWhiteListFilter toFilter = EntityRoleWhiteListFilter.class.cast(filterToBeUpdated);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public void intoTransientRepresentation() {
@PrePersist
@PreUpdate
public void fromTransientRepresentation() {
this.attributes.clear();
List<org.opensaml.saml.saml2.core.Attribute> attributeList = new ArrayList<>();
attributeList.addAll(getAttributeListFromAttributeReleaseList(this.attributeRelease));
attributeList.addAll(getAttributeListFromRelyingPartyOverridesRepresentation(this.relyingPartyOverrides));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration

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.frontend.RelyingPartyOverridesRepresentation
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects
import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityDescriptorServiceImpl
Expand Down Expand Up @@ -92,4 +92,114 @@ class MetadataResolverRepositoryTest extends Specification {
item1.hashCode() == item2.hashCode()
}

def "persisting and performing transformation into transient representation for EntityAttributesFilter correctly"() {
when:
def mdr = new MetadataResolver().with {
it.name = "testme"
it
}
metadataResolverRepository.save(mdr)

entityManager.flush()
entityManager.clear()

//Simulate adding new filter with incoming transient attribute release value as done in MetadataFiltersController
def filter = new EntityAttributesFilter().with {
it.name = 'original'
it.resourceId = 'new-filter-UUID'
it.attributeRelease = ['attr-for-release']
it.relyingPartyOverrides = new RelyingPartyOverridesRepresentation().with {
it.signAssertion = true
it
}
it
}
MetadataResolver metadataResolver = metadataResolverRepository.findAll().iterator().next()

//convert before saving into database
filter.fromTransientRepresentation()

metadataResolver.getMetadataFilters().add(filter)
MetadataResolver persistedMr = metadataResolverRepository.save(metadataResolver)

entityManager.flush()
entityManager.clear()

//This is how it's done in MetadataFiltersController POST/PUT to return the newly saved object back to UI layer
// We are checking here that the method responsible for converting persistent state into the
// transient state used by UI is performed correctly
EntityAttributesFilter persistedFilter = persistedMr.getMetadataFilters().find {
it.resourceId == filter.resourceId
}
//convert before returning to UI
persistedFilter.intoTransientRepresentation()

then:
persistedFilter.name == 'original'
persistedFilter.attributeRelease.find() {
it == 'attr-for-release'
}
persistedFilter.attributes.findAll() {
it.attributeValues.find() {
it.value == 'attr-for-release'
}
}
persistedFilter.relyingPartyOverrides.signAssertion

when:
entityManager.flush()
entityManager.clear()
//Now lets update our filter
filter = new EntityAttributesFilter().with {
it.name = 'updated'
it.resourceId = 'new-filter-UUID'
it.attributeRelease = ['attr-for-release', 'attr-for-release2']
it.relyingPartyOverrides = new RelyingPartyOverridesRepresentation().with {
it.signAssertion = false
it
}
it
}
metadataResolver = metadataResolverRepository.findAll().iterator().next()
EntityAttributesFilter filterToBeUpdated = metadataResolver.metadataFilters.find() {
it.resourceId == filter.resourceId
}
filterToBeUpdated.name = filter.name
filterToBeUpdated.entityAttributesFilterTarget = filter.entityAttributesFilterTarget
filterToBeUpdated.relyingPartyOverrides = filter.relyingPartyOverrides
filterToBeUpdated.attributeRelease = filter.attributeRelease

//convert before saving into database
filterToBeUpdated.fromTransientRepresentation()
entityManager.clear()
persistedMr = metadataResolverRepository.save(metadataResolver)


persistedFilter = persistedMr.getMetadataFilters().find {
it.resourceId == filter.resourceId
}
//convert before returning to UI
persistedFilter.intoTransientRepresentation()

then:
persistedFilter.name == 'updated'
persistedFilter.attributeRelease.find() {
it == 'attr-for-release'
}
persistedFilter.attributeRelease.find() {
it == 'attr-for-release2'
}
persistedFilter.attributes.find() {
it.attributeValues.findAll() {
it.value == 'attr-for-release'
}
}
persistedFilter.attributes.find() {
it.attributeValues.findAll() {
it.value == 'attr-for-release2'
}
}
!persistedFilter.relyingPartyOverrides.signAssertion
}

}

0 comments on commit 0e37753

Please sign in to comment.