Dashboard: Support configuring default timezone via config file (#27404)

Add a default timezone that the administrator can set in the settings. 
This setting is be used as default for the users timezone preference.
Can be used when creating Grafana instances without administrator 
intervention, in order to give user the correct default timezone.

Fixes #25654
This commit is contained in:
Wouter Smeenk
2020-09-15 15:20:53 +02:00
committed by GitHub
parent 53153c82fc
commit 39eba5065b
9 changed files with 94 additions and 16 deletions
+4 -4
View File
@@ -10,13 +10,13 @@ import (
"github.com/grafana/grafana/pkg/setting"
)
func init() {
func (ss *SqlStore) addPreferencesQueryAndCommandHandlers() {
bus.AddHandler("sql", GetPreferences)
bus.AddHandler("sql", GetPreferencesWithDefaults)
bus.AddHandler("sql", ss.GetPreferencesWithDefaults)
bus.AddHandler("sql", SavePreferences)
}
func GetPreferencesWithDefaults(query *models.GetPreferencesWithDefaultsQuery) error {
func (ss *SqlStore) GetPreferencesWithDefaults(query *models.GetPreferencesWithDefaultsQuery) error {
params := make([]interface{}, 0)
filter := ""
@@ -43,7 +43,7 @@ func GetPreferencesWithDefaults(query *models.GetPreferencesWithDefaultsQuery) e
res := &models.Preferences{
Theme: setting.DefaultTheme,
Timezone: "browser",
Timezone: ss.Cfg.DateFormats.DefaultTimezone,
HomeDashboardId: 0,
}
+13 -10
View File
@@ -11,14 +11,17 @@ import (
func TestPreferencesDataAccess(t *testing.T) {
Convey("Testing preferences data access", t, func() {
InitTestDB(t)
ss := InitTestDB(t)
Convey("GetPreferencesWithDefaults with no saved preferences should return defaults", func() {
setting.DefaultTheme = "light"
ss.Cfg.DateFormats.DefaultTimezone = "UTC"
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{}}
err := GetPreferencesWithDefaults(query)
err := ss.GetPreferencesWithDefaults(query)
So(err, ShouldBeNil)
So(query.Result.Theme, ShouldEqual, setting.DefaultTheme)
So(query.Result.Timezone, ShouldEqual, "browser")
So(query.Result.Theme, ShouldEqual, "light")
So(query.Result.Timezone, ShouldEqual, "UTC")
So(query.Result.HomeDashboardId, ShouldEqual, 0)
})
@@ -29,7 +32,7 @@ func TestPreferencesDataAccess(t *testing.T) {
So(err, ShouldBeNil)
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{OrgId: 1, UserId: 1}}
err = GetPreferencesWithDefaults(query)
err = ss.GetPreferencesWithDefaults(query)
So(err, ShouldBeNil)
So(query.Result.HomeDashboardId, ShouldEqual, 4)
})
@@ -41,7 +44,7 @@ func TestPreferencesDataAccess(t *testing.T) {
So(err, ShouldBeNil)
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{OrgId: 1, UserId: 2}}
err = GetPreferencesWithDefaults(query)
err = ss.GetPreferencesWithDefaults(query)
So(err, ShouldBeNil)
So(query.Result.HomeDashboardId, ShouldEqual, 1)
})
@@ -57,7 +60,7 @@ func TestPreferencesDataAccess(t *testing.T) {
query := &models.GetPreferencesWithDefaultsQuery{
User: &models.SignedInUser{OrgId: 1, Teams: []int64{2, 3}},
}
err = GetPreferencesWithDefaults(query)
err = ss.GetPreferencesWithDefaults(query)
So(err, ShouldBeNil)
So(query.Result.HomeDashboardId, ShouldEqual, 3)
})
@@ -71,7 +74,7 @@ func TestPreferencesDataAccess(t *testing.T) {
So(err, ShouldBeNil)
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{OrgId: 1}}
err = GetPreferencesWithDefaults(query)
err = ss.GetPreferencesWithDefaults(query)
So(err, ShouldBeNil)
So(query.Result.HomeDashboardId, ShouldEqual, 1)
})
@@ -89,7 +92,7 @@ func TestPreferencesDataAccess(t *testing.T) {
query := &models.GetPreferencesWithDefaultsQuery{
User: &models.SignedInUser{OrgId: 1, UserId: 1, Teams: []int64{2, 3}},
}
err = GetPreferencesWithDefaults(query)
err = ss.GetPreferencesWithDefaults(query)
So(err, ShouldBeNil)
So(query.Result.HomeDashboardId, ShouldEqual, 4)
})
@@ -107,7 +110,7 @@ func TestPreferencesDataAccess(t *testing.T) {
query := &models.GetPreferencesWithDefaultsQuery{
User: &models.SignedInUser{OrgId: 1, UserId: 2},
}
err = GetPreferencesWithDefaults(query)
err = ss.GetPreferencesWithDefaults(query)
So(err, ShouldBeNil)
So(query.Result.HomeDashboardId, ShouldEqual, 1)
})
+1
View File
@@ -102,6 +102,7 @@ func (ss *SqlStore) Init() error {
// Register handlers
ss.addUserQueryAndCommandHandlers()
ss.addAlertNotificationUidByIdHandler()
ss.addPreferencesQueryAndCommandHandlers()
err = ss.logOrgsNotice()
if err != nil {
+30
View File
@@ -1,9 +1,16 @@
package setting
import (
"time"
"gopkg.in/ini.v1"
)
type DateFormats struct {
FullDate string `json:"fullDate"`
UseBrowserLocale bool `json:"useBrowserLocale"`
Interval DateFormatIntervals `json:"interval"`
DefaultTimezone string `json:"defaultTimezone"`
}
type DateFormatIntervals struct {
@@ -15,6 +22,23 @@ type DateFormatIntervals struct {
Year string `json:"year"`
}
const LocalBrowserTimezone = "browser"
func valueAsTimezone(section *ini.Section, keyName string, defaultValue string) (string, error) {
timezone := section.Key(keyName).MustString(defaultValue)
if timezone == LocalBrowserTimezone {
return LocalBrowserTimezone, nil
}
location, err := time.LoadLocation(timezone)
if err != nil {
return LocalBrowserTimezone, err
}
return location.String(), nil
}
func (cfg *Cfg) readDateFormats() {
dateFormats := cfg.Raw.Section("date_formats")
cfg.DateFormats.FullDate = valueAsString(dateFormats, "full_date", "YYYY-MM-DD HH:mm:ss")
@@ -25,4 +49,10 @@ func (cfg *Cfg) readDateFormats() {
cfg.DateFormats.Interval.Month = valueAsString(dateFormats, "interval_month", "YYYY-MM")
cfg.DateFormats.Interval.Year = "YYYY"
cfg.DateFormats.UseBrowserLocale = dateFormats.Key("date_format_use_browser_locale").MustBool(false)
timezone, err := valueAsTimezone(dateFormats, "default_timezone", LocalBrowserTimezone)
if err != nil {
cfg.Logger.Warn("Unknown timezone as default_timezone", "err", err)
}
cfg.DateFormats.DefaultTimezone = timezone
}
+37
View File
@@ -0,0 +1,37 @@
package setting
import (
"testing"
"gopkg.in/ini.v1"
"github.com/stretchr/testify/assert"
)
func TestValueAsTimezone(t *testing.T) {
tests := map[string]struct {
output string
hasErr bool
}{
"browser": {"browser", false},
"UTC": {"UTC", false},
"utc": {"browser", true},
"Amsterdam": {"browser", true},
"europe/amsterdam": {"browser", true},
"Europe/Amsterdam": {"Europe/Amsterdam", false},
}
sec, err := ini.Empty().NewSection("test")
assert.NoError(t, err)
key, err := sec.NewKey("test", "")
assert.NoError(t, err)
for input, expected := range tests {
key.SetValue(input)
output, err := valueAsTimezone(sec, "test", "default")
assert.Equal(t, expected.hasErr, err != nil, "Invalid has err for input: %s err: %v", input, err)
assert.Equal(t, expected.output, output, "Invalid output for input: %s", input)
}
}