/* * Copyright 2016 Crown Copyright * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package uk.gov.gchq.gaffer.integration.impl; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.junit.Test; import uk.gov.gchq.gaffer.commonutil.TestGroups; import uk.gov.gchq.gaffer.commonutil.TestPropertyNames; import uk.gov.gchq.gaffer.commonutil.TestTypes; import uk.gov.gchq.gaffer.commonutil.iterable.CloseableIterable; import uk.gov.gchq.gaffer.data.element.Element; import uk.gov.gchq.gaffer.data.element.Entity; import uk.gov.gchq.gaffer.graph.Graph; import uk.gov.gchq.gaffer.integration.AbstractStoreIT; import uk.gov.gchq.gaffer.integration.TraitRequirement; import uk.gov.gchq.gaffer.operation.OperationException; import uk.gov.gchq.gaffer.operation.data.EntitySeed; import uk.gov.gchq.gaffer.operation.impl.add.AddElements; import uk.gov.gchq.gaffer.operation.impl.get.GetElements; import uk.gov.gchq.gaffer.serialisation.implementation.StringSerialiser; import uk.gov.gchq.gaffer.store.StoreTrait; import uk.gov.gchq.gaffer.store.schema.Schema; import uk.gov.gchq.gaffer.store.schema.SchemaEntityDefinition; import uk.gov.gchq.gaffer.store.schema.TypeDefinition; import uk.gov.gchq.gaffer.user.User; import uk.gov.gchq.koryphe.impl.binaryoperator.StringConcat; import java.util.HashSet; import java.util.List; import java.util.Set; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.isEmptyString; import static org.hamcrest.collection.IsCollectionWithSize.hasSize; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; public class VisibilityIT extends AbstractStoreIT { private static final User USER_DEFAULT = new User(); private static final User USER_VIS_1 = new User.Builder().dataAuth("vis1") .build(); private static final User USER_VIS_2 = new User.Builder().dataAuth("vis2") .build(); @Test @TraitRequirement(StoreTrait.VISIBILITY) public void shouldAccessMissingVisibilityGroups() throws OperationException, JsonProcessingException { final Set<Element> elements = new HashSet<>(); final Entity entity1 = new Entity(TestGroups.ENTITY, "A"); // Do NOT add an explicit visibility property // entity1.putProperty(AccumuloPropertyNames.VISIBILITY, ""); elements.add(entity1); final AddElements addElements = new AddElements.Builder() .input(elements) .build(); graph.execute(addElements, USER_DEFAULT); final GetElements get = new GetElements.Builder() .input(new EntitySeed("A")) .build(); final CloseableIterable<? extends Element> iterable = graph.execute(get, USER_DEFAULT); final List<Element> results = Lists.newArrayList(iterable); // Check for all entities which should be visible assertThat("Results do not contain all expected entities.", results, hasSize(1)); for (final Element e : results) { // Check that all visible entities contain the visibility property assertTrue("Visibility property should be visible.", e.getProperties() .containsKey(TestTypes.VISIBILITY)); assertThat("Visibility property should contain an empty String.", e.getProperties() .get(TestTypes.VISIBILITY) .toString(), isEmptyString()); } iterable.close(); } @Test @TraitRequirement(StoreTrait.VISIBILITY) public void shouldAccessMissingVisibilityGroupsWithNoVisibilityPropertyInSchema() throws OperationException, JsonProcessingException { graph = createGraphWithNoVisibility(); final Set<Element> elements = new HashSet<>(); final Entity entity1 = new Entity(TestGroups.ENTITY, "A"); elements.add(entity1); final AddElements addElements = new AddElements.Builder() .input(elements) .build(); graph.execute(addElements, USER_DEFAULT); final GetElements get = new GetElements.Builder() .input(new EntitySeed("A")) .build(); final CloseableIterable<? extends Element> iterable = graph.execute(get, USER_DEFAULT); final List<Element> results = Lists.newArrayList(iterable); // Check for all entities which should be visible assertThat("Results do not contain all expected entities.", results, hasSize(1)); for (final Element e : results) { // Check that all visible entities do not contain the visibility property assertFalse("Visibility property should not be visible.", e.getProperties() .containsKey(TestTypes.VISIBILITY)); } iterable.close(); } @Test @TraitRequirement(StoreTrait.VISIBILITY) public void shouldAccessEmptyVisibilityGroups() throws OperationException, JsonProcessingException { final Set<Element> elements = new HashSet<>(); final Entity entity1 = new Entity(TestGroups.ENTITY, "A"); entity1.putProperty(TestTypes.VISIBILITY, ""); elements.add(entity1); final AddElements addElements = new AddElements.Builder() .input(elements) .build(); graph.execute(addElements, USER_DEFAULT); final GetElements get = new GetElements.Builder() .input(new EntitySeed("A")) .build(); final CloseableIterable<? extends Element> iterable = graph.execute(get, USER_DEFAULT); final List<Element> results = Lists.newArrayList(iterable); // Check for all entities which should be visible assertThat("Results do not contain all expected entities.", results, hasSize(1)); for (final Element e : results) { // Check that all visible entities contain the visibility property assertTrue("Visibility property should be visible.", e.getProperties() .containsKey(TestTypes.VISIBILITY)); assertThat("Visibility property should contain an empty String.", e.getProperties() .get(TestTypes.VISIBILITY) .toString(), isEmptyString()); } iterable.close(); } @Test @TraitRequirement(StoreTrait.VISIBILITY) public void shouldAccessNullVisibilityGroups() throws OperationException, JsonProcessingException { final Set<Element> elements = new HashSet<>(); final Entity entity1 = new Entity(TestGroups.ENTITY, "A"); entity1.putProperty(TestTypes.VISIBILITY, null); elements.add(entity1); final AddElements addElements = new AddElements.Builder() .input(elements) .build(); graph.execute(addElements, USER_DEFAULT); final GetElements get = new GetElements.Builder() .input(new EntitySeed("A"), new EntitySeed("B")) .build(); final CloseableIterable<? extends Element> iterable = graph.execute(get, USER_DEFAULT); final List<Element> results = Lists.newArrayList(iterable); // Check for all entities which should be visible assertThat("Results do not contain all expected entities.", results, hasSize(1)); for (final Element e : results) { // Check that all visible entities contain the visibility property assertTrue("Visibility property should be visible.", e.getProperties() .containsKey(TestTypes.VISIBILITY)); assertThat("Visibility property should contain an empty String.", e.getProperties() .get(TestTypes.VISIBILITY) .toString(), isEmptyString()); } iterable.close(); } @Test @TraitRequirement(StoreTrait.VISIBILITY) public void shouldAccessSingleVisibilityGroup() throws OperationException { final Set<Element> elements = new HashSet<>(); final Entity entity1 = new Entity(TestGroups.ENTITY, "A"); entity1.putProperty(TestTypes.VISIBILITY, "vis1"); final Entity entity2 = new Entity(TestGroups.ENTITY, "B"); entity2.putProperty(TestTypes.VISIBILITY, "vis1"); elements.add(entity1); elements.add(entity2); final AddElements addElements = new AddElements.Builder() .input(elements) .build(); graph.execute(addElements, USER_VIS_1); final GetElements get = new GetElements.Builder() .input(new EntitySeed("A"), new EntitySeed("B")) .build(); final CloseableIterable<? extends Element> userVis1Iterable = graph.execute(get, USER_VIS_1); final CloseableIterable<? extends Element> userVis2Iterable = graph.execute(get, USER_VIS_2); final List<Element> userVis1Results = Lists.newArrayList(userVis1Iterable); final List<Element> userVis2Results = Lists.newArrayList(userVis2Iterable); assertThat(userVis1Results, hasSize(2)); assertThat(userVis2Results, is(empty())); for (final Element e : userVis1Results) { // Check that all visible entities contain the visibility property assertTrue("Missing visibility property.", e.getProperties() .containsKey(TestTypes.VISIBILITY)); // Check that the visibility key contai // ns the correct value assertEquals("Visibility property should be \"vis1\"", e.getProperties() .get(TestTypes.VISIBILITY) .toString(), "vis1"); } userVis1Iterable.close(); userVis2Iterable.close(); } @Test @TraitRequirement(StoreTrait.VISIBILITY) public void shouldAccessMultipleVisibilityGroups_and() throws OperationException { final Set<Element> elements = new HashSet<>(); final Entity entity1 = new Entity(TestGroups.ENTITY, "B"); entity1.putProperty(TestTypes.VISIBILITY, "vis1&vis2"); elements.add(entity1); final AddElements addElements = new AddElements.Builder() .input(elements) .build(); graph.execute(addElements, new User()); final GetElements get = new GetElements.Builder() .input(new EntitySeed("B")) .build(); final CloseableIterable<? extends Element> iterable = graph.execute(get, new User(User.UNKNOWN_USER_ID, Sets .newHashSet("vis1", "vis2"))); final List<Element> results = Lists.newArrayList(iterable); assertThat("Results do not contain all expected Elements.", results, hasSize(1)); for (final Element e : iterable) { assertTrue(e.getProperties() .containsKey(TestTypes.VISIBILITY)); } iterable.close(); } @Test @TraitRequirement(StoreTrait.VISIBILITY) public void shouldAccessMultipleVisibilityGroups_or() throws OperationException { final Set<Element> elements = new HashSet<>(); final Entity entity1 = new Entity(TestGroups.ENTITY, "B"); entity1.putProperty(TestTypes.VISIBILITY, "vis1|vis2"); elements.add(entity1); final AddElements addElements = new AddElements.Builder() .input(elements) .build(); graph.execute(addElements, new User()); final GetElements get = new GetElements.Builder() .input(new EntitySeed("B")) .build(); final CloseableIterable<? extends Element> iterable = graph.execute(get, new User(User.UNKNOWN_USER_ID, Sets .newHashSet("vis1"))); final List<Element> results = Lists.newArrayList(iterable); assertThat("Results do not contain all expected Elements.", results, hasSize(1)); for (final Element e : results) { assertTrue(e.getProperties() .containsKey(TestTypes.VISIBILITY)); } iterable.close(); } @Override protected Schema createSchema() { return new Schema.Builder() .merge(super.createSchema()) .type(TestTypes.VISIBILITY, new TypeDefinition.Builder() .clazz(String.class) .aggregateFunction(new StringConcat()) .serialiser(new StringSerialiser()) .build()) .entity(TestGroups.ENTITY, new SchemaEntityDefinition.Builder() .vertex(TestTypes.ID_STRING) .property(TestPropertyNames.STRING, TestTypes.PROP_STRING) .property(TestTypes.VISIBILITY, TestTypes.VISIBILITY) .groupBy(TestPropertyNames.INT) .build()) .visibilityProperty(TestTypes.VISIBILITY) .build(); } private Schema createSchemaNoVisibility() { return new Schema.Builder() .type(TestTypes.ID_STRING, new TypeDefinition.Builder() .clazz(String.class) .build()) .entity(TestGroups.ENTITY, new SchemaEntityDefinition.Builder() .vertex(TestTypes.ID_STRING) .build()) .build(); } private Graph createGraphWithNoVisibility() { return new Graph.Builder() .storeProperties(getStoreProperties()) .addSchema(createSchemaNoVisibility()) .addSchema(getStoreSchema()) .build(); } }