You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by pm...@apache.org on 2021/06/23 09:13:16 UTC

[unomi] branch issue-474 created (now bffdccc)

This is an automated email from the ASF dual-hosted git repository.

pmi pushed a change to branch issue-474
in repository https://gitbox.apache.org/repos/asf/unomi.git.


      at bffdccc  UNOMI-474 Add priorities to GraphQL field visibility providers

This branch includes the following new commits:

     new bffdccc  UNOMI-474 Add priorities to GraphQL field visibility providers

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[unomi] 01/01: UNOMI-474 Add priorities to GraphQL field visibility providers

Posted by pm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

pmi pushed a commit to branch issue-474
in repository https://gitbox.apache.org/repos/asf/unomi.git

commit bffdccc6c80f17d357f13ffe4ca5a58730f256ce
Author: Pavel Milkevich <pa...@gmail.com>
AuthorDate: Wed Jun 23 12:12:48 2021 +0300

    UNOMI-474 Add priorities to GraphQL field visibility providers
---
 .../providers/CompositeGraphQLFieldVisibility.java | 109 +++++++++++++++++++++
 .../providers/GraphQLFieldVisibilityProvider.java  |   5 +-
 .../graphql/schema/GraphQLSchemaProvider.java      |  20 ++--
 .../unomi/graphql/schema/GraphQLSchemaUpdater.java |  12 +--
 .../providers/sample/CDPProviderSample.java        |   5 +
 .../sample/CDPVisibilityOnlyProvider.java          |  57 +++++++++++
 6 files changed, 192 insertions(+), 16 deletions(-)

diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/providers/CompositeGraphQLFieldVisibility.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/providers/CompositeGraphQLFieldVisibility.java
new file mode 100644
index 0000000..d304314
--- /dev/null
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/providers/CompositeGraphQLFieldVisibility.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.unomi.graphql.providers;
+
+import com.google.common.collect.Lists;
+import graphql.schema.GraphQLFieldDefinition;
+import graphql.schema.GraphQLFieldsContainer;
+import graphql.schema.GraphQLInputFieldsContainer;
+import graphql.schema.GraphQLInputObjectField;
+import graphql.schema.GraphQLNamedSchemaElement;
+import graphql.schema.visibility.GraphqlFieldVisibility;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+public class CompositeGraphQLFieldVisibility implements GraphqlFieldVisibility {
+
+    private final List<GraphQLFieldVisibilityProvider> providers;
+
+    public CompositeGraphQLFieldVisibility(List<GraphQLFieldVisibilityProvider> providers) {
+        this.providers = providers;
+        if (providers != null && !providers.isEmpty()) {
+            providers.sort(Comparator.comparingInt(GraphQLFieldVisibilityProvider::getPriority).reversed());
+        }
+    }
+
+    @Override
+    public List<GraphQLFieldDefinition> getFieldDefinitions(GraphQLFieldsContainer fieldsContainer) {
+        if (providers == null) {
+            return Lists.newArrayList();
+        }
+        return providers.stream().
+                map(provider -> provider.getGraphQLFieldVisibility().getFieldDefinitions(fieldsContainer)).
+                reduce(CompositeGraphQLFieldVisibility::intersect).
+                orElse(Lists.newArrayList());
+    }
+
+    @Override
+    public GraphQLFieldDefinition getFieldDefinition(GraphQLFieldsContainer fieldsContainer, String fieldName) {
+        if (providers == null) {
+            return null;
+        }
+        List<GraphQLFieldDefinition> list = providers.stream().
+                map(provider -> provider.getGraphQLFieldVisibility().getFieldDefinition(fieldsContainer, fieldName)).
+                collect(Collectors.toList());
+
+        return extractWithPriority(list);
+    }
+
+    @Override
+    public List<GraphQLInputObjectField> getFieldDefinitions(GraphQLInputFieldsContainer fieldsContainer) {
+        if (providers == null) {
+            return Lists.newArrayList();
+        }
+        return providers.stream().
+                map(provider -> provider.getGraphQLFieldVisibility().getFieldDefinitions(fieldsContainer)).
+                reduce(CompositeGraphQLFieldVisibility::intersect).
+                orElse(Lists.newArrayList());
+    }
+
+    @Override
+    public GraphQLInputObjectField getFieldDefinition(GraphQLInputFieldsContainer fieldsContainer, String fieldName) {
+        if (providers == null) {
+            return null;
+        }
+        List<GraphQLInputObjectField> list = providers.stream().
+                map(provider -> provider.getGraphQLFieldVisibility().getFieldDefinition(fieldsContainer, fieldName)).
+                collect(Collectors.toList());
+
+        return extractWithPriority(list);
+    }
+
+    private static <T extends GraphQLNamedSchemaElement> List<T> intersect(List<T> prev, List<T> curr) {
+        return curr.
+                stream().
+                distinct().
+                filter(prev::contains).
+                collect(Collectors.toList());
+    }
+
+    private static <T> T extractWithPriority(List<T> list) {
+        boolean anyBlocks = list.stream().anyMatch(Objects::isNull);
+        boolean noItems = list.size() == 0;
+        if (anyBlocks || noItems) {
+            // some provider blocks it or none describes at all
+            return null;
+        } else {
+            // return first as they are sorted by priority
+            return list.get(0);
+        }
+    }
+}
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/providers/GraphQLFieldVisibilityProvider.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/providers/GraphQLFieldVisibilityProvider.java
index a835030..5aef2c1 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/providers/GraphQLFieldVisibilityProvider.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/providers/GraphQLFieldVisibilityProvider.java
@@ -19,11 +19,12 @@ package org.apache.unomi.graphql.providers;
 import graphql.schema.visibility.GraphqlFieldVisibility;
 
 /**
- *  Provider of {@link GraphqlFieldVisibility} to limit graphql schema fields visibility
- *  More about it here https://www.graphql-java.com/documentation/v14/fieldvisibility/
+ * Provider of {@link GraphqlFieldVisibility} to limit graphql schema fields visibility
+ * More about it here https://www.graphql-java.com/documentation/v14/fieldvisibility/
  */
 public interface GraphQLFieldVisibilityProvider extends GraphQLProvider {
 
     GraphqlFieldVisibility getGraphQLFieldVisibility();
 
+    int getPriority();
 }
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java
index 8ea7193..a0ac1fa 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java
@@ -32,6 +32,7 @@ import graphql.schema.GraphQLObjectType;
 import graphql.schema.GraphQLOutputType;
 import graphql.schema.GraphQLSchema;
 import graphql.schema.GraphQLType;
+import graphql.schema.visibility.GraphqlFieldVisibility;
 import org.apache.unomi.api.EventType;
 import org.apache.unomi.api.PropertyType;
 import org.apache.unomi.api.services.EventTypeRegistry;
@@ -43,6 +44,7 @@ import org.apache.unomi.graphql.fetchers.CustomerPropertyDataFetcher;
 import org.apache.unomi.graphql.fetchers.DynamicFieldDataFetcher;
 import org.apache.unomi.graphql.fetchers.event.EventListenerSubscriptionFetcher;
 import org.apache.unomi.graphql.fetchers.event.UnomiEventPublisher;
+import org.apache.unomi.graphql.providers.CompositeGraphQLFieldVisibility;
 import org.apache.unomi.graphql.providers.GraphQLAdditionalTypesProvider;
 import org.apache.unomi.graphql.providers.GraphQLCodeRegistryProvider;
 import org.apache.unomi.graphql.providers.GraphQLExtensionsProvider;
@@ -100,7 +102,7 @@ public class GraphQLSchemaProvider {
 
     private final List<GraphQLSubscriptionProvider> subscriptionProviders;
 
-    private final GraphQLFieldVisibilityProvider fieldVisibilityProvider;
+    private final List<GraphQLFieldVisibilityProvider> fieldVisibilityProviders;
 
     private final GraphQLCodeRegistryProvider codeRegistryProvider;
 
@@ -121,7 +123,7 @@ public class GraphQLSchemaProvider {
         this.mutationProviders = builder.mutationProviders;
         this.subscriptionProviders = builder.subscriptionProviders;
         this.codeRegistryProvider = builder.codeRegistryProvider;
-        this.fieldVisibilityProvider = builder.fieldVisibilityProvider;
+        this.fieldVisibilityProviders = builder.fieldVisibilityProviders;
     }
 
     public GraphQLSchema createSchema() {
@@ -679,10 +681,12 @@ public class GraphQLSchemaProvider {
     }
 
     private void configureFieldVisibility() {
-        if (fieldVisibilityProvider != null) {
-            graphQLAnnotations.getContainer().getCodeRegistryBuilder()
-                    .fieldVisibility(fieldVisibilityProvider.getGraphQLFieldVisibility());
+        if (fieldVisibilityProviders == null || fieldVisibilityProviders.isEmpty()) {
+            return;
         }
+        GraphqlFieldVisibility compositeVisibility = new CompositeGraphQLFieldVisibility(fieldVisibilityProviders);
+
+        graphQLAnnotations.getContainer().getCodeRegistryBuilder().fieldVisibility(compositeVisibility);
     }
 
     public GraphQLInputObjectType getInputObjectType(final Class<?> annotatedClass) {
@@ -717,7 +721,7 @@ public class GraphQLSchemaProvider {
 
         List<GraphQLSubscriptionProvider> subscriptionProviders;
 
-        GraphQLFieldVisibilityProvider fieldVisibilityProvider;
+        List<GraphQLFieldVisibilityProvider> fieldVisibilityProviders;
 
         GraphQLCodeRegistryProvider codeRegistryProvider;
 
@@ -768,8 +772,8 @@ public class GraphQLSchemaProvider {
             return this;
         }
 
-        public Builder fieldVisibilityProvider(GraphQLFieldVisibilityProvider fieldVisibilityProvider) {
-            this.fieldVisibilityProvider = fieldVisibilityProvider;
+        public Builder fieldVisibilityProviders(List<GraphQLFieldVisibilityProvider> fieldVisibilityProviders) {
+            this.fieldVisibilityProviders = fieldVisibilityProviders;
             return this;
         }
 
diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaUpdater.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaUpdater.java
index 73a7712..dac986a 100644
--- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaUpdater.java
+++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaUpdater.java
@@ -73,7 +73,7 @@ public class GraphQLSchemaUpdater {
 
     private final List<GraphQLTypeFunctionProvider> typeFunctionProviders = new CopyOnWriteArrayList<>();
 
-    private GraphQLFieldVisibilityProvider fieldVisibilityProvider;
+    private List<GraphQLFieldVisibilityProvider> fieldVisibilityProviders = new CopyOnWriteArrayList<>();
 
     private GraphQLCodeRegistryProvider codeRegistryProvider;
 
@@ -165,7 +165,7 @@ public class GraphQLSchemaUpdater {
             additionalTypesProviders.add((GraphQLAdditionalTypesProvider) provider);
         }
         if (provider instanceof GraphQLFieldVisibilityProvider) {
-            fieldVisibilityProvider = (GraphQLFieldVisibilityProvider) provider;
+            fieldVisibilityProviders.add((GraphQLFieldVisibilityProvider) provider);
         }
         if (provider instanceof GraphQLCodeRegistryProvider) {
             codeRegistryProvider = (GraphQLCodeRegistryProvider) provider;
@@ -187,7 +187,7 @@ public class GraphQLSchemaUpdater {
             additionalTypesProviders.remove(provider);
         }
         if (provider instanceof GraphQLFieldVisibilityProvider) {
-            fieldVisibilityProvider = null;
+            fieldVisibilityProviders.remove(provider);
         }
         if (provider instanceof GraphQLCodeRegistryProvider) {
             codeRegistryProvider = GraphQLCodeRegistry::newCodeRegistry;
@@ -237,13 +237,13 @@ public class GraphQLSchemaUpdater {
 
     @Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
     public void bindFieldVisibilityProvider(GraphQLFieldVisibilityProvider provider) {
-        fieldVisibilityProvider = provider;
+        fieldVisibilityProviders.remove(provider);
 
         updateSchema();
     }
 
     public void unbindFieldVisibilityProvider(GraphQLFieldVisibilityProvider provider) {
-        fieldVisibilityProvider = null;
+        fieldVisibilityProviders = null;
 
         updateSchema();
     }
@@ -339,7 +339,7 @@ public class GraphQLSchemaUpdater {
                 .subscriptionProviders(subscriptionProviders)
                 .eventPublisher(eventPublisher)
                 .codeRegistryProvider(codeRegistryProvider)
-                .fieldVisibilityProvider(fieldVisibilityProvider)
+                .fieldVisibilityProviders(fieldVisibilityProviders)
                 .build();
 
         final GraphQLSchema schema = schemaProvider.createSchema();
diff --git a/samples/graphql-providers/src/main/java/org/apache/unomi/graphql/providers/sample/CDPProviderSample.java b/samples/graphql-providers/src/main/java/org/apache/unomi/graphql/providers/sample/CDPProviderSample.java
index 8f688d4..8d2f7b0 100644
--- a/samples/graphql-providers/src/main/java/org/apache/unomi/graphql/providers/sample/CDPProviderSample.java
+++ b/samples/graphql-providers/src/main/java/org/apache/unomi/graphql/providers/sample/CDPProviderSample.java
@@ -148,4 +148,9 @@ public class CDPProviderSample
                 .addPattern(".*\\.delete.*") // regular expressions allowed
                 .build();
     }
+
+    @Override
+    public int getPriority() {
+        return 0;
+    }
 }
diff --git a/samples/graphql-providers/src/main/java/org/apache/unomi/graphql/providers/sample/CDPVisibilityOnlyProvider.java b/samples/graphql-providers/src/main/java/org/apache/unomi/graphql/providers/sample/CDPVisibilityOnlyProvider.java
new file mode 100644
index 0000000..c48f6b3
--- /dev/null
+++ b/samples/graphql-providers/src/main/java/org/apache/unomi/graphql/providers/sample/CDPVisibilityOnlyProvider.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.unomi.graphql.providers.sample;
+
+import graphql.schema.visibility.BlockedFields;
+import graphql.schema.visibility.GraphqlFieldVisibility;
+import org.apache.unomi.graphql.providers.GraphQLFieldVisibilityProvider;
+import org.apache.unomi.graphql.providers.GraphQLProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+
+@Component(immediate = true, service = GraphQLProvider.class)
+public class CDPVisibilityOnlyProvider
+        implements GraphQLFieldVisibilityProvider {
+
+    private boolean isActivated;
+
+    @Activate
+    public void activate(final BundleContext context) {
+        this.isActivated = true;
+    }
+
+    @Deactivate
+    public void deactivate() {
+        this.isActivated = false;
+    }
+
+    @Override
+    public GraphqlFieldVisibility getGraphQLFieldVisibility() {
+        // Blocks fields based on patterns
+        return BlockedFields.newBlock()
+                .addPattern("CDP_SegmentInput.view")
+                .addPattern(".*\\.remove.*") // regular expressions allowed
+                .build();
+    }
+
+    @Override
+    public int getPriority() {
+        return 1;
+    }
+}