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

dominikriemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/dev by this push:
     new dd42d00372 fix(#4687): kiosk mode does not show data for logged out 
users (#4689)
dd42d00372 is described below

commit dd42d003721aa6e8fa164cdc79d8dcaad42b44b3
Author: Philipp Zehnder <[email protected]>
AuthorDate: Mon Jul 6 21:39:19 2026 +0200

    fix(#4687): kiosk mode does not show data for logged out users (#4689)
---
 .../datalake/KioskDashboardDataLakeResource.java   | 27 --------
 .../service/core/UnauthenticatedInterfaces.java    |  2 +-
 ui/cypress/support/utils/dashboard/Inspector.ts    | 36 ++++++++++-
 ui/cypress/tests/chart/publicDashboardLink.spec.ts | 71 ++++++++++++++++------
 .../src/lib/apis/dashboard-kiosk.service.ts        | 12 ----
 .../lib/query/data-view-query-generator.service.ts | 28 ---------
 6 files changed, 89 insertions(+), 87 deletions(-)

diff --git 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/KioskDashboardDataLakeResource.java
 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/KioskDashboardDataLakeResource.java
index b513405bff..401e3ac7af 100644
--- 
a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/KioskDashboardDataLakeResource.java
+++ 
b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/KioskDashboardDataLakeResource.java
@@ -71,33 +71,6 @@ public class KioskDashboardDataLakeResource extends 
AbstractAuthGuardedRestResou
     this.permissionStorage = resourceManager.managePermissions().getDb();
   }
 
-  @PostMapping(path = "/{dashboardId}/{widgetId}/data",
-      consumes = MediaType.APPLICATION_JSON_VALUE,
-      produces = MediaType.APPLICATION_JSON_VALUE)
-  @PreAuthorize("this.hasReadAuthorityOrAnonymous(#dashboardId) and 
hasPermission(#dashboardId, 'READ')")
-  public ResponseEntity<?> getData(@PathVariable("dashboardId") String 
dashboardId,
-                                   @PathVariable("widgetId") String widgetId,
-                                   @RequestBody Map<String, String> 
queryParams) {
-    var dashboard = dashboardStorage.getElementById(dashboardId);
-    if (dashboard.getWidgets().stream().noneMatch(w -> 
w.getDataViewElementId().equals(widgetId))) {
-      return badRequest(String.format("Widget with id %s not found in 
dashboard", widgetId));
-    }
-    var widget = dataExplorerWidgetStorage.getElementById(widgetId);
-    var measureName = queryParams.get("measureName");
-    if (!checkMeasureNameInWidget(widget, measureName)) {
-     return badRequest("Measure name not found in widget configuration");
-    } else {
-      ProvidedRestQueryParams sanitizedParams = new 
ProvidedRestQueryParams(measureName, queryParams);
-      try {
-        SpQueryResult result =
-            this.dataExplorerQueryManagement.getData(sanitizedParams, true);
-        return ok(result);
-      } catch (RuntimeException e) {
-        return badRequest(SpLogMessage.from(e));
-      }
-    }
-  }
-
   @PostMapping(path = "/{dashboardId}/data",
       consumes = MediaType.APPLICATION_JSON_VALUE,
       produces = MediaType.APPLICATION_JSON_VALUE)
diff --git 
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/UnauthenticatedInterfaces.java
 
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/UnauthenticatedInterfaces.java
index 774de0c1ea..a151eca694 100644
--- 
a/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/UnauthenticatedInterfaces.java
+++ 
b/streampipes-service-core/src/main/java/org/apache/streampipes/service/core/UnauthenticatedInterfaces.java
@@ -47,7 +47,7 @@ public class UnauthenticatedInterfaces {
         "/streampipes-backend/index.html",
         // anonymous dashboard access is allowed
         "/api/v3/datalake/dashboard/*/composite",
-        "/api/v3/datalake/dashboard/kiosk/*/*/data"
+        "/api/v3/datalake/dashboard/kiosk/*/data"
     );
   }
 }
diff --git a/ui/cypress/support/utils/dashboard/Inspector.ts 
b/ui/cypress/support/utils/dashboard/Inspector.ts
index 8f862fb981..d5075efd5f 100644
--- a/ui/cypress/support/utils/dashboard/Inspector.ts
+++ b/ui/cypress/support/utils/dashboard/Inspector.ts
@@ -42,7 +42,22 @@ export class Inspector {
         cy.visit(`#/dashboard-kiosk/${dashboardId}`);
     }
 
-    public static validateDashboardKioskWithTableChart(dashboardName: string) {
+    public static openDashboardKioskAsLoggedOutUser(dashboardId: string) {
+        cy.clearLocalStorage();
+        cy.clearCookies();
+        cy.visit(`#/dashboard-kiosk/${dashboardId}`, {
+            onBeforeLoad: win => {
+                win.localStorage.clear();
+                win.sessionStorage.clear();
+                expect(win.localStorage.getItem('auth-token')).to.equal(null);
+            },
+        });
+    }
+
+    public static validateDashboardKioskWithTableChart(
+        dashboardName: string,
+        expectedColumns: string[] = [],
+    ) {
         cy.contains('.dashboard-title', dashboardName, {
             timeout: 10000,
         }).should('be.visible');
@@ -56,5 +71,24 @@ export class Inspector {
         )
             .filter(':visible')
             .should('have.length.at.least', 1);
+
+        expectedColumns.forEach(column => {
+            if (column === 'time') {
+                cy.dataCy('data-explorer-table-row-timestamp', {
+                    timeout: 10000,
+                })
+                    .filter(':visible')
+                    .should('have.length.at.least', 1);
+            } else {
+                cy.dataCy(`data-explorer-table-header-${column}`, {
+                    timeout: 10000,
+                }).should('be.visible');
+                cy.dataCy(`data-explorer-table-row-${column}`, {
+                    timeout: 10000,
+                })
+                    .filter(':visible')
+                    .should('have.length.at.least', 1);
+            }
+        });
     }
 }
diff --git a/ui/cypress/tests/chart/publicDashboardLink.spec.ts 
b/ui/cypress/tests/chart/publicDashboardLink.spec.ts
index e88dceaea9..a2e506c92e 100644
--- a/ui/cypress/tests/chart/publicDashboardLink.spec.ts
+++ b/ui/cypress/tests/chart/publicDashboardLink.spec.ts
@@ -17,33 +17,68 @@
  */
 
 import { ChartUtils } from '../../support/utils/chart/ChartUtils';
+import { DataLakeSeedUtils } from 
'../../support/utils/dataset/DataLakeSeedUtils';
 import { Inspector } from '../../support/utils/dashboard/Inspector';
 import { PermissionUtils } from '../../support/utils/user/PermissionUtils';
 
-describe('Public dashboard links', () => {
-    const dashboardName = 'public-dashboard';
-    const chartName = 'public-dashboard-chart';
+const dashboardName = 'public-dashboard';
+const chartName = 'public-dashboard-chart';
+const tableColumns = ['time', 'randombool', 'randomnumber', 'randomtext'];
 
+describe('Public dashboard links', () => {
     beforeEach('Setup Test', () => {
         cy.initStreamPipesTest();
-        ChartUtils.loadDataIntoDataLake('datalake/sample.csv');
+        DataLakeSeedUtils.importCsvData({
+            headers: ['timestamp', 'randombool', 'randomnumber', 'randomtext'],
+            rows: kioskTableRows(),
+            measurementName: ChartUtils.ADAPTER_NAME,
+            timestampColumn: 'timestamp',
+            columnOverrides: {
+                randomtext: {
+                    propertyScope: 'DIMENSION_PROPERTY',
+                },
+            },
+        });
     });
 
-    it('allows anonymous users to view a dashboard with a chart', () => {
-        ChartUtils.addDataViewAndTableWidget(ChartUtils.ADAPTER_NAME);
-        ChartUtils.saveDataViewConfiguration(false, false, chartName);
+    it('allows logged-out users to view all table columns in kiosk mode', () 
=> {
+        createPublicDashboardWithTableChart();
 
-        ChartUtils.goToDashboard();
-        ChartUtils.createAndEditDashboard(dashboardName);
-        ChartUtils.addDataViewToDashboard(chartName, true);
-        ChartUtils.saveDashboardConfiguration();
-
-        PermissionUtils.markElementAsAnonymousPublic(dashboardName);
-        PermissionUtils.validateAnonymousPublicLinkIsEnabled(dashboardName);
-
-        Inspector.getDashboardIdByName(dashboardName).then(dashboardId => {
-            Inspector.openDashboardKioskAsAnonymous(dashboardId);
-            Inspector.validateDashboardKioskWithTableChart(dashboardName);
+        getDashboardId().then(dashboardId => {
+            cy.logout();
+            cy.location('hash', { timeout: 10000 }).should('eq', '#/login');
+            Inspector.openDashboardKioskAsLoggedOutUser(dashboardId);
+            Inspector.validateDashboardKioskWithTableChart(
+                dashboardName,
+                tableColumns,
+            );
         });
     });
 });
+
+function createPublicDashboardWithTableChart(): void {
+    ChartUtils.addDataViewAndTableWidget(ChartUtils.ADAPTER_NAME);
+    ChartUtils.saveDataViewConfiguration(false, false, chartName);
+
+    ChartUtils.goToDashboard();
+    ChartUtils.createAndEditDashboard(dashboardName);
+    ChartUtils.addDataViewToDashboard(chartName, true);
+    ChartUtils.saveDashboardConfiguration();
+
+    PermissionUtils.markElementAsAnonymousPublic(dashboardName);
+    PermissionUtils.validateAnonymousPublicLinkIsEnabled(dashboardName);
+}
+
+function getDashboardId() {
+    return Inspector.getDashboardIdByName(dashboardName);
+}
+
+function kioskTableRows(): string[][] {
+    const baseTimestamp = Date.now() - 60_000;
+
+    return [
+        [baseTimestamp.toString(), 'true', '62.0', 'c'],
+        [(baseTimestamp + 1_000).toString(), 'false', '46.0', 'a'],
+        [(baseTimestamp + 2_000).toString(), 'true', '41.0', 'b'],
+    ];
+}
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/apis/dashboard-kiosk.service.ts
 
b/ui/projects/streampipes/platform-services/src/lib/apis/dashboard-kiosk.service.ts
index f1f2b3a0ef..a794ad579f 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/apis/dashboard-kiosk.service.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/apis/dashboard-kiosk.service.ts
@@ -36,18 +36,6 @@ export class DashboardKioskRestService {
     private http = inject(HttpClient);
     private platformServicesCommons = inject(PlatformServicesCommons);
 
-    getData(
-        dashboardId: string,
-        widgetId: string,
-        queryParams: DatalakeQueryParameters,
-    ): Observable<SpQueryResult> {
-        const context = new HttpContext().set(NGX_LOADING_BAR_IGNORED, true);
-        const url = 
`${this.dashboardKioskBasePath}/${dashboardId}/${widgetId}/data`;
-        return this.http.post<SpQueryResult>(url, queryParams, {
-            context,
-        });
-    }
-
     performMultiQuery(
         dashboardId: string,
         requests: DashboardKioskDataQuery[],
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/query/data-view-query-generator.service.ts
 
b/ui/projects/streampipes/platform-services/src/lib/query/data-view-query-generator.service.ts
index e68b52f966..86054d815b 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/query/data-view-query-generator.service.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/query/data-view-query-generator.service.ts
@@ -26,7 +26,6 @@ import {
 import { SpQueryResult } from '../model/gen/streampipes-model';
 import { DatalakeQueryParameters } from 
'../model/datalake/DatalakeQueryParameters';
 import { DatalakeQueryParameterBuilder } from 
'./DatalakeQueryParameterBuilder';
-import { DashboardKioskRestService } from '../apis/dashboard-kiosk.service';
 import { DashboardDataRequestCoordinatorService } from 
'./dashboard-data-request-coordinator.service';
 
 @Injectable({
@@ -34,7 +33,6 @@ import { DashboardDataRequestCoordinatorService } from 
'./dashboard-data-request
 })
 export class DataViewQueryGeneratorService {
     protected dataLakeRestService = inject(DatalakeRestService);
-    protected dashboardKioskRestService = inject(DashboardKioskRestService);
     protected dashboardDataRequestCoordinator = inject(
         DashboardDataRequestCoordinatorService,
     );
@@ -62,32 +60,6 @@ export class DataViewQueryGeneratorService {
         });
     }
 
-    generateObservablesForKioskMode(
-        startTime: number,
-        endTime: number,
-        dataConfig: DataExplorerDataConfig,
-        dashboardId: string,
-        widgetId: string,
-        maximumResultingEvents = -1,
-    ): Observable<SpQueryResult>[] {
-        return dataConfig.sourceConfigs.map(sourceConfig => {
-            const dataLakeConfiguration = this.generateQuery(
-                startTime,
-                endTime,
-                sourceConfig,
-                dataConfig.ignoreMissingValues,
-                maximumResultingEvents,
-                true,
-            );
-
-            return this.dashboardKioskRestService.getData(
-                dashboardId,
-                widgetId,
-                dataLakeConfiguration,
-            );
-        });
-    }
-
     generateBatchedObservables(
         startTime: number,
         endTime: number,

Reply via email to