Compare commits

...

17 Commits

Author SHA1 Message Date
Grot (@grafanabot)
859a2654d3 Release: Bump version to 9.5.6 (#928)
"Release: Updated versions in package to 9.5.6"

Co-authored-by: grafana-delivery-bot[bot] <132647405+grafana-delivery-bot[bot]@users.noreply.github.com>
2023-07-10 15:35:40 -03:00
Vardan Torosyan
b481af936b [v9.5.x] Add and document option for enabling email lookup (#915)
Add and document option for enabling email lookup (#913)

* Docs: Document option for enabling email lookup

* Add the new config in the config files

* Apply suggestions from code review

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>

* Don't capitalize identity providers

* Apply suggestions from code review

Co-authored-by: Jo <joao.guerreiro@grafana.com>

* Apply suggestions from code review

Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>

---------

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
Co-authored-by: Jo <joao.guerreiro@grafana.com>
Co-authored-by: Christopher Moyer <35463610+chri2547@users.noreply.github.com>
(cherry picked from commit 8380bc7d6a79794cc260bf1c427e2b4e849adbf6)
(cherry picked from commit b3418215c93b4d9abbf4d9632bb5b14e72d85cf8)
2023-07-10 15:32:04 +03:00
Grot (@grafanabot)
865c308e11 [v9.5.x] Dashboard: Fix library panels in collapsed rows not getting updated (#68536)
Dashboard: Fix library panels in collapsed rows not getting updated (#66643)

(cherry picked from commit f478504bc9)

Co-authored-by: Victor Colomb <51762123+VictorColomb@users.noreply.github.com>
(cherry picked from commit 5e2559597a)
2023-07-10 15:31:46 +03:00
Grot (@grafanabot)
284c43c23d Release: Bump version to 9.5.5 (#922)
"Release: Updated versions in package to 9.5.5"

Co-authored-by: grafana-delivery-bot[bot] <132647405+grafana-delivery-bot[bot]@users.noreply.github.com>
2023-06-22 10:59:19 +02:00
Dimitris Sotirakis
9225b6a519 [v9.5.x] What's New: Bump whatsnewurl link (#70314)
Bump whatsNewUrl link
2023-06-22 10:50:03 +02:00
Andreas Christou
cfc152a82b [v9.5.x] Azure: Fix Kusto auto-completion for Azure datasources (#69685) (#69694)
Azure: Fix Kusto auto-completion for Azure datasources (#69685)

* Fix Kusto auto-completion not working in HG

* Add update to script paths

* Update CODEOWNERS

* Missed the ts

(cherry picked from commit a6484c6f81)

# Conflicts:
#	yarn.lock
2023-06-22 10:49:31 +02:00
Grot (@grafanabot)
f70714b70b [v9.5.x] Revert: Allow editors to access GET /datasources (#68654)
Revert: Allow editors to access GET /datasources (#68632)

Revert "Allow editors to access GET /datasources"

This reverts commit 5a830c43c0.

(cherry picked from commit 6a2bcba078)

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>
2023-06-22 10:48:15 +02:00
Grot (@grafanabot)
12093e5dd5 [v9.5.x] Settings: Add ability to override skip_org_role_sync with Env variables (#68375)
Settings: Add ability to override `skip_org_role_sync` with Env variables (#68364)

Switch to using the SectionsWithOverride for settings for skip org role sync

(cherry picked from commit 1a79c8a601)

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>
2023-06-22 10:47:27 +02:00
Grot (@grafanabot)
a958c75f1b [v9.5.x] RBAC: Remove legacy AC editor and admin role on new dashboard route (#68776)
RBAC: Remove legacy AC editor and admin role on new dashboard route (#68762)

remove legacy AC editor and admin role on new dashboard route

(cherry picked from commit 94283f5039)

Co-authored-by: Eric Leijonmarck <eric.leijonmarck@gmail.com>
2023-06-22 10:46:34 +02:00
Grot (@grafanabot)
2a57aed24e [v9.5.x] Auth: Show invite button if disable login form is set to false (#70154)
Auth: Show invite button if disable login form is set to false (#69946)

* show invite button if disable login form is set to false

* fix test

* Update public/app/features/users/UsersActionBar.tsx

Co-authored-by: Misi <mgyongyosi@users.noreply.github.com>

---------

Co-authored-by: Misi <mgyongyosi@users.noreply.github.com>
(cherry picked from commit 21f8dd9599)

Co-authored-by: Ieva <ieva.vasiljeva@grafana.com>
2023-06-22 10:45:57 +02:00
Grot (@grafanabot)
e24c6a4a6a [v9.5.x] Auth: Fix visibility of the Invite button on /admin/users page (#69066)
Auth: Fix visibility of the Invite button on /admin/users page (#68991)

* Fix for invite button visibility

* Align test

(cherry picked from commit df4db412cb)

Co-authored-by: Misi <mgyongyosi@users.noreply.github.com>
2023-06-07 16:22:04 +02:00
Grot (@grafanabot)
b9d4a7c50d Release: Bump version to 9.5.4 (#905)
"Release: Updated versions in package to 9.5.4"
2023-06-07 08:55:54 +02:00
Ieva
36567d4fc3 Auth: Remove Email Lookup from oauth integrations 9.5 (#895)
backport https://github.com/grafana/grafana-private-mirror/pull/894 to 9.5.x
2023-06-07 08:52:42 +02:00
Grot (@grafanabot)
916d9793aa Release: Bump version to 9.5.3 (#883)
"Release: Updated versions in package to 9.5.3"
2023-05-22 12:01:35 -05:00
Grot (@grafanabot)
79bb8e554c [v9.5.x] Prevent crash while executing concurrent mixed queries (#877)
Prevent crash while executing concurrent mixed queries (#874)

limit parallel query execution to 1 at a time

(cherry picked from commit 96579a60e19e2a9f2d6bdaeba64e0e702211eb73)

Co-authored-by: Michael Mandrus <41969079+mmandrus@users.noreply.github.com>
2023-05-18 17:16:01 -03:00
George Robinson
4b92020636 [v9.5.x] Require alert.notifications:write permissions to test receivers and templates (#867)
Require alert.notifications:write permissions to test receivers and templates (#865)

(cherry picked from commit 3c21ab70075256d4ba8e4fbfdcb15f5a394161fa)
(cherry picked from commit 2d4eb6622a48cf5ccd34b6a490a8c9fe2d25aedc)
2023-05-18 10:24:31 +02:00
Sofia Papagiannaki
cfcea75916 [v9.5.x] Chore: Upgrade Go to 1.20.4 (#67757)
Chore: Upgrade Go to 1.20.4
2023-05-04 11:56:30 +02:00
36 changed files with 569 additions and 391 deletions

File diff suppressed because it is too large Load Diff

1
.github/CODEOWNERS vendored
View File

@@ -428,6 +428,7 @@ lerna.json @grafana/frontend-ops
/public/gazetteer/ @ryantxu
/public/img/ @grafana/grafana-frontend-platform
/public/lib/ @grafana/grafana-frontend-platform
/public/lib/monaco-languages/kusto.ts @grafana/partner-datasources
/public/maps/ @ryantxu
/public/robots.txt @grafana/frontend-ops
/public/sass/ @grafana/grafana-frontend-platform

View File

@@ -3,7 +3,7 @@
ARG BASE_IMAGE=alpine:3.17
ARG JS_IMAGE=node:18-alpine3.17
ARG JS_PLATFORM=linux/amd64
ARG GO_IMAGE=golang:1.20.3-alpine3.17
ARG GO_IMAGE=golang:1.20.4-alpine3.17
ARG GO_SRC=go-builder
ARG JS_SRC=js-builder

View File

@@ -192,7 +192,7 @@ build-docker-full-ubuntu: ## Build Docker image based on Ubuntu for development.
--build-arg COMMIT_SHA=$$(git rev-parse --short HEAD) \
--build-arg BUILD_BRANCH=$$(git rev-parse --abbrev-ref HEAD) \
--build-arg BASE_IMAGE=ubuntu:20.04 \
--build-arg GO_IMAGE=golang:1.20.3 \
--build-arg GO_IMAGE=golang:1.20.4 \
--tag grafana/grafana$(TAG_SUFFIX):dev-ubuntu \
$(DOCKER_BUILD_ARGS)

View File

@@ -531,6 +531,9 @@ sigv4_verbose_logging = false
# Set to true to enable Azure authentication option for HTTP-based datasources
azure_auth_enabled = false
# Use email lookup in addition to the unique ID provided by the IdP
oauth_allow_insecure_email_lookup = false
#################################### Anonymous Auth ######################
[auth.anonymous]
# enable anonymous access

View File

@@ -520,6 +520,9 @@
# Set to skip the organization role from JWT login and use system's role assignment instead.
; skip_org_role_sync = false
# Use email lookup in addition to the unique ID provided by the IdP
;oauth_allow_insecure_email_lookup = false
#################################### Anonymous Auth ######################
[auth.anonymous]
# enable anonymous access

View File

@@ -76,6 +76,9 @@ token_rotation_interval_minutes = 10
# The maximum lifetime (seconds) an API key can be used. If it is set all the API keys should have limited lifetime that is lower than this value.
api_key_max_seconds_to_live = -1
# Enforce user lookup based on email instead of the unique ID provided by the IdP.
oauth_allow_insecure_email_lookup = false
```
### Anonymous authentication
@@ -118,6 +121,20 @@ Hide the Grafana login form using the below configuration settings.
disable_login_form = true
```
### Enable email lookup
Enable user lookup based on email in addition to using unique ID provided by IdPs.
By default, Grafana relies on the user unique ID provided by the identity provider.
Looking up users by email can be safe for some identity providers (for example, when they are single tenants and unique non-editable, validated emails are provided), as well as in some infrastructures.
We strongly recommend against enabling email lookups, however it is possible to do with the following configuration.
```bash
[auth]
oauth_allow_insecure_email_lookup = true
```
### Automatic OAuth login
Set to true to attempt login with specific OAuth provider automatically, skipping the login screen.

View File

@@ -2,5 +2,5 @@
"npmClient": "yarn",
"useWorkspaces": true,
"packages": ["packages/*"],
"version": "9.5.2"
"version": "9.5.6"
}

View File

@@ -3,7 +3,7 @@
"license": "AGPL-3.0-only",
"private": true,
"name": "grafana",
"version": "9.5.2",
"version": "9.5.6",
"repository": "github:grafana/grafana",
"scripts": {
"build": "yarn i18n:compile && NODE_ENV=production webpack --progress --config scripts/webpack/webpack.prod.js",
@@ -60,7 +60,7 @@
"betterer:issues": "ts-node --transpile-only --project ./scripts/cli/tsconfig.json ./scripts/cli/generateBettererIssues.ts"
},
"grafana": {
"whatsNewUrl": "https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-v9-2/",
"whatsNewUrl": "https://grafana.com/docs/grafana/next/whatsnew/whats-new-in-v9-5/",
"releaseNotesUrl": "https://grafana.com/docs/grafana/next/release-notes/"
},
"lint-staged": {
@@ -269,7 +269,7 @@
"@grafana/scenes": "^0.6.0",
"@grafana/schema": "workspace:*",
"@grafana/ui": "workspace:*",
"@kusto/monaco-kusto": "5.3.6",
"@kusto/monaco-kusto": "^7.4.0",
"@leeoniya/ufuzzy": "1.0.6",
"@lezer/common": "1.0.2",
"@lezer/highlight": "1.1.3",

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/data",
"version": "9.5.2",
"version": "9.5.6",
"description": "Grafana Data Library",
"keywords": [
"typescript"
@@ -36,7 +36,7 @@
},
"dependencies": {
"@braintree/sanitize-url": "6.0.2",
"@grafana/schema": "9.5.2",
"@grafana/schema": "9.5.6",
"@types/d3-interpolate": "^3.0.0",
"d3-interpolate": "3.0.1",
"date-fns": "2.29.3",

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/e2e-selectors",
"version": "9.5.2",
"version": "9.5.6",
"description": "Grafana End-to-End Test Selectors Library",
"keywords": [
"cli",

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/e2e",
"version": "9.5.2",
"version": "9.5.6",
"description": "Grafana End-to-End Test Library",
"keywords": [
"cli",
@@ -63,7 +63,7 @@
"@babel/core": "7.20.5",
"@babel/preset-env": "7.20.2",
"@cypress/webpack-preprocessor": "5.17.0",
"@grafana/e2e-selectors": "9.5.2",
"@grafana/e2e-selectors": "9.5.6",
"@grafana/tsconfig": "^1.2.0-rc1",
"@mochajs/json-file-reporter": "^1.2.0",
"babel-loader": "9.1.2",

View File

@@ -1,7 +1,7 @@
{
"name": "@grafana/eslint-plugin",
"description": "ESLint rules for use within the Grafana repo. Not suitable (or supported) for external use.",
"version": "9.5.2",
"version": "9.5.6",
"main": "./index.cjs",
"author": "Grafana Labs",
"license": "Apache-2.0",

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/runtime",
"version": "9.5.2",
"version": "9.5.6",
"description": "Grafana Runtime Library",
"keywords": [
"grafana",
@@ -37,10 +37,10 @@
"postpack": "mv package.json.bak package.json"
},
"dependencies": {
"@grafana/data": "9.5.2",
"@grafana/e2e-selectors": "9.5.2",
"@grafana/data": "9.5.6",
"@grafana/e2e-selectors": "9.5.6",
"@grafana/faro-web-sdk": "1.0.2",
"@grafana/ui": "9.5.2",
"@grafana/ui": "9.5.6",
"@sentry/browser": "6.19.7",
"history": "4.10.1",
"lodash": "4.17.21",

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/schema",
"version": "9.5.2",
"version": "9.5.6",
"description": "Grafana Schema Library",
"keywords": [
"typescript"

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/toolkit",
"version": "9.5.2",
"version": "9.5.6",
"description": "Grafana Toolkit",
"keywords": [
"grafana",
@@ -51,10 +51,10 @@
"@babel/preset-env": "7.18.9",
"@babel/preset-react": "7.18.6",
"@babel/preset-typescript": "7.18.6",
"@grafana/data": "9.5.2",
"@grafana/data": "9.5.6",
"@grafana/eslint-config": "5.1.0",
"@grafana/tsconfig": "^1.2.0-rc1",
"@grafana/ui": "9.5.2",
"@grafana/ui": "9.5.6",
"@jest/core": "27.5.1",
"@types/command-exists": "^1.2.0",
"@types/eslint": "8.4.1",

View File

@@ -2,7 +2,7 @@
"author": "Grafana Labs",
"license": "Apache-2.0",
"name": "@grafana/ui",
"version": "9.5.2",
"version": "9.5.6",
"description": "Grafana Components Library",
"keywords": [
"grafana",
@@ -49,10 +49,10 @@
"dependencies": {
"@emotion/css": "11.10.6",
"@emotion/react": "11.10.6",
"@grafana/data": "9.5.2",
"@grafana/e2e-selectors": "9.5.2",
"@grafana/data": "9.5.6",
"@grafana/e2e-selectors": "9.5.6",
"@grafana/faro-web-sdk": "1.0.2",
"@grafana/schema": "9.5.2",
"@grafana/schema": "9.5.6",
"@leeoniya/ufuzzy": "1.0.6",
"@monaco-editor/react": "4.4.6",
"@popperjs/core": "2.11.6",

View File

@@ -392,7 +392,7 @@ func (hs *HTTPServer) registerRoutes() {
idScope := datasources.ScopeProvider.GetResourceScope(ac.Parameter(":id"))
uidScope := datasources.ScopeProvider.GetResourceScopeUID(ac.Parameter(":uid"))
nameScope := datasources.ScopeProvider.GetResourceScopeName(ac.Parameter(":name"))
datasourceRoute.Get("/", authorize(reqEditorRole, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(hs.GetDataSources))
datasourceRoute.Get("/", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionRead)), routing.Wrap(hs.GetDataSources))
datasourceRoute.Post("/", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionCreate)), quota(string(datasources.QuotaTargetSrv)), routing.Wrap(hs.AddDataSource))
datasourceRoute.Put("/:id", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, idScope)), routing.Wrap(hs.UpdateDataSourceByID))
datasourceRoute.Put("/uid/:uid", authorize(reqOrgAdmin, ac.EvalPermission(datasources.ActionWrite, uidScope)), routing.Wrap(hs.UpdateDataSourceByUID))

View File

@@ -339,16 +339,17 @@ func (hs *HTTPServer) SyncUser(
connect social.SocialConnector,
) (*user.User, error) {
oauthLogger.Debug("Syncing Grafana user with corresponding OAuth profile")
lookupParams := loginservice.UserLookupParams{}
if hs.Cfg.OAuthAllowInsecureEmailLookup {
lookupParams.Email = &extUser.Email
}
// add/update user in Grafana
cmd := &loginservice.UpsertUserCommand{
ReqContext: ctx,
ExternalUser: extUser,
SignupAllowed: connect.IsSignupAllowed(),
UserLookupParams: loginservice.UserLookupParams{
Email: &extUser.Email,
UserID: nil,
Login: nil,
},
ReqContext: ctx,
ExternalUser: extUser,
SignupAllowed: connect.IsSignupAllowed(),
UserLookupParams: lookupParams,
}
upsertedUser, err := hs.Login.UpsertUser(ctx.Req.Context(), cmd)

View File

@@ -91,7 +91,7 @@ func (hs *HTTPServer) AddOrgInvite(c *contextmodel.ReqContext) response.Response
}
if hs.Cfg.DisableLoginForm {
return response.Error(400, "Cannot invite when login is disabled.", nil)
return response.Error(400, "Cannot invite external user when login is disabled.", nil)
}
cmd := tempuser.CreateTempUserCommand{}

View File

@@ -140,6 +140,11 @@ func (c *OAuth) Authenticate(ctx context.Context, r *authn.Request) (*authn.Iden
return userInfo.Role, userInfo.IsGrafanaAdmin, nil
})
lookupParams := login.UserLookupParams{}
if c.cfg.OAuthAllowInsecureEmailLookup {
lookupParams.Email = &userInfo.Email
}
return &authn.Identity{
Login: userInfo.Login,
Name: userInfo.Name,
@@ -158,7 +163,7 @@ func (c *OAuth) Authenticate(ctx context.Context, r *authn.Request) (*authn.Iden
AllowSignUp: c.connector.IsSignupAllowed(),
// skip org role flag is checked and handled in the connector. For now we can skip the hook if no roles are passed
SyncOrgRoles: len(orgRoles) > 0,
LookUpParams: login.UserLookupParams{Email: &userInfo.Email},
LookUpParams: lookupParams,
},
}, nil
}

View File

@@ -19,9 +19,10 @@ import (
func TestOAuth_Authenticate(t *testing.T) {
type testCase struct {
desc string
req *authn.Request
oauthCfg *social.OAuthInfo
desc string
req *authn.Request
oauthCfg *social.OAuthInfo
allowInsecureTakeover bool
addStateCookie bool
stateCookieValue string
@@ -140,16 +141,42 @@ func TestOAuth_Authenticate(t *testing.T) {
AllowSignUp: true,
FetchSyncedUser: true,
SyncOrgRoles: true,
LookUpParams: login.UserLookupParams{Email: strPtr("some@email.com")},
LookUpParams: login.UserLookupParams{},
},
},
},
{
desc: "should return identity for valid request - and lookup user by email",
req: &authn.Request{HTTPRequest: &http.Request{
Header: map[string][]string{},
URL: mustParseURL("http://grafana.com/?state=some-state"),
},
},
oauthCfg: &social.OAuthInfo{UsePKCE: true},
allowInsecureTakeover: true,
addStateCookie: true,
stateCookieValue: "some-state",
addPKCECookie: true,
pkceCookieValue: "some-pkce-value",
isEmailAllowed: true,
userInfo: &social.BasicUserInfo{
Id: "123",
Name: "name",
Email: "some@email.com",
Role: "Admin",
Groups: []string{"grp1", "grp2"},
},
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
cfg := setting.NewCfg()
if tt.allowInsecureTakeover {
cfg.OAuthAllowInsecureEmailLookup = true
}
if tt.addStateCookie {
v := tt.stateCookieValue
if v != "" {

View File

@@ -170,7 +170,7 @@ func (api *API) authorize(method, path string) web.Handler {
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
case http.MethodPost + "/api/alertmanager/grafana/config/api/v1/receivers/test":
fallback = middleware.ReqEditorRole
eval = ac.EvalPermission(ac.ActionAlertingNotificationsRead)
eval = ac.EvalPermission(ac.ActionAlertingNotificationsWrite)
// External Alertmanager Paths
case http.MethodDelete + "/api/alertmanager/{DatasourceUID}/config/api/v1/alerts":

View File

@@ -101,7 +101,10 @@ func (s *ServiceImpl) QueryData(ctx context.Context, user *user.SignedInUser, sk
// executeConcurrentQueries executes queries to multiple datasources concurrently and returns the aggregate result.
func (s *ServiceImpl) executeConcurrentQueries(ctx context.Context, user *user.SignedInUser, skipCache bool, reqDTO dtos.MetricRequest, queriesbyDs map[string][]parsedQuery) (*backend.QueryDataResponse, error) {
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(8) // arbitrary limit to prevent too many concurrent requests
// TODO: Temporarily limiting concurrency here to 1 to avoid concurrent map writes in the plugin middleware that crash the app
// This is a workaround to mitigate the security issue. We will implement a more thread-safe way of handling concurrent queries as a next step.
g.SetLimit(1)
// g.SetLimit(8) // arbitrary limit to prevent too many concurrent requests
rchan := make(chan backend.Responses, len(queriesbyDs))
// Create panic recovery function for loop below

View File

@@ -291,8 +291,9 @@ type Cfg struct {
AuthProxySyncTTL int
// OAuth
OAuthAutoLogin bool
OAuthCookieMaxAge int
OAuthAutoLogin bool
OAuthCookieMaxAge int
OAuthAllowInsecureEmailLookup bool
// JWT Auth
JWTAuthEnabled bool
@@ -1390,44 +1391,44 @@ func readSecuritySettings(iniFile *ini.File, cfg *Cfg) error {
return nil
}
func readAuthAzureADSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.azuread")
func readAuthAzureADSettings(cfg *Cfg) {
sec := cfg.SectionWithEnvOverrides("auth.azuread")
cfg.AzureADEnabled = sec.Key("enabled").MustBool(false)
cfg.AzureADSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readAuthGrafanaComSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.grafana_com")
func readAuthGrafanaComSettings(cfg *Cfg) {
sec := cfg.SectionWithEnvOverrides("auth.grafana_com")
cfg.GrafanaComAuthEnabled = sec.Key("enabled").MustBool(false)
cfg.GrafanaComSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readAuthGithubSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.github")
func readAuthGithubSettings(cfg *Cfg) {
sec := cfg.SectionWithEnvOverrides("auth.github")
cfg.GitHubAuthEnabled = sec.Key("enabled").MustBool(false)
cfg.GitHubSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readAuthGoogleSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.google")
func readAuthGoogleSettings(cfg *Cfg) {
sec := cfg.SectionWithEnvOverrides("auth.google")
cfg.GoogleAuthEnabled = sec.Key("enabled").MustBool(false)
cfg.GoogleSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readAuthGitlabSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.gitlab")
func readAuthGitlabSettings(cfg *Cfg) {
sec := cfg.SectionWithEnvOverrides("auth.gitlab")
cfg.GitLabAuthEnabled = sec.Key("enabled").MustBool(false)
cfg.GitLabSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readGenericOAuthSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.generic_oauth")
func readGenericOAuthSettings(cfg *Cfg) {
sec := cfg.SectionWithEnvOverrides("auth.generic_oauth")
cfg.GenericOAuthAuthEnabled = sec.Key("enabled").MustBool(false)
cfg.GenericOAuthSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
func readAuthOktaSettings(iniFile *ini.File, cfg *Cfg) {
sec := iniFile.Section("auth.okta")
func readAuthOktaSettings(cfg *Cfg) {
sec := cfg.SectionWithEnvOverrides("auth.okta")
cfg.OktaAuthEnabled = sec.Key("enabled").MustBool(false)
cfg.OktaSkipOrgRoleSync = sec.Key("skip_org_role_sync").MustBool(false)
}
@@ -1444,6 +1445,8 @@ func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) {
return err
}
cfg.OAuthAllowInsecureEmailLookup = auth.Key("oauth_allow_insecure_email_lookup").MustBool(false)
const defaultMaxLifetime = "30d"
maxLifetimeDurationVal := valueAsString(auth, "login_maximum_lifetime_duration", defaultMaxLifetime)
cfg.LoginMaxLifetime, err = gtime.ParseDuration(maxLifetimeDurationVal)
@@ -1488,19 +1491,25 @@ func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) {
// Azure Auth
AzureAuthEnabled = auth.Key("azure_auth_enabled").MustBool(false)
cfg.AzureAuthEnabled = AzureAuthEnabled
readAuthAzureADSettings(iniFile, cfg)
readAuthAzureADSettings(cfg)
// Google Auth
readAuthGoogleSettings(iniFile, cfg)
readAuthGoogleSettings(cfg)
// GitLab Auth
readAuthGitlabSettings(iniFile, cfg)
readAuthGitlabSettings(cfg)
// Generic OAuth
readGenericOAuthSettings(iniFile, cfg)
readGenericOAuthSettings(cfg)
// Okta Auth
readAuthOktaSettings(iniFile, cfg)
readAuthOktaSettings(cfg)
// GrafanaCom
readAuthGrafanaComSettings(cfg)
// Github
readAuthGithubSettings(cfg)
// anonymous access
cfg.AnonymousEnabled = iniFile.Section("auth.anonymous").Key("enabled").MustBool(false)
@@ -1554,11 +1563,6 @@ func readAuthSettings(iniFile *ini.File, cfg *Cfg) (err error) {
cfg.AuthProxyHeadersEncoded = authProxy.Key("headers_encoded").MustBool(false)
// GrafanaCom
readAuthGrafanaComSettings(iniFile, cfg)
// Github
readAuthGithubSettings(iniFile, cfg)
return nil
}

View File

@@ -1,6 +1,6 @@
{
"name": "@grafana-plugins/input-datasource",
"version": "9.5.2",
"version": "9.5.6",
"description": "Input Datasource",
"private": true,
"repository": {
@@ -15,15 +15,15 @@
},
"author": "Grafana Labs",
"devDependencies": {
"@grafana/toolkit": "9.5.2",
"@grafana/toolkit": "9.5.6",
"@types/jest": "26.0.15",
"@types/lodash": "4.14.149",
"@types/react": "17.0.30",
"lodash": "4.17.21"
},
"dependencies": {
"@grafana/data": "9.5.2",
"@grafana/ui": "9.5.2",
"@grafana/data": "9.5.6",
"@grafana/ui": "9.5.6",
"jquery": "3.5.1",
"react": "17.0.1",
"react-dom": "17.0.1",

View File

@@ -195,6 +195,27 @@ describe('PanelModel', () => {
expect(saveModel.events).toBe(undefined);
});
it('getSaveModel should clean libraryPanels from a collapsed row', () => {
const newmodelJson = {
type: 'row',
panels: [
{
...modelJson,
libraryPanel: {
uid: 'BVIBScisnl',
model: modelJson,
name: 'Library panel title',
},
},
modelJson,
],
};
const newmodel = new PanelModel(newmodelJson);
const saveModel = newmodel.getSaveModel();
expect(saveModel.panels[0].tagrets).toBe(undefined);
expect(saveModel.panels[1].targets).toBeTruthy();
});
describe('variables interpolation', () => {
beforeEach(() => {
model.scopedVars = {

View File

@@ -310,6 +310,26 @@ export class PanelModel implements DataConfigSource, IPanelModel {
model[property] = cloneDeep(this[property]);
}
// clean libraryPanel from collapsed rows
if (this.type === 'row' && this.panels && this.panels.length > 0) {
model.panels = this.panels.map((panel) => {
if (panel.libraryPanel) {
const { id, title, libraryPanel, gridPos } = panel;
return {
id,
title,
gridPos,
libraryPanel: {
uid: libraryPanel.uid,
name: libraryPanel.name,
},
};
}
return panel;
});
}
return model;
}

View File

@@ -65,8 +65,9 @@ describe('Render', () => {
expect(screen.getByRole('link', { name: 'someUrl' })).toHaveAttribute('href', 'some/url');
});
it('should not show invite button when disableLoginForm is set', () => {
const originalDisableLoginForm = config.disableLoginForm;
it('should not show invite button when externalUserMngInfo is set and disableLoginForm is true', () => {
const originalExternalUserMngInfo = config.externalUserMngInfo;
config.externalUserMngInfo = 'truthy';
config.disableLoginForm = true;
setup({
@@ -75,6 +76,32 @@ describe('Render', () => {
expect(screen.queryByRole('link', { name: 'Invite' })).not.toBeInTheDocument();
// Reset the disableLoginForm mock to its original value
config.disableLoginForm = originalDisableLoginForm;
config.externalUserMngInfo = originalExternalUserMngInfo;
});
it('should show invite button when externalUserMngInfo is not set and disableLoginForm is true', () => {
config.externalUserMngInfo = '';
config.disableLoginForm = true;
setup({
canInvite: true,
});
expect(screen.getByRole('link', { name: 'Invite' })).toHaveAttribute('href', 'org/users/invite');
// Reset the disableLoginForm mock to its original value
config.disableLoginForm = false;
});
it('should show invite button when externalUserMngInfo is set and disableLoginForm is false', () => {
const originalExternalUserMngInfo = config.externalUserMngInfo;
config.externalUserMngInfo = 'truthy';
setup({
canInvite: true,
});
expect(screen.getByRole('link', { name: 'Invite' })).toHaveAttribute('href', 'org/users/invite');
// Reset the disableLoginForm mock to its original value
config.externalUserMngInfo = originalExternalUserMngInfo;
});
});

View File

@@ -49,8 +49,10 @@ export const UsersActionBarUnconnected = ({
{ label: `Pending Invites (${pendingInvitesCount})`, value: 'invites' },
];
const canAddToOrg: boolean = contextSrv.hasAccess(AccessControlAction.OrgUsersAdd, canInvite);
// backend rejects invitations if the login form is disabled
const showInviteButton: boolean = canAddToOrg && !config.disableLoginForm;
// Show invite button in the following cases:
// 1) the instance is not a hosted Grafana instance (!config.externalUserMngInfo)
// 2) new basic auth users can be created for this instance (!config.disableLoginForm).
const showInviteButton: boolean = canAddToOrg && !(config.disableLoginForm && config.externalUserMngInfo);
return (
<div className="page-action-bar" data-testid="users-action-bar">

View File

@@ -74,7 +74,7 @@ export function getAppRoutes(): RouteDescriptor[] {
},
{
path: '/dashboard/new',
roles: () => contextSrv.evaluatePermission(() => ['Editor', 'Admin'], [AccessControlAction.DashboardsCreate]),
roles: () => contextSrv.evaluatePermission(() => [], [AccessControlAction.DashboardsCreate]),
pageClass: 'page-dashboard',
routeName: DashboardRoutes.New,
component: SafeDynamicImport(

View File

@@ -5,17 +5,6 @@ declare global {
}
}
const monacoPath = (window.__grafana_public_path__ ?? 'public/') + 'lib/monaco/min/vs';
const scripts = [
[`${monacoPath}/language/kusto/bridge.min.js`],
[
`${monacoPath}/language/kusto/kusto.javascript.client.min.js`,
`${monacoPath}/language/kusto/newtonsoft.json.min.js`,
`${monacoPath}/language/kusto/Kusto.Language.Bridge.min.js`,
],
];
function loadScript(script: HTMLScriptElement | string): Promise<void> {
return new Promise((resolve, reject) => {
let scriptEl: HTMLScriptElement;
@@ -47,6 +36,16 @@ const loadMonacoKusto = () => {
};
export default async function loadKusto() {
const monacoPath = (window.__grafana_public_path__ ?? 'public/') + 'lib/monaco/min/vs';
const scripts = [
[`${monacoPath}/language/kusto/bridge.min.js`],
[
`${monacoPath}/language/kusto/kusto.javascript.client.min.js`,
`${monacoPath}/language/kusto/newtonsoft.json.min.js`,
`${monacoPath}/language/kusto/Kusto.Language.Bridge.min.js`,
],
];
let promise = Promise.resolve();
for (const parallelScripts of scripts) {

View File

@@ -108,7 +108,7 @@ RUN rm dockerize-linux-amd64-v${DOCKERIZE_VERSION}.tar.gz
# Use old Debian (LTS into 2024) in order to ensure binary compatibility with older glibc's.
FROM debian:buster-20220822
ENV GOVERSION=1.20.3 \
ENV GOVERSION=1.20.4 \
PATH=/usr/local/go/bin:$PATH \
GOPATH=/go \
NODEVERSION=18.12.0-1nodesource1 \

View File

@@ -9,14 +9,14 @@ load(
)
grabpl_version = "v3.0.30"
build_image = "grafana/build-container:1.7.3"
build_image = "grafana/build-container:1.7.4"
publish_image = "grafana/grafana-ci-deploy:1.3.3"
deploy_docker_image = "us.gcr.io/kubernetes-dev/drone/plugins/deploy-image"
alpine_image = "alpine:3.17.1"
curl_image = "byrnedo/alpine-curl:0.1.8"
windows_image = "mcr.microsoft.com/windows:1809"
wix_image = "grafana/ci-wix:0.1.1"
go_image = "golang:1.20.3"
go_image = "golang:1.20.4"
trigger_oss = {
"repo": [

View File

@@ -57,7 +57,7 @@ module.exports = {
},
},
{
context: path.join(require.resolve('@kusto/monaco-kusto'), '../'),
context: path.join(require.resolve('@kusto/monaco-kusto/package.json'), '../release/min'),
from: '**/*',
to: '../lib/monaco/min/vs/language/kusto/',
},

113
yarn.lock
View File

@@ -1814,6 +1814,16 @@ __metadata:
languageName: node
linkType: hard
"@babel/runtime-corejs3@npm:^7.16.5":
version: 7.22.3
resolution: "@babel/runtime-corejs3@npm:7.22.3"
dependencies:
core-js-pure: ^3.30.2
regenerator-runtime: ^0.13.11
checksum: ec92a0b874669bb5eff9e7f20d4e0dbfb0bb5d433bd9e2d6f892c38884079d657240165306a402bb4747942765bdd37b7b5857c573505d2179c1fa4162bf966b
languageName: node
linkType: hard
"@babel/runtime@npm:7.20.1":
version: 7.20.1
resolution: "@babel/runtime@npm:7.20.1"
@@ -2988,9 +2998,9 @@ __metadata:
version: 0.0.0-use.local
resolution: "@grafana-plugins/input-datasource@workspace:plugins-bundled/internal/input-datasource"
dependencies:
"@grafana/data": 9.5.2
"@grafana/toolkit": 9.5.2
"@grafana/ui": 9.5.2
"@grafana/data": 9.5.6
"@grafana/toolkit": 9.5.6
"@grafana/ui": 9.5.6
"@types/jest": 26.0.15
"@types/lodash": 4.14.149
"@types/react": 17.0.30
@@ -3023,12 +3033,12 @@ __metadata:
languageName: node
linkType: hard
"@grafana/data@9.5.2, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data":
"@grafana/data@9.5.6, @grafana/data@workspace:*, @grafana/data@workspace:packages/grafana-data":
version: 0.0.0-use.local
resolution: "@grafana/data@workspace:packages/grafana-data"
dependencies:
"@braintree/sanitize-url": 6.0.2
"@grafana/schema": 9.5.2
"@grafana/schema": 9.5.6
"@grafana/tsconfig": ^1.2.0-rc1
"@rollup/plugin-commonjs": 23.0.2
"@rollup/plugin-json": 5.0.1
@@ -3088,7 +3098,7 @@ __metadata:
languageName: unknown
linkType: soft
"@grafana/e2e-selectors@9.5.2, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors":
"@grafana/e2e-selectors@9.5.6, @grafana/e2e-selectors@workspace:*, @grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors":
version: 0.0.0-use.local
resolution: "@grafana/e2e-selectors@workspace:packages/grafana-e2e-selectors"
dependencies:
@@ -3125,7 +3135,7 @@ __metadata:
"@babel/core": 7.20.5
"@babel/preset-env": 7.20.2
"@cypress/webpack-preprocessor": 5.17.0
"@grafana/e2e-selectors": 9.5.2
"@grafana/e2e-selectors": 9.5.6
"@grafana/tsconfig": ^1.2.0-rc1
"@mochajs/json-file-reporter": ^1.2.0
"@rollup/plugin-node-resolve": 15.0.1
@@ -3285,11 +3295,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "@grafana/runtime@workspace:packages/grafana-runtime"
dependencies:
"@grafana/data": 9.5.2
"@grafana/e2e-selectors": 9.5.2
"@grafana/data": 9.5.6
"@grafana/e2e-selectors": 9.5.6
"@grafana/faro-web-sdk": 1.0.2
"@grafana/tsconfig": ^1.2.0-rc1
"@grafana/ui": 9.5.2
"@grafana/ui": 9.5.6
"@rollup/plugin-commonjs": 23.0.2
"@rollup/plugin-node-resolve": 15.0.1
"@sentry/browser": 6.19.7
@@ -3340,7 +3350,7 @@ __metadata:
languageName: node
linkType: hard
"@grafana/schema@9.5.2, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema":
"@grafana/schema@9.5.6, @grafana/schema@workspace:*, @grafana/schema@workspace:packages/grafana-schema":
version: 0.0.0-use.local
resolution: "@grafana/schema@workspace:packages/grafana-schema"
dependencies:
@@ -3359,7 +3369,7 @@ __metadata:
languageName: unknown
linkType: soft
"@grafana/toolkit@9.5.2, @grafana/toolkit@workspace:*, @grafana/toolkit@workspace:packages/grafana-toolkit":
"@grafana/toolkit@9.5.6, @grafana/toolkit@workspace:*, @grafana/toolkit@workspace:packages/grafana-toolkit":
version: 0.0.0-use.local
resolution: "@grafana/toolkit@workspace:packages/grafana-toolkit"
dependencies:
@@ -3375,10 +3385,10 @@ __metadata:
"@babel/preset-env": 7.18.9
"@babel/preset-react": 7.18.6
"@babel/preset-typescript": 7.18.6
"@grafana/data": 9.5.2
"@grafana/data": 9.5.6
"@grafana/eslint-config": 5.1.0
"@grafana/tsconfig": ^1.2.0-rc1
"@grafana/ui": 9.5.2
"@grafana/ui": 9.5.6
"@jest/core": 27.5.1
"@types/command-exists": ^1.2.0
"@types/eslint": 8.4.1
@@ -3459,17 +3469,17 @@ __metadata:
languageName: node
linkType: hard
"@grafana/ui@9.5.2, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui":
"@grafana/ui@9.5.6, @grafana/ui@workspace:*, @grafana/ui@workspace:packages/grafana-ui":
version: 0.0.0-use.local
resolution: "@grafana/ui@workspace:packages/grafana-ui"
dependencies:
"@babel/core": 7.20.5
"@emotion/css": 11.10.6
"@emotion/react": 11.10.6
"@grafana/data": 9.5.2
"@grafana/e2e-selectors": 9.5.2
"@grafana/data": 9.5.6
"@grafana/e2e-selectors": 9.5.6
"@grafana/faro-web-sdk": 1.0.2
"@grafana/schema": 9.5.2
"@grafana/schema": 9.5.6
"@grafana/tsconfig": ^1.2.0-rc1
"@leeoniya/ufuzzy": 1.0.6
"@mdx-js/react": 1.6.22
@@ -4418,29 +4428,34 @@ __metadata:
languageName: node
linkType: hard
"@kusto/language-service-next@npm:0.0.59":
version: 0.0.59
resolution: "@kusto/language-service-next@npm:0.0.59"
checksum: 90f377a4c59e632a2fd904c202be3c823f41359b62b05a7bc66fd4a9e86d7bed34970822b720232dacd45f6ce3373abff53fb843b5228878c5f84f5b5ba68fba
"@kusto/language-service-next@npm:0.0.66":
version: 0.0.66
resolution: "@kusto/language-service-next@npm:0.0.66"
checksum: d85dda481fc72b81097481ed6a8f51fe342cfbe17e8436c9a69ad22904e3c1695b4fbf26d63aef891e8d6f262d618e939e5ad5bdbd531c7cd4cd16ad91095865
languageName: node
linkType: hard
"@kusto/language-service@npm:0.0.38":
version: 0.0.38
resolution: "@kusto/language-service@npm:0.0.38"
checksum: 9ad45b144409162298f1e61b87209e40315f3fe30b5766175b831ce9ab6b5cd4f046323956fa35ce971993aa67f84b175c5af1de9614dd57a12f4fd61bfa401c
"@kusto/language-service@npm:0.0.43":
version: 0.0.43
resolution: "@kusto/language-service@npm:0.0.43"
checksum: cae1ddf61424ff34e631e2defe54fc6344877079101b164d611606885207fef9128cfcf079f51b7dd8856132cf458e208396f418f7eb63c6342986c167a3be23
languageName: node
linkType: hard
"@kusto/monaco-kusto@npm:5.3.6":
version: 5.3.6
resolution: "@kusto/monaco-kusto@npm:5.3.6"
"@kusto/monaco-kusto@npm:^7.4.0":
version: 7.4.0
resolution: "@kusto/monaco-kusto@npm:7.4.0"
dependencies:
"@kusto/language-service": 0.0.38
"@kusto/language-service-next": 0.0.59
"@kusto/language-service": 0.0.43
"@kusto/language-service-next": 0.0.66
lodash-es: ^4.17.21
vscode-languageserver-types: 3.16.0
xregexp: ^5.1.1
peerDependencies:
monaco-editor: 0.34.1
checksum: 55cef304cca6383ed4bccd60639d7429e2bee224e719eb33b294067ba47086df51752d5a51d9bb8cd73b7fe5a2fa3d6e5f625d392d013e281c451d967a529672
monaco-editor: ~0.38.0
bin:
copyMonacoFilesAMD: copyMonacoFilesAMD.js
checksum: d3905b049729f1b58286e868c000f934f237db07745f5498121c839bdf65e41c2564dca5a0ee0e53c9e4c413e2843e92cfbb2e5910bee620746625da02d4bf8d
languageName: node
linkType: hard
@@ -14803,6 +14818,13 @@ __metadata:
languageName: node
linkType: hard
"core-js-pure@npm:^3.30.2":
version: 3.30.2
resolution: "core-js-pure@npm:3.30.2"
checksum: e0e012fe94e38663d837410baac62efe05d0c7431e3fbaa70c65f51eb980da9c3add225eca04208d576bc0d92cefeca9a4f7671a65fd84fd7dfc92d8618dddfd
languageName: node
linkType: hard
"core-js@npm:3.28.0":
version: 3.28.0
resolution: "core-js@npm:3.28.0"
@@ -20115,7 +20137,7 @@ __metadata:
"@grafana/toolkit": "workspace:*"
"@grafana/tsconfig": ^1.2.0-rc1
"@grafana/ui": "workspace:*"
"@kusto/monaco-kusto": 5.3.6
"@kusto/monaco-kusto": ^7.4.0
"@leeoniya/ufuzzy": 1.0.6
"@lezer/common": 1.0.2
"@lezer/highlight": 1.1.3
@@ -24909,6 +24931,13 @@ __metadata:
languageName: node
linkType: hard
"lodash-es@npm:^4.17.21":
version: 4.17.21
resolution: "lodash-es@npm:4.17.21"
checksum: 05cbffad6e2adbb331a4e16fbd826e7faee403a1a04873b82b42c0f22090f280839f85b95393f487c1303c8a3d2a010048bf06151a6cbe03eee4d388fb0a12d2
languageName: node
linkType: hard
"lodash.debounce@npm:^4.0.8":
version: 4.0.8
resolution: "lodash.debounce@npm:4.0.8"
@@ -36831,6 +36860,13 @@ __metadata:
languageName: node
linkType: hard
"vscode-languageserver-types@npm:3.16.0":
version: 3.16.0
resolution: "vscode-languageserver-types@npm:3.16.0"
checksum: 7a44fb10b9fbeb9529f832337b7f0430fc6275d62945b86851d425a950e22da3917ef5f6c552688191769dd1eae047c6ee9ec3d9f2280498353007c2dfe0725c
languageName: node
linkType: hard
"vue-template-compiler@npm:^2.6.11":
version: 2.7.10
resolution: "vue-template-compiler@npm:2.7.10"
@@ -37783,6 +37819,15 @@ __metadata:
languageName: node
linkType: hard
"xregexp@npm:^5.1.1":
version: 5.1.1
resolution: "xregexp@npm:5.1.1"
dependencies:
"@babel/runtime-corejs3": ^7.16.5
checksum: b7fee45db0daacc68d8f747c9d3865af6b1135866c6dbd72980fc7d61138310018c397effdc0ec1f50ced71b9437ccb70c27818f4470e28e48dc59ea6e3900a0
languageName: node
linkType: hard
"xss@npm:^1.0.14":
version: 1.0.14
resolution: "xss@npm:1.0.14"