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

asf-gitbox-commits pushed a commit to branch graphql-gate-processevents
in repository https://gitbox.apache.org/repos/asf/unomi.git

commit 437942a7ad73d4b564859d85baddfe680ca98522
Author: Serge Huber <[email protected]>
AuthorDate: Fri Aug 21 12:06:14 2026 +0200

    Apply the restricted-event-type gate to events submitted over GraphQL
    
    Events submitted through the processEvents mutation were handed straight
    to EventService.send(), which performs no authorization of its own, so
    they skipped the restricted-event-type check the REST event paths apply.
    Apply the same check before sending, and skip an event that does not pass
    it.
    
    This transport carries no source IP to match against a tenant's
    authorized IP list, so a restricted event type is refused whenever such a
    list is configured.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
 .../graphql/commands/ProcessEventsCommand.java     | 28 +++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git 
a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/ProcessEventsCommand.java
 
b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/ProcessEventsCommand.java
index e1a72ebb5..712c06d6e 100644
--- 
a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/ProcessEventsCommand.java
+++ 
b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/ProcessEventsCommand.java
@@ -20,7 +20,9 @@ import graphql.language.InputObjectTypeDefinition;
 import graphql.schema.GraphQLInputObjectField;
 import graphql.schema.GraphQLInputObjectType;
 import org.apache.unomi.api.Event;
+import org.apache.unomi.api.ExecutionContext;
 import org.apache.unomi.api.services.EventService;
+import org.apache.unomi.api.services.ExecutionContextManager;
 import org.apache.unomi.api.services.ProfileService;
 import org.apache.unomi.graphql.CDPGraphQLConstants;
 import org.apache.unomi.graphql.types.input.CDPConsentUpdateEventInput;
@@ -161,7 +163,14 @@ public class ProcessEventsCommand extends 
BaseCommand<Integer> {
     }
 
     private void processEvent(final Event event) {
-        int eventCode = 
serviceManager.getService(EventService.class).send(event);
+        final EventService eventService = 
serviceManager.getService(EventService.class);
+
+        if (!isEventAllowedForCurrentTenant(event, eventService)) {
+            LOGGER.debug("Event type {} is not authorized for this tenant, 
skipping it", event.getEventType());
+            return;
+        }
+
+        int eventCode = eventService.send(event);
 
         if (eventCode == EventService.PROFILE_UPDATED) {
             
serviceManager.getService(ProfileService.class).save(event.getProfile());
@@ -169,6 +178,23 @@ public class ProcessEventsCommand extends 
BaseCommand<Integer> {
         processedEventsQty.incrementAndGet();
     }
 
+    /**
+     * Applies the same restricted-event-type gate the REST event paths apply 
before handing an event to
+     * {@link EventService#send(Event)}, which performs no such check of its 
own. Without this, an event
+     * submitted through this mutation skipped a control the REST path 
enforces.
+     * <p>
+     * This transport carries no source IP to match against a tenant's 
authorized IP list, so a restricted
+     * event type is refused whenever such a list is configured.
+     */
+    private boolean isEventAllowedForCurrentTenant(final Event event, final 
EventService eventService) {
+        final ExecutionContextManager executionContextManager = 
serviceManager.getService(ExecutionContextManager.class);
+        final ExecutionContext executionContext = executionContextManager != 
null
+                ? executionContextManager.getCurrentContext() : null;
+        final String tenantId = executionContext != null ? 
executionContext.getTenantId() : null;
+
+        return eventService.isEventAllowedForTenant(event, tenantId, null);
+    }
+
     public static Builder create(final List<CDPEventInput> eventInputs) {
         return new Builder(eventInputs);
     }

Reply via email to