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); }
