commit 43476dc1bb783d7b20be67c2006ef0d33f1094ce
Author: Marcus Efraimsson <marcus.efraimsson@gmail.com>
Date:   Wed Feb 17 09:51:50 2021 +0100

    Snapshots: Disallow anonymous user to create snapshots (#31263)
    
    (cherry picked from commit 8f20b13f1c8e49b224ad807c78f759a302be20b9)

diff --git a/pkg/middleware/auth.go b/pkg/middleware/auth.go
index d61914a2eb75..c94d7a52ddc7 100644
--- a/pkg/middleware/auth.go
+++ b/pkg/middleware/auth.go
@@ -108,15 +108,17 @@ func AdminOrFeatureEnabled(enabled bool) macaron.Handler {
 	}
 }
 
+// SnapshotPublicModeOrSignedIn creates a middleware that allows access
+// if snapshot public mode is enabled or if user is signed in.
 func SnapshotPublicModeOrSignedIn() macaron.Handler {
 	return func(c *models.ReqContext) {
 		if setting.SnapshotPublicMode {
 			return
 		}
 
-		_, err := c.Invoke(ReqSignedIn)
-		if err != nil {
-			c.JsonApiErr(500, "Failed to invoke required signed in middleware", err)
+		if !c.IsSignedIn {
+			notAuthorized(c)
+			return
 		}
 	}
 }
diff --git a/pkg/middleware/auth_test.go b/pkg/middleware/auth_test.go
index 0688b458deda..5fb9450c8684 100644
--- a/pkg/middleware/auth_test.go
+++ b/pkg/middleware/auth_test.go
@@ -35,11 +35,22 @@ func TestMiddlewareAuth(t *testing.T) {
 
 		Convey("snapshot public mode or signed in", func() {
 			middlewareScenario(t, "Snapshot public mode disabled and unauthenticated request should return 401", func(sc *scenarioContext) {
-				sc.m.Get("/api/snapshot", SnapshotPublicModeOrSignedIn(), sc.defaultHandler)
+			sc.m.Get("/api/snapshot", func(c *models.ReqContext) {
+				c.IsSignedIn = false
+			}, SnapshotPublicModeOrSignedIn(sc.cfg), sc.defaultHandler)
 				sc.fakeReq("GET", "/api/snapshot").exec()
 				So(sc.resp.Code, ShouldEqual, 401)
 			})
 
+			middlewareScenario(t, "Snapshot public mode disabled and authenticated request should return 200", func(
+				t *testing.T, sc *scenarioContext) {
+				sc.m.Get("/api/snapshot", func(c *models.ReqContext) {
+					c.IsSignedIn = true
+				}, SnapshotPublicModeOrSignedIn(sc.cfg), sc.defaultHandler)
+				sc.fakeReq("GET", "/api/snapshot").exec()
+				assert.Equal(t, 200, sc.resp.Code)
+			})
+
 			middlewareScenario(t, "Snapshot public mode enabled and unauthenticated request should return 200", func(sc *scenarioContext) {
 				setting.SnapshotPublicMode = true
 				sc.m.Get("/api/snapshot", SnapshotPublicModeOrSignedIn(), sc.defaultHandler)
diff --git a/public/app/features/dashboard/components/ShareModal/ShareModal.tsx b/public/app/features/dashboard/components/ShareModal/ShareModal.tsx
index efe68781a3ff..d6687a93b40f 100644
--- a/public/app/features/dashboard/components/ShareModal/ShareModal.tsx
+++ b/public/app/features/dashboard/components/ShareModal/ShareModal.tsx
@@ -6,21 +6,7 @@ import { ShareSnapshot } from './ShareSnapshot';
 import { ShareExport } from './ShareExport';
 import { ShareEmbed } from './ShareEmbed';
 import { ShareModalTabModel } from './types';
-
-const shareCommonTabs: ShareModalTabModel[] = [
-  { label: 'Link', value: 'link', component: ShareLink },
-  { label: 'Snapshot', value: 'snapshot', component: ShareSnapshot },
-];
-
-// prettier-ignore
-const shareDashboardTabs: ShareModalTabModel[] = [
-  { label: 'Export', value: 'export', component: ShareExport },
-];
-
-// prettier-ignore
-const sharePanelTabs: ShareModalTabModel[] = [
-  { label: 'Embed', value: 'embed', component: ShareEmbed },
-];
+import { contextSrv } from 'app/core/core';
 
 const customDashboardTabs: ShareModalTabModel[] = [];
 const customPanelTabs: ShareModalTabModel[] = [];
@@ -43,13 +29,18 @@ function getInitialState(props: Props): State {
 
 function getTabs(props: Props) {
   const { panel } = props;
-  const tabs = [...shareCommonTabs];
+
+  const tabs: ShareModalTabModel[] = [{ label: 'Link', value: 'link', component: ShareLink }];
+
+  if (contextSrv.isSignedIn) {
+    tabs.push({ label: 'Snapshot', value: 'snapshot', component: ShareSnapshot });
+  }
 
   if (panel) {
-    tabs.push(...sharePanelTabs);
+    tabs.push({ label: 'Embed', value: 'embed', component: ShareEmbed });
     tabs.push(...customPanelTabs);
   } else {
-    tabs.push(...shareDashboardTabs);
+    tabs.push({ label: 'Export', value: 'export', component: ShareExport });
     tabs.push(...customDashboardTabs);
   }
 
