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
The following commit(s) were added to refs/heads/graphql-gate-processevents by
this push:
new ecbc97782 Cover the GraphQL restricted-event-type gate with unit tests.
ecbc97782 is described below
commit ecbc9778262f3b17947d7b17b364047843dba4e1
Author: Serge Huber <[email protected]>
AuthorDate: Thu Sep 17 12:27:10 2026 +0200
Cover the GraphQL restricted-event-type gate with unit tests.
---
.../graphql/commands/ProcessEventsCommand.java | 18 ++---
.../graphql/commands/ProcessEventsCommandTest.java | 82 ++++++++++++++++++++++
2 files changed, 91 insertions(+), 9 deletions(-)
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 712c06d6e..5d4147f58 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
@@ -165,7 +165,8 @@ public class ProcessEventsCommand extends
BaseCommand<Integer> {
private void processEvent(final Event event) {
final EventService eventService =
serviceManager.getService(EventService.class);
- if (!isEventAllowedForCurrentTenant(event, eventService)) {
+ if (!isEventAllowedForCurrentTenant(event, eventService,
+ serviceManager.getService(ExecutionContextManager.class))) {
LOGGER.debug("Event type {} is not authorized for this tenant,
skipping it", event.getEventType());
return;
}
@@ -179,15 +180,14 @@ public class ProcessEventsCommand extends
BaseCommand<Integer> {
}
/**
- * 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.
+ * Same restricted-event-type check as REST {@code EventService#send}
callers. GraphQL does not
+ * currently thread a client IP through this command, so the source IP is
{@code null}: a
+ * restricted type is refused when the tenant has an authorized-IP list,
and unrestricted types
+ * still pass.
*/
- private boolean isEventAllowedForCurrentTenant(final Event event, final
EventService eventService) {
- final ExecutionContextManager executionContextManager =
serviceManager.getService(ExecutionContextManager.class);
+ static boolean isEventAllowedForCurrentTenant(final Event event,
+ final EventService
eventService,
+ final
ExecutionContextManager executionContextManager) {
final ExecutionContext executionContext = executionContextManager !=
null
? executionContextManager.getCurrentContext() : null;
final String tenantId = executionContext != null ?
executionContext.getTenantId() : null;
diff --git
a/graphql/cxs-impl/src/test/java/org/apache/unomi/graphql/commands/ProcessEventsCommandTest.java
b/graphql/cxs-impl/src/test/java/org/apache/unomi/graphql/commands/ProcessEventsCommandTest.java
new file mode 100644
index 000000000..a387637c9
--- /dev/null
+++
b/graphql/cxs-impl/src/test/java/org/apache/unomi/graphql/commands/ProcessEventsCommandTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.commands;
+
+import org.apache.unomi.api.Event;
+import org.apache.unomi.api.ExecutionContext;
+import org.apache.unomi.api.Profile;
+import org.apache.unomi.api.services.EventService;
+import org.apache.unomi.api.services.ExecutionContextManager;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class ProcessEventsCommandTest {
+
+ private static final String TENANT_ID = "tenant-1";
+
+ @Mock
+ private EventService eventService;
+ @Mock
+ private ExecutionContextManager executionContextManager;
+ @Mock
+ private ExecutionContext executionContext;
+
+ @Test
+ void allowsEventWhenTenantGatePasses() {
+ Event event = viewEvent();
+
when(executionContextManager.getCurrentContext()).thenReturn(executionContext);
+ when(executionContext.getTenantId()).thenReturn(TENANT_ID);
+ when(eventService.isEventAllowedForTenant(event, TENANT_ID,
null)).thenReturn(true);
+
+ assertTrue(ProcessEventsCommand.isEventAllowedForCurrentTenant(event,
eventService, executionContextManager));
+ verify(eventService).isEventAllowedForTenant(event, TENANT_ID, null);
+ }
+
+ @Test
+ void refusesEventWhenTenantGateFails() {
+ Event event = viewEvent();
+
when(executionContextManager.getCurrentContext()).thenReturn(executionContext);
+ when(executionContext.getTenantId()).thenReturn(TENANT_ID);
+ when(eventService.isEventAllowedForTenant(event, TENANT_ID,
null)).thenReturn(false);
+
+ assertFalse(ProcessEventsCommand.isEventAllowedForCurrentTenant(event,
eventService, executionContextManager));
+ verify(eventService).isEventAllowedForTenant(event, TENANT_ID, null);
+ }
+
+ @Test
+ void passesNullTenantWhenThereIsNoExecutionContext() {
+ Event event = viewEvent();
+ when(eventService.isEventAllowedForTenant(event, null,
null)).thenReturn(false);
+
+ assertFalse(ProcessEventsCommand.isEventAllowedForCurrentTenant(event,
eventService, null));
+ verify(eventService).isEventAllowedForTenant(event, null, null);
+ }
+
+ private static Event viewEvent() {
+ return new Event("view", null, new Profile(), null, null, null, new
Date());
+ }
+}