/**
* Copyright (c) Codice Foundation
* <p>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.test.itests.catalog;
import static java.lang.String.format;
import static org.codice.ddf.itests.common.catalog.CatalogTestCommons.deleteMetacard;
import static org.codice.ddf.itests.common.catalog.CatalogTestCommons.ingest;
import static org.codice.ddf.itests.common.config.ConfigureTestCommons.configureEnforceValidityErrorsAndWarnings;
import static org.codice.ddf.itests.common.config.ConfigureTestCommons.configureEnforcedMetacardValidators;
import static org.codice.ddf.itests.common.config.ConfigureTestCommons.configureFilterInvalidMetacards;
import static org.codice.ddf.itests.common.config.ConfigureTestCommons.configureMetacardValidityFilterPlugin;
import static org.codice.ddf.itests.common.config.ConfigureTestCommons.configureShowInvalidMetacards;
import static org.codice.ddf.itests.common.csw.CswQueryBuilder.NOT;
import static org.codice.ddf.itests.common.csw.CswQueryBuilder.OR;
import static org.codice.ddf.itests.common.csw.CswQueryBuilder.PROPERTY_IS_EQUAL_TO;
import static org.codice.ddf.itests.common.csw.CswQueryBuilder.PROPERTY_IS_LIKE;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.xml.HasXPath.hasXPath;
import static com.jayway.restassured.RestAssured.given;
import static com.jayway.restassured.RestAssured.when;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpStatus;
import org.codice.ddf.itests.common.AbstractIntegrationTest;
import org.codice.ddf.itests.common.annotations.BeforeExam;
import org.codice.ddf.itests.common.annotations.ConditionalIgnoreRule;
import org.codice.ddf.itests.common.annotations.ConditionalIgnoreRule.ConditionalIgnore;
import org.codice.ddf.itests.common.annotations.SkipUnstableTest;
import org.codice.ddf.itests.common.csw.CswQueryBuilder;
import org.codice.ddf.itests.common.utils.LoggingUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerSuite;
import org.osgi.service.cm.Configuration;
import com.google.common.collect.ImmutableMap;
import com.jayway.restassured.response.ValidatableResponse;
import ddf.catalog.data.types.Validation;
/**
* Tests catalog validation
* This test was created to pull out 16 tests in TestCatalog that were starting/stopping the
* sample-validator each time. Since there is almost no overhead now for a new class it is faster
* to just start the feature once for all 16 of the tests instead of toggling it for each one.
*/
@RunWith(PaxExam.class)
@ExamReactorStrategy(PerSuite.class)
public class TestCatalogValidation extends AbstractIntegrationTest {
private static final String METACARD_X_PATH = "/metacards/metacard[@id='%s']";
@Rule
public TestName testName = new TestName();
@Rule
public ConditionalIgnoreRule rule = new ConditionalIgnoreRule();
@BeforeExam
public void beforeExam() throws Exception {
try {
waitForSystemReady();
getServiceManager().startFeature(true, "sample-validator");
} catch (Exception e) {
LoggingUtils.failWithThrowableStacktrace(e, "Failed in @BeforeExam: ");
}
}
@Test
public void testEnforceValidityErrorsOnly() throws Exception {
//Configure to enforce validator
configureEnforcedMetacardValidators(Collections.singletonList("sample-validator"),
getAdminConfig());
//Configure to enforce errors but not warnings
configureEnforceValidityErrorsAndWarnings("true", "false", getAdminConfig());
//Configure to show invalid metacards to show that invalid metacards were not ingested
configureShowInvalidMetacards("true", "true", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml");
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml",
false);
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard and warning metacard should be in results but not error one
response.body(containsString("warning metacard"));
response.body(containsString("clean metacard"));
response.body(not(containsString("error metacard")));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
deleteMetacard(id3, false);
configureEnforceValidityErrorsAndWarningsReset();
configureShowInvalidMetacardsReset();
}
}
@Test
public void testEnforceValidityWarningsOnly() throws Exception {
//Configure to enforce validator
configureEnforcedMetacardValidators(Collections.singletonList("sample-validator"),
getAdminConfig());
//Configure to enforce warnings but not errors
configureEnforceValidityErrorsAndWarnings("false", "true", getAdminConfig());
//Configure to show invalid metacards to show that invalid metacards were not ingested
configureShowInvalidMetacards("true", "true", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml",
false);
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml");
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard and error metacard should be in results but not warning one
response.body(not(containsString("warning metacard")));
response.body(containsString("clean metacard"));
response.body(containsString("error metacard"));
} finally {
deleteMetacard(id1, false);
deleteMetacard(id2);
deleteMetacard(id3);
configureEnforceValidityErrorsAndWarningsReset();
configureShowInvalidMetacardsReset();
}
}
@Test
@ConditionalIgnore(condition = SkipUnstableTest.class) // DDF-2958
public void testEnforceValidityErrorsAndWarnings() throws Exception {
//Configure to enforce validator
configureEnforcedMetacardValidators(Collections.singletonList("sample-validator"),
getAdminConfig());
//Configure to enforce errors and warnings
configureEnforceValidityErrorsAndWarnings("true", "true", getAdminConfig());
//Configure to show invalid metacards to show that invalid metacards were not ingested
configureShowInvalidMetacards("true", "true", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml",
false);
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml",
false);
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard should be in results but not invalid ones
response.body(not(containsString("warning metacard")));
response.body(containsString("clean metacard"));
response.body(not(containsString("error metacard")));
} finally {
deleteMetacard(id1, false);
deleteMetacard(id2);
deleteMetacard(id3, false);
configureEnforceValidityErrorsAndWarningsReset();
configureShowInvalidMetacardsReset();
}
}
@Test
@ConditionalIgnore(condition = SkipUnstableTest.class) // DDF-2958
public void testNoEnforceValidityErrorsOrWarnings() throws Exception {
//Configure to enforce validator
configureEnforcedMetacardValidators(Collections.singletonList("sample-validator"),
getAdminConfig());
//Configure to enforce neither errors nor warnings
configureEnforceValidityErrorsAndWarnings("false", "false", getAdminConfig());
//Configure to show invalid metacards to show that invalid metacards were not ingested
configureShowInvalidMetacards("true", "true", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml");
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml");
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard should be in results but not invalid one
response.body(containsString("warning metacard"));
response.body(containsString("clean metacard"));
response.body(containsString("error metacard"));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
deleteMetacard(id3);
configureEnforceValidityErrorsAndWarningsReset();
configureShowInvalidMetacardsReset();
}
}
@Test
public void testQueryByErrorFailedValidators() throws Exception {
//Don't enforce the validator, so that it will be marked but ingested
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
//Configure to show invalid metacards so the marked ones will appear in search
configureShowInvalidMetacards("true", "true", getAdminConfig());
//Configure to not filter invalid metacards
configureFilterInvalidMetacards("false", "false", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml");
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml");
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
Validation.FAILED_VALIDATORS_ERRORS,
"sample-validator")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard and warning metacard should be in results but not error one
response.body(not(containsString("warning metacard")));
response.body(not(containsString("clean metacard")));
response.body(containsString("error metacard"));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
deleteMetacard(id3);
configureShowInvalidMetacardsReset();
configureFilterInvalidMetacardsReset();
}
}
@Test
public void testQueryByWarningFailedValidators() throws Exception {
//Don't enforce the validator, so that it will be marked but ingested
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
//Configure to show invalid metacards so the marked ones will appear in search
configureShowInvalidMetacards("true", "true", getAdminConfig());
//Configure to not filter invalid metacards
configureFilterInvalidMetacards("false", "false", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml");
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml");
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
Validation.FAILED_VALIDATORS_WARNINGS,
"sample-validator")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard and warning metacard should be in results but not error one
response.body(not(containsString("error metacard")));
response.body(not(containsString("clean metacard")));
response.body(containsString("warning metacard"));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
deleteMetacard(id3);
configureShowInvalidMetacardsReset();
configureFilterInvalidMetacardsReset();
}
}
@Test
public void testFilterPluginWarningsOnly() throws Exception {
//Configure not enforcing validators so invalid metacards can ingest
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
// Configure invalid filtering
configureMetacardValidityFilterPlugin(Arrays.asList("invalid-state=system-admin"),
getAdminConfig());
// Configure query to request invalid metacards
configureShowInvalidMetacards("true", "true", getAdminConfig());
//Configure to filter metacards with validation warnings but not validation errors
configureFilterInvalidMetacards("false", "true", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml");
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml");
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard should be in results but not invalid one
response.body(not(containsString("warning metacard")));
response.body(containsString("clean metacard"));
response.body(containsString("error metacard"));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
deleteMetacard(id3);
configureFilterInvalidMetacardsReset();
configureMetacardValidityFilterPlugin(Arrays.asList(""), getAdminConfig());
configureShowInvalidMetacardsReset();
}
}
@Test
public void testFilterPluginErrorsOnly() throws Exception {
//Configure not enforcing validators so invalid metacards can ingest
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
// Configure invalid filtering
configureMetacardValidityFilterPlugin(Arrays.asList("invalid-state=system-admin"),
getAdminConfig());
// Configure query to request invalid metacards
configureShowInvalidMetacards("true", "true", getAdminConfig());
//Configure to filter metacards with validation errors but not validation warnings
configureFilterInvalidMetacards("true", "false", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml");
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml");
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard should be in results but not invalid one
response.body(not(containsString("error metacard")));
response.body(containsString("clean metacard"));
response.body(containsString("warning metacard"));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
deleteMetacard(id3);
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
configureFilterInvalidMetacardsReset();
configureMetacardValidityFilterPlugin(Arrays.asList(""), getAdminConfig());
configureShowInvalidMetacardsReset();
}
}
@Test
public void testFilterPluginWarningsAndErrors() throws Exception {
//Configure not enforcing validators so invalid metacards can ingest
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
// Configure invalid filtering
configureMetacardValidityFilterPlugin(Arrays.asList("invalid-state=system-admin"),
getAdminConfig());
// Configure query to request invalid metacards
configureShowInvalidMetacards("true", "true", getAdminConfig());
//configure to filter both metacards with validation errors and validation warnings
configureFilterInvalidMetacards("true", "true", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml");
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml");
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard should be in results but not invalid one
response.body(not(containsString("error metacard")));
response.body(not(containsString("warning metacard")));
response.body(containsString("clean metacard"));
} finally {
deleteMetacard(id1);
deleteMetacard(id3);
deleteMetacard(id2);
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
configureFilterInvalidMetacardsReset();
configureMetacardValidityFilterPlugin(Arrays.asList(""), getAdminConfig());
configureShowInvalidMetacardsReset();
}
}
@Test
@ConditionalIgnore(condition = SkipUnstableTest.class) // DDF-2958
public void testFilterPluginNoFiltering() throws Exception {
//Configure not enforcing validators so invalid metacards can ingest
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
// Configure invalid filtering
configureMetacardValidityFilterPlugin(Arrays.asList("invalid-state=system-admin"),
getAdminConfig());
// Configure query to request invalid metacards
configureShowInvalidMetacards("true", "true", getAdminConfig());
//Configure to not filter metacard with validation errors or warnings
configureFilterInvalidMetacards("false", "false", getAdminConfig());
String id1 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleErrorMetacard.xml");
String id2 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleCleanMetacard.xml");
String id3 = ingestXmlFromResource(XML_RECORD_RESOURCE_PATH + "/sampleWarningMetacard.xml");
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
//clean metacard should be in results but not invalid one
response.body(containsString("error metacard"));
response.body(containsString("warning metacard"));
response.body(containsString("clean metacard"));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
deleteMetacard(id3);
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
configureFilterInvalidMetacardsReset();
configureMetacardValidityFilterPlugin(Arrays.asList(""), getAdminConfig());
configureShowInvalidMetacardsReset();
}
}
@Test
public void testValidationEnforced() throws Exception {
// Update metacardMarkerPlugin config with enforcedMetacardValidators
configureEnforcedMetacardValidators(Collections.singletonList("sample-validator"),
getAdminConfig());
String id1 = ingestXmlFromResource("/metacard1.xml");
String id2 = ingestXmlFromResource("/metacard2.xml", false);
try {
// Search for all entries, implicit "validation-warnings is null" and "validation-errors is null"
// should get added by ValidationQueryFactory
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 is in results AND not Metacard2
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
// Search for all entries that have no validation warnings or errors
query =
new CswQueryBuilder().addPropertyIsNullAttributeFilter(Validation.VALIDATION_WARNINGS)
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 is in results AND not Metacard2
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
//Search for all entries that have validation-warnings from sample-validator or no validation warnings
//Only search that will actually return all entries
query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_EQUAL_TO,
Validation.VALIDATION_WARNINGS,
"*")
.addPropertyIsNullAttributeFilter(Validation.VALIDATION_WARNINGS)
.addLogicalOperator(OR)
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 and NOT metacard2 is in results
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
// Search for all metacards that have validation-warnings
query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_EQUAL_TO,
Validation.VALIDATION_WARNINGS,
"*")
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 and metacard2 are NOT in results
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1))));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
} finally {
deleteMetacard(id1);
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
}
}
@Test
public void testValidationUnenforced() throws Exception {
getServiceManager().stopFeature(true, "catalog-security-filter");
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
String id1 = ingestXmlFromResource("/metacard1.xml");
String id2 = ingestXmlFromResource("/metacard2.xml");
try {
// metacardMarkerPlugin has no enforcedMetacardValidators
// Search for all entries, implicit "validation-warnings is null" and "validation-errors is null"
// should get added by ValidationQueryFactory
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 is in results AND not Metacard2
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
// Search for all entries that have no validation warnings
query =
new CswQueryBuilder().addPropertyIsNullAttributeFilter(Validation.VALIDATION_WARNINGS)
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 is in results AND not Metacard2
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
//Search for all entries that have validation-warnings or no validation warnings
//Only search that will actually return all entries
query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
Validation.VALIDATION_WARNINGS,
"sampleWarnings")
.addPropertyIsNullAttributeFilter(Validation.VALIDATION_WARNINGS)
.addLogicalOperator(OR)
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 AND Metacard2 are in results
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2)));
// Search for all entries that are invalid
query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
Validation.VALIDATION_WARNINGS,
"*")
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard2 is in results AND not Metacard1
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1))));
query =
new CswQueryBuilder().addPropertyIsNullAttributeFilter(Validation.VALIDATION_WARNINGS)
.addLogicalOperator(NOT)
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard2 is in results AND not Metacard1
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1))));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
getServiceManager().startFeature(true, "catalog-security-filter");
}
}
@Test
public void testValidationEnforcedUpdate() throws Exception {
// metacardMarkerPlugin has no enforced validators so both metacards can be ingested
final String id1 = ingestXmlFromResource("/metacard1.xml");
final String id2 = ingestXmlFromResource("/metacard2.xml");
try {
// Enforce the sample metacard validator
configureEnforcedMetacardValidators(Collections.singletonList("sample-validator"),
getAdminConfig());
String metacard2Xml = getFileContent("metacard2.xml");
given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(metacard2Xml)
.put(new DynamicUrl(REST_PATH, id1).getUrl())
.then()
.assertThat()
.statusCode(HttpStatus.SC_BAD_REQUEST);
String metacard1Xml = getFileContent("metacard1.xml");
given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(metacard1Xml)
.put(new DynamicUrl(REST_PATH, id2).getUrl())
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK);
String metacard1Path = format(METACARD_X_PATH, id1);
String metacard2Path = format(METACARD_X_PATH, id2);
executeOpenSearch("xml", "q=*").log()
.all()
.assertThat()
.body(hasXPath(metacard1Path))
.body(hasXPath(metacard1Path + "/string[@name='title']/value",
is("Metacard-1")))
.body(not(hasXPath(metacard1Path + "/string[@name='validation-errors']")))
.body(not(hasXPath(metacard1Path + "/string[@name='validation-warnings']")))
.body(hasXPath(metacard2Path))
.body(hasXPath(metacard2Path + "/string[@name='title']/value",
is("Metacard-1")))
.body(not(hasXPath(metacard2Path + "/string[@name='validation-errors']")))
.body(not(hasXPath(metacard2Path + "/string[@name='validation-warnings']")));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
configureEnforcedMetacardValidators(Collections.singletonList(""), getAdminConfig());
}
}
@Test
public void testValidationUnenforcedUpdate() throws Exception {
// metacardMarkerPlugin has no enforced validators so both metacards can be ingested
final String id1 = ingestXmlFromResource("/metacard1.xml");
final String id2 = ingestXmlFromResource("/metacard2.xml");
try {
String metacard2Xml = getFileContent("metacard2.xml");
given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(metacard2Xml)
.put(new DynamicUrl(REST_PATH, id1).getUrl())
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK);
String metacard1Xml = getFileContent("metacard1.xml");
given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(metacard1Xml)
.put(new DynamicUrl(REST_PATH, id2).getUrl())
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK);
configureShowInvalidMetacards("true", "true", getAdminConfig());
String metacard1Path = format(METACARD_X_PATH, id1);
String metacard2Path = format(METACARD_X_PATH, id2);
executeOpenSearch("xml", "q=*").log()
.all()
.assertThat()
.body(hasXPath(metacard1Path))
.body(hasXPath(metacard1Path + "/string[@name='title']/value",
is("Metacard-2")))
.body(hasXPath(
"count(" + metacard1Path + "/string[@name='validation-errors']/value)",
is("1")))
.body(hasXPath("count(" + metacard1Path
+ "/string[@name='validation-warnings']/value)", is("1")))
.body(hasXPath(metacard2Path))
.body(hasXPath(metacard2Path + "/string[@name='title']/value",
is("Metacard-1")))
.body(not(hasXPath(metacard2Path + "/string[@name='validation-errors']")))
.body(not(hasXPath(metacard2Path + "/string[@name='validation-warnings']")));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
configureShowInvalidMetacardsReset();
}
}
@Test
public void testValidationFiltering() throws Exception {
// Update metacardMarkerPlugin config with no enforcedMetacardValidators
configureEnforcedMetacardValidators(Arrays.asList(""), getAdminConfig());
// Configure invalid filtering
configureMetacardValidityFilterPlugin(Arrays.asList("invalid-state=system-admin"),
getAdminConfig());
// Configure the PDP
PdpProperties pdpProperties = new PdpProperties();
pdpProperties.put("matchOneMappings",
Arrays.asList(
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/role=invalid-state"));
Configuration config = configAdmin.getConfiguration("ddf.security.pdp.realm.AuthzRealm",
null);
Dictionary<String, ?> configProps = new Hashtable<>(pdpProperties);
config.update(configProps);
String id1 = ingestXmlFromResource("/metacard1.xml");
String id2 = ingestXmlFromResource("/metacard2.xml");
try {
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
Validation.VALIDATION_WARNINGS,
"*")
.addPropertyIsNullAttributeFilter(Validation.VALIDATION_WARNINGS)
.addLogicalOperator(OR)
.getQuery();
ValidatableResponse response = given().auth()
.preemptive()
.basic("admin", "admin")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard2 is in results AND Metacard1
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2)));
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard2 is in results Metacard1
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
// Configure invalid filtering
configureMetacardValidityFilterPlugin(Arrays.asList("invalid-state=system-admin,guest"),
getAdminConfig());
response = given().auth()
.preemptive()
.basic("admin", "admin")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard2 is in results AND Metacard1
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2)));
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard2 is in results Metacard1
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2)));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
config = configAdmin.getConfiguration("ddf.security.pdp.realm.AuthzRealm", null);
configProps = new Hashtable<>(new PdpProperties());
config.update(configProps);
}
}
@Test
public void testValidationChecker() throws Exception {
configureEnforcedMetacardValidators(Arrays.asList(""), getAdminConfig());
// Configure invalid filtering
configureMetacardValidityFilterPlugin(Arrays.asList(""), getAdminConfig());
configureShowInvalidMetacards("true", "true", getAdminConfig());
String id1 = ingestXmlFromResource("/metacard1.xml");
String id2 = ingestXmlFromResource("/metacard2.xml");
try {
// Search for all entries, implicit "validation-warnings is null" and "validation-errors is null"
// should get added by ValidationQueryFactory
String query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_LIKE,
"AnyText",
"*")
.getQuery();
ValidatableResponse response = given().header(HttpHeaders.CONTENT_TYPE,
MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 is in results AND Metacard2 because showInvalidMetacards is true
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body((hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
// Search for all entries that have no validation warnings or errors
query =
new CswQueryBuilder().addPropertyIsNullAttributeFilter(Validation.VALIDATION_WARNINGS)
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 is in results AND not Metacard2
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
//Search for all entries that have validation-warnings from sample-validator or no validation warnings
query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_EQUAL_TO,
Validation.VALIDATION_WARNINGS,
"*")
.addPropertyIsNullAttributeFilter(Validation.VALIDATION_WARNINGS)
.addLogicalOperator(OR)
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 and NOT metacard2 is in results
response.body(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1)));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
// Search for all metacards that have validation-warnings
query = new CswQueryBuilder().addAttributeFilter(PROPERTY_IS_EQUAL_TO,
Validation.VALIDATION_WARNINGS,
"*")
.getQuery();
response = given().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML)
.body(query)
.post(CSW_PATH.getUrl())
.then();
// Assert Metacard1 and metacard2 are NOT in results
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id1))));
response.body(not(hasXPath(format(
"/GetRecordsResponse/SearchResults/Record[identifier=\"%s\"]",
id2))));
} finally {
deleteMetacard(id1);
deleteMetacard(id2);
configureShowInvalidMetacardsReset();
}
}
private ValidatableResponse executeOpenSearch(String format, String... query) {
StringBuilder buffer = new StringBuilder(OPENSEARCH_PATH.getUrl()).append("?")
.append("format=")
.append(format);
for (String term : query) {
buffer.append("&")
.append(term);
}
String url = buffer.toString();
LOGGER.info("Getting response to {}", url);
return when().get(url)
.then();
}
protected String ingestXmlFromResource(String resourceName) throws IOException {
StringWriter writer = new StringWriter();
IOUtils.copy(IOUtils.toInputStream(getFileContent(resourceName)), writer);
return ingest(writer.toString(), "text/xml");
}
protected String ingestXmlFromResource(String resourceName, boolean checkResponse)
throws IOException {
if (checkResponse) {
return ingestXmlFromResource(resourceName);
} else {
StringWriter writer = new StringWriter();
IOUtils.copy(IOUtils.toInputStream(getFileContent(resourceName)), writer);
return ingest(writer.toString(), "text/xml", checkResponse);
}
}
public class PdpProperties extends HashMap<String, Object> {
public static final String SYMBOLIC_NAME = "security-pdp-authzrealm";
public static final String FACTORY_PID = "ddf.security.pdp.realm.AuthzRealm";
public PdpProperties() {
this.putAll(getServiceManager().getMetatypeDefaults(SYMBOLIC_NAME, FACTORY_PID));
}
}
public class CatalogPolicyProperties extends HashMap<String, Object> {
public static final String SYMBOLIC_NAME = "catalog-security-policyplugin";
public static final String FACTORY_PID = "org.codice.ddf.catalog.security.CatalogPolicy";
public CatalogPolicyProperties() {
this.putAll(getServiceManager().getMetatypeDefaults(SYMBOLIC_NAME, FACTORY_PID));
}
}
public static String getGetRecordByIdProductRetrievalUrl() {
return "?service=CSW&version=2.0.2&request=GetRecordById&NAMESPACE=xmlns="
+ "http://www.opengis.net/cat/csw/2.0.2&"
+ "outputFormat=application/octet-stream&outputSchema="
+ "http://www.iana.org/assignments/media-types/application/octet-stream&"
+ "id=placeholder_id";
}
public static String getSimpleXml(String uri) {
return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + getFileContent(
XML_RECORD_RESOURCE_PATH + "/SimpleXmlNoDecMetacard",
ImmutableMap.of("uri", uri));
}
public void configureShowInvalidMetacardsReset() throws IOException {
configureShowInvalidMetacards("false", "true", getAdminConfig());
}
public void configureFilterInvalidMetacardsReset() throws IOException {
configureFilterInvalidMetacards("true", "false", getAdminConfig());
}
protected void configureEnforceValidityErrorsAndWarningsReset() throws IOException {
configureEnforceValidityErrorsAndWarnings("true", "false", getAdminConfig());
}
}