From 6adc45bf30ba6ef3aa2835ad45baf0abc11df514 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Mon, 5 Jan 2026 15:27:49 +0000 Subject: [PATCH] FS: Allow anonymous access to snapshot route (#115829) allow anonymous access to snapshot route --- public/app/core/navigation/GrafanaRoute.tsx | 8 ++++++-- public/app/core/navigation/types.ts | 3 ++- public/app/routes/routes.tsx | 8 +++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/public/app/core/navigation/GrafanaRoute.tsx b/public/app/core/navigation/GrafanaRoute.tsx index e17a3bf6a4a..3820f0a7d9b 100644 --- a/public/app/core/navigation/GrafanaRoute.tsx +++ b/public/app/core/navigation/GrafanaRoute.tsx @@ -1,5 +1,5 @@ import { Suspense, useEffect, useLayoutEffect } from 'react'; -import { Navigate, useLocation } from 'react-router-dom-v5-compat'; +import { Navigate, useLocation, useParams } from 'react-router-dom-v5-compat'; import { config, locationSearchToObject, navigationLogger, reportPageview } from '@grafana/runtime'; import { ErrorBoundary } from '@grafana/ui'; @@ -63,10 +63,14 @@ export function GrafanaRoute(props: Props) { export function GrafanaRouteWrapper({ route }: Pick) { const location = useLocation(); + const params = useParams(); + + const allowAnonymous = + typeof route.allowAnonymous === 'function' ? route.allowAnonymous(params) : route.allowAnonymous; // Perform login check in the frontend now if (isFrontendService()) { - const routeRequiresSignin = !route.allowAnonymous && !config.anonymousEnabled; + const routeRequiresSignin = !allowAnonymous && !config.anonymousEnabled; if (routeRequiresSignin && !contextSrv.isSignedIn) { contextSrv.setRedirectToUrl(); diff --git a/public/app/core/navigation/types.ts b/public/app/core/navigation/types.ts index 757eeefb725..2188cf3935b 100644 --- a/public/app/core/navigation/types.ts +++ b/public/app/core/navigation/types.ts @@ -1,5 +1,6 @@ import { Location } from 'history'; import { ComponentType } from 'react'; +import { Params } from 'react-router-dom-v5-compat'; import { UrlQueryMap } from '@grafana/data'; @@ -25,5 +26,5 @@ export interface RouteDescriptor { * Allow the route to be access by anonymous users. * Currently only used when using the frontend-service. */ - allowAnonymous?: boolean; + allowAnonymous?: boolean | ((params: Readonly>) => boolean); } diff --git a/public/app/routes/routes.tsx b/public/app/routes/routes.tsx index 78cf632a1b1..8b8b3213004 100644 --- a/public/app/routes/routes.tsx +++ b/public/app/routes/routes.tsx @@ -30,7 +30,7 @@ const isDevEnv = config.buildInfo.env === 'development'; export const extraRoutes: RouteDescriptor[] = []; export function getAppRoutes(): RouteDescriptor[] { - return [ + const routes: Array = [ // Based on the Grafana configuration standalone plugin pages can even override and extend existing core pages, or they can register new routes under existing ones. // In order to make it possible we need to register them first due to how `` is evaluating routes. (This will be unnecessary once/when we upgrade to React Router v6 and start using `` instead.) ...getAppPluginRoutes(), @@ -77,6 +77,7 @@ export function getAppRoutes(): RouteDescriptor[] { }, { path: '/dashboard/:type/:slug', + allowAnonymous: (params) => params.type === 'snapshot', pageClass: 'page-dashboard', routeName: DashboardRoutes.Normal, component: SafeDynamicImport( @@ -223,7 +224,6 @@ export function getAppRoutes(): RouteDescriptor[] { }, { path: '/admin/extensions', - navId: 'extensions', roles: () => contextSrv.evaluatePermission([AccessControlAction.PluginsInstall, AccessControlAction.PluginsWrite]), component: @@ -560,7 +560,9 @@ export function getAppRoutes(): RouteDescriptor[] { path: '/*', component: PageNotFound, }, - ].filter(isTruthy); + ]; + + return routes.filter(isTruthy); } export function getSupportBundleRoutes(cfg = config): RouteDescriptor[] {