mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat: team preferences
This commit is contained in:
@@ -155,6 +155,8 @@ func (hs *HTTPServer) registerRoutes() {
|
|||||||
teamsRoute.Get("/:teamId/members", Wrap(GetTeamMembers))
|
teamsRoute.Get("/:teamId/members", Wrap(GetTeamMembers))
|
||||||
teamsRoute.Post("/:teamId/members", bind(m.AddTeamMemberCommand{}), Wrap(AddTeamMember))
|
teamsRoute.Post("/:teamId/members", bind(m.AddTeamMemberCommand{}), Wrap(AddTeamMember))
|
||||||
teamsRoute.Delete("/:teamId/members/:userId", Wrap(RemoveTeamMember))
|
teamsRoute.Delete("/:teamId/members/:userId", Wrap(RemoveTeamMember))
|
||||||
|
teamsRoute.Get("/:teamId/preferences", Wrap(GetTeamPreferences))
|
||||||
|
teamsRoute.Put("/:teamId/preferences", bind(dtos.UpdatePrefsCmd{}), Wrap(UpdateTeamPreferences))
|
||||||
}, reqOrgAdmin)
|
}, reqOrgAdmin)
|
||||||
|
|
||||||
// team without requirement of user to be org admin
|
// team without requirement of user to be org admin
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ func PostDashboard(c *m.ReqContext, cmd m.SaveDashboardCommand) Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetHomeDashboard(c *m.ReqContext) Response {
|
func GetHomeDashboard(c *m.ReqContext) Response {
|
||||||
prefsQuery := m.GetPreferencesWithDefaultsQuery{OrgId: c.OrgId, UserId: c.UserId}
|
prefsQuery := m.GetPreferencesWithDefaultsQuery{User: c.SignedInUser}
|
||||||
if err := bus.Dispatch(&prefsQuery); err != nil {
|
if err := bus.Dispatch(&prefsQuery); err != nil {
|
||||||
return Error(500, "Failed to get preferences", err)
|
return Error(500, "Failed to get preferences", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func (hs *HTTPServer) setIndexViewData(c *m.ReqContext) (*dtos.IndexViewData, er
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
prefsQuery := m.GetPreferencesWithDefaultsQuery{OrgId: c.OrgId, UserId: c.UserId}
|
prefsQuery := m.GetPreferencesWithDefaultsQuery{User: c.SignedInUser}
|
||||||
if err := bus.Dispatch(&prefsQuery); err != nil {
|
if err := bus.Dispatch(&prefsQuery); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ func SetHomeDashboard(c *m.ReqContext, cmd m.SavePreferencesCommand) Response {
|
|||||||
|
|
||||||
// GET /api/user/preferences
|
// GET /api/user/preferences
|
||||||
func GetUserPreferences(c *m.ReqContext) Response {
|
func GetUserPreferences(c *m.ReqContext) Response {
|
||||||
return getPreferencesFor(c.OrgId, c.UserId)
|
return getPreferencesFor(c.OrgId, c.UserId, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPreferencesFor(orgID int64, userID int64) Response {
|
func getPreferencesFor(orgID, userID, teamID int64) Response {
|
||||||
prefsQuery := m.GetPreferencesQuery{UserId: userID, OrgId: orgID}
|
prefsQuery := m.GetPreferencesQuery{UserId: userID, OrgId: orgID, TeamId: teamID}
|
||||||
|
|
||||||
if err := bus.Dispatch(&prefsQuery); err != nil {
|
if err := bus.Dispatch(&prefsQuery); err != nil {
|
||||||
return Error(500, "Failed to get preferences", err)
|
return Error(500, "Failed to get preferences", err)
|
||||||
@@ -42,13 +42,14 @@ func getPreferencesFor(orgID int64, userID int64) Response {
|
|||||||
|
|
||||||
// PUT /api/user/preferences
|
// PUT /api/user/preferences
|
||||||
func UpdateUserPreferences(c *m.ReqContext, dtoCmd dtos.UpdatePrefsCmd) Response {
|
func UpdateUserPreferences(c *m.ReqContext, dtoCmd dtos.UpdatePrefsCmd) Response {
|
||||||
return updatePreferencesFor(c.OrgId, c.UserId, &dtoCmd)
|
return updatePreferencesFor(c.OrgId, c.UserId, 0, &dtoCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePreferencesFor(orgID int64, userID int64, dtoCmd *dtos.UpdatePrefsCmd) Response {
|
func updatePreferencesFor(orgID, userID, teamId int64, dtoCmd *dtos.UpdatePrefsCmd) Response {
|
||||||
saveCmd := m.SavePreferencesCommand{
|
saveCmd := m.SavePreferencesCommand{
|
||||||
UserId: userID,
|
UserId: userID,
|
||||||
OrgId: orgID,
|
OrgId: orgID,
|
||||||
|
TeamId: teamId,
|
||||||
Theme: dtoCmd.Theme,
|
Theme: dtoCmd.Theme,
|
||||||
Timezone: dtoCmd.Timezone,
|
Timezone: dtoCmd.Timezone,
|
||||||
HomeDashboardId: dtoCmd.HomeDashboardID,
|
HomeDashboardId: dtoCmd.HomeDashboardID,
|
||||||
@@ -63,10 +64,10 @@ func updatePreferencesFor(orgID int64, userID int64, dtoCmd *dtos.UpdatePrefsCmd
|
|||||||
|
|
||||||
// GET /api/org/preferences
|
// GET /api/org/preferences
|
||||||
func GetOrgPreferences(c *m.ReqContext) Response {
|
func GetOrgPreferences(c *m.ReqContext) Response {
|
||||||
return getPreferencesFor(c.OrgId, 0)
|
return getPreferencesFor(c.OrgId, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT /api/org/preferences
|
// PUT /api/org/preferences
|
||||||
func UpdateOrgPreferences(c *m.ReqContext, dtoCmd dtos.UpdatePrefsCmd) Response {
|
func UpdateOrgPreferences(c *m.ReqContext, dtoCmd dtos.UpdatePrefsCmd) Response {
|
||||||
return updatePreferencesFor(c.OrgId, 0, &dtoCmd)
|
return updatePreferencesFor(c.OrgId, 0, 0, &dtoCmd)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,3 +96,13 @@ func GetTeamByID(c *m.ReqContext) Response {
|
|||||||
query.Result.AvatarUrl = dtos.GetGravatarUrlWithDefault(query.Result.Email, query.Result.Name)
|
query.Result.AvatarUrl = dtos.GetGravatarUrlWithDefault(query.Result.Email, query.Result.Name)
|
||||||
return JSON(200, &query.Result)
|
return JSON(200, &query.Result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GET /api/teams/:teamId/preferences
|
||||||
|
func GetTeamPreferences(c *m.ReqContext) Response {
|
||||||
|
return getPreferencesFor(c.OrgId, 0, c.ParamsInt64(":teamId"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PUT /api/teams/:teamId/preferences
|
||||||
|
func UpdateTeamPreferences(c *m.ReqContext, dtoCmd dtos.UpdatePrefsCmd) Response {
|
||||||
|
return updatePreferencesFor(c.OrgId, 0, c.ParamsInt64(":teamId"), &dtoCmd)
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type Preferences struct {
|
|||||||
Id int64
|
Id int64
|
||||||
OrgId int64
|
OrgId int64
|
||||||
UserId int64
|
UserId int64
|
||||||
|
TeamId int64
|
||||||
Version int
|
Version int
|
||||||
HomeDashboardId int64
|
HomeDashboardId int64
|
||||||
Timezone string
|
Timezone string
|
||||||
@@ -29,14 +30,13 @@ type GetPreferencesQuery struct {
|
|||||||
Id int64
|
Id int64
|
||||||
OrgId int64
|
OrgId int64
|
||||||
UserId int64
|
UserId int64
|
||||||
|
TeamId int64
|
||||||
|
|
||||||
Result *Preferences
|
Result *Preferences
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetPreferencesWithDefaultsQuery struct {
|
type GetPreferencesWithDefaultsQuery struct {
|
||||||
Id int64
|
User *SignedInUser
|
||||||
OrgId int64
|
|
||||||
UserId int64
|
|
||||||
|
|
||||||
Result *Preferences
|
Result *Preferences
|
||||||
}
|
}
|
||||||
@@ -46,6 +46,7 @@ type GetPreferencesWithDefaultsQuery struct {
|
|||||||
type SavePreferencesCommand struct {
|
type SavePreferencesCommand struct {
|
||||||
UserId int64
|
UserId int64
|
||||||
OrgId int64
|
OrgId int64
|
||||||
|
TeamId int64
|
||||||
|
|
||||||
HomeDashboardId int64 `json:"homeDashboardId"`
|
HomeDashboardId int64 `json:"homeDashboardId"`
|
||||||
Timezone string `json:"timezone"`
|
Timezone string `json:"timezone"`
|
||||||
|
|||||||
@@ -34,4 +34,13 @@ func addPreferencesMigrations(mg *Migrator) {
|
|||||||
{Name: "timezone", Type: DB_NVarchar, Length: 50, Nullable: false},
|
{Name: "timezone", Type: DB_NVarchar, Length: 50, Nullable: false},
|
||||||
{Name: "theme", Type: DB_NVarchar, Length: 20, Nullable: false},
|
{Name: "theme", Type: DB_NVarchar, Length: 20, Nullable: false},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
mg.AddMigration("Add column team_id in preferences", NewAddColumnMigration(preferencesV2, &Column{
|
||||||
|
Name: "team_id", Type: DB_BigInt, Nullable: true,
|
||||||
|
}))
|
||||||
|
|
||||||
|
mg.AddMigration("Update team_id column values in preferences", NewRawSqlMigration("").
|
||||||
|
Sqlite("UPDATE preferences SET team_id=0 WHERE team_id IS NULL;").
|
||||||
|
Postgres("UPDATE preferences SET team_id=0 WHERE team_id IS NULL;").
|
||||||
|
Mysql("UPDATE preferences SET team_id=0 WHERE team_id IS NULL;"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package sqlstore
|
package sqlstore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
@@ -16,11 +17,22 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetPreferencesWithDefaults(query *m.GetPreferencesWithDefaultsQuery) error {
|
func GetPreferencesWithDefaults(query *m.GetPreferencesWithDefaultsQuery) error {
|
||||||
|
params := make([]interface{}, 0)
|
||||||
|
filter := ""
|
||||||
|
if len(query.User.Teams) > 0 {
|
||||||
|
filter = "(org_id=? AND team_id IN (?" + strings.Repeat(",?", len(query.User.Teams)-1) + ")) OR "
|
||||||
|
params = append(params, query.User.OrgId)
|
||||||
|
for _, v := range query.User.Teams {
|
||||||
|
params = append(params, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filter += "(org_id=? AND user_id=? AND team_id=0) OR (org_id=? AND team_id=0 AND user_id=0)"
|
||||||
|
params = append(params, query.User.OrgId)
|
||||||
|
params = append(params, query.User.UserId)
|
||||||
|
params = append(params, query.User.OrgId)
|
||||||
prefs := make([]*m.Preferences, 0)
|
prefs := make([]*m.Preferences, 0)
|
||||||
filter := "(org_id=? AND user_id=?) OR (org_id=? AND user_id=0)"
|
err := x.Where(filter, params...).
|
||||||
err := x.Where(filter, query.OrgId, query.UserId, query.OrgId).
|
OrderBy("user_id ASC, team_id ASC").
|
||||||
OrderBy("user_id ASC").
|
|
||||||
Find(&prefs)
|
Find(&prefs)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -50,9 +62,8 @@ func GetPreferencesWithDefaults(query *m.GetPreferencesWithDefaultsQuery) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetPreferences(query *m.GetPreferencesQuery) error {
|
func GetPreferences(query *m.GetPreferencesQuery) error {
|
||||||
|
|
||||||
var prefs m.Preferences
|
var prefs m.Preferences
|
||||||
exists, err := x.Where("org_id=? AND user_id=?", query.OrgId, query.UserId).Get(&prefs)
|
exists, err := x.Where("org_id=? AND user_id=? AND team_id=?", query.OrgId, query.UserId, query.TeamId).Get(&prefs)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -71,7 +82,7 @@ func SavePreferences(cmd *m.SavePreferencesCommand) error {
|
|||||||
return inTransaction(func(sess *DBSession) error {
|
return inTransaction(func(sess *DBSession) error {
|
||||||
|
|
||||||
var prefs m.Preferences
|
var prefs m.Preferences
|
||||||
exists, err := sess.Where("org_id=? AND user_id=?", cmd.OrgId, cmd.UserId).Get(&prefs)
|
exists, err := sess.Where("org_id=? AND user_id=? AND team_id=?", cmd.OrgId, cmd.UserId, cmd.TeamId).Get(&prefs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -80,6 +91,7 @@ func SavePreferences(cmd *m.SavePreferencesCommand) error {
|
|||||||
prefs = m.Preferences{
|
prefs = m.Preferences{
|
||||||
UserId: cmd.UserId,
|
UserId: cmd.UserId,
|
||||||
OrgId: cmd.OrgId,
|
OrgId: cmd.OrgId,
|
||||||
|
TeamId: cmd.TeamId,
|
||||||
HomeDashboardId: cmd.HomeDashboardId,
|
HomeDashboardId: cmd.HomeDashboardId,
|
||||||
Timezone: cmd.Timezone,
|
Timezone: cmd.Timezone,
|
||||||
Theme: cmd.Theme,
|
Theme: cmd.Theme,
|
||||||
|
|||||||
91
pkg/services/sqlstore/preferences_test.go
Normal file
91
pkg/services/sqlstore/preferences_test.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package sqlstore
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPreferencesDataAccess(t *testing.T) {
|
||||||
|
Convey("Testing preferences data access", t, func() {
|
||||||
|
InitTestDB(t)
|
||||||
|
|
||||||
|
Convey("GetPreferencesWithDefaults with no saved preferences should return defaults", func() {
|
||||||
|
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{}}
|
||||||
|
err := GetPreferencesWithDefaults(query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(query.Result.Theme, ShouldEqual, setting.DefaultTheme)
|
||||||
|
So(query.Result.Timezone, ShouldEqual, "browser")
|
||||||
|
So(query.Result.HomeDashboardId, ShouldEqual, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("GetPreferencesWithDefaults with saved org and user home dashboard should return user home dashboard", func() {
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, HomeDashboardId: 1})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, UserId: 1, HomeDashboardId: 4})
|
||||||
|
|
||||||
|
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{OrgId: 1, UserId: 1}}
|
||||||
|
err := GetPreferencesWithDefaults(query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(query.Result.HomeDashboardId, ShouldEqual, 4)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("GetPreferencesWithDefaults with saved org and other user home dashboard should return org home dashboard", func() {
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, HomeDashboardId: 1})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, UserId: 1, HomeDashboardId: 4})
|
||||||
|
|
||||||
|
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{OrgId: 1, UserId: 2}}
|
||||||
|
err := GetPreferencesWithDefaults(query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(query.Result.HomeDashboardId, ShouldEqual, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("GetPreferencesWithDefaults with saved org and teams home dashboard should return last team home dashboard", func() {
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, HomeDashboardId: 1})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, TeamId: 2, HomeDashboardId: 2})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, TeamId: 3, HomeDashboardId: 3})
|
||||||
|
|
||||||
|
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{OrgId: 1, Teams: []int64{2, 3}}}
|
||||||
|
err := GetPreferencesWithDefaults(query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(query.Result.HomeDashboardId, ShouldEqual, 3)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("GetPreferencesWithDefaults with saved org and other teams home dashboard should return org home dashboard", func() {
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, HomeDashboardId: 1})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, TeamId: 2, HomeDashboardId: 2})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, TeamId: 3, HomeDashboardId: 3})
|
||||||
|
|
||||||
|
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{OrgId: 1}}
|
||||||
|
err := GetPreferencesWithDefaults(query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(query.Result.HomeDashboardId, ShouldEqual, 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("GetPreferencesWithDefaults with saved org, teams and user home dashboard should return user home dashboard", func() {
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, HomeDashboardId: 1})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, TeamId: 2, HomeDashboardId: 2})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, TeamId: 3, HomeDashboardId: 3})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, UserId: 1, HomeDashboardId: 4})
|
||||||
|
|
||||||
|
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{OrgId: 1, UserId: 1, Teams: []int64{2, 3}}}
|
||||||
|
err := GetPreferencesWithDefaults(query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(query.Result.HomeDashboardId, ShouldEqual, 4)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("GetPreferencesWithDefaults with saved org, other teams and user home dashboard should return org home dashboard", func() {
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, HomeDashboardId: 1})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, TeamId: 2, HomeDashboardId: 2})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, TeamId: 3, HomeDashboardId: 3})
|
||||||
|
SavePreferences(&models.SavePreferencesCommand{OrgId: 1, UserId: 1, HomeDashboardId: 4})
|
||||||
|
|
||||||
|
query := &models.GetPreferencesWithDefaultsQuery{User: &models.SignedInUser{OrgId: 1, UserId: 2}}
|
||||||
|
err := GetPreferencesWithDefaults(query)
|
||||||
|
So(err, ShouldBeNil)
|
||||||
|
So(query.Result.HomeDashboardId, ShouldEqual, 1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user