mirror of
https://github.com/grafana/grafana.git
synced 2024-12-02 13:39:19 -06:00
9de00c8eb2
* chore/backend: move dashboard errors to dashboard service Dashboard-related models are slowly moving out of the models package and into dashboard services. This commit moves dashboard-related errors; the rest will come in later commits. There are no logical code changes, this is only a structural (package) move. * lint lint lint
594 lines
20 KiB
Go
594 lines
20 KiB
Go
package sqlstore
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/components/simplejson"
|
|
"github.com/grafana/grafana/pkg/models"
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
|
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
|
"github.com/grafana/grafana/pkg/services/user"
|
|
"github.com/grafana/grafana/pkg/util"
|
|
)
|
|
|
|
func TestIntegrationAccountDataAccess(t *testing.T) {
|
|
if testing.Short() {
|
|
t.Skip("skipping integration test")
|
|
}
|
|
t.Run("Testing Account DB Access", func(t *testing.T) {
|
|
sqlStore := InitTestDB(t)
|
|
testUser := &models.SignedInUser{
|
|
Permissions: map[int64]map[string][]string{
|
|
1: {accesscontrol.ActionOrgUsersRead: []string{accesscontrol.ScopeUsersAll}},
|
|
},
|
|
}
|
|
|
|
t.Run("Given we have organizations, we can query them by IDs", func(t *testing.T) {
|
|
var err error
|
|
var cmd *models.CreateOrgCommand
|
|
ids := []int64{}
|
|
|
|
for i := 1; i < 4; i++ {
|
|
cmd = &models.CreateOrgCommand{Name: fmt.Sprint("Org #", i)}
|
|
err = sqlStore.CreateOrg(context.Background(), cmd)
|
|
require.NoError(t, err)
|
|
|
|
ids = append(ids, cmd.Result.Id)
|
|
}
|
|
|
|
query := &models.SearchOrgsQuery{Ids: ids}
|
|
err = sqlStore.SearchOrgs(context.Background(), query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result), 3)
|
|
})
|
|
|
|
t.Run("Given we have organizations, we can limit and paginate search", func(t *testing.T) {
|
|
sqlStore = InitTestDB(t)
|
|
for i := 1; i < 4; i++ {
|
|
cmd := &models.CreateOrgCommand{Name: fmt.Sprint("Org #", i)}
|
|
err := sqlStore.CreateOrg(context.Background(), cmd)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
t.Run("Should be able to search with defaults", func(t *testing.T) {
|
|
query := &models.SearchOrgsQuery{}
|
|
err := sqlStore.SearchOrgs(context.Background(), query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result), 3)
|
|
})
|
|
|
|
t.Run("Should be able to limit search", func(t *testing.T) {
|
|
query := &models.SearchOrgsQuery{Limit: 1}
|
|
err := sqlStore.SearchOrgs(context.Background(), query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result), 1)
|
|
})
|
|
|
|
t.Run("Should be able to limit and paginate search", func(t *testing.T) {
|
|
query := &models.SearchOrgsQuery{Limit: 2, Page: 1}
|
|
err := sqlStore.SearchOrgs(context.Background(), query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result), 1)
|
|
})
|
|
})
|
|
|
|
t.Run("Given single org mode", func(t *testing.T) {
|
|
sqlStore.Cfg.AutoAssignOrg = true
|
|
sqlStore.Cfg.AutoAssignOrgId = 1
|
|
sqlStore.Cfg.AutoAssignOrgRole = "Viewer"
|
|
|
|
t.Run("Users should be added to default organization", func(t *testing.T) {
|
|
ac1cmd := user.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
|
|
ac2cmd := user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name"}
|
|
|
|
ac1, err := sqlStore.CreateUser(context.Background(), ac1cmd)
|
|
require.NoError(t, err)
|
|
ac2, err := sqlStore.CreateUser(context.Background(), ac2cmd)
|
|
require.NoError(t, err)
|
|
|
|
q1 := models.GetUserOrgListQuery{UserId: ac1.ID}
|
|
q2 := models.GetUserOrgListQuery{UserId: ac2.ID}
|
|
err = sqlStore.GetUserOrgList(context.Background(), &q1)
|
|
require.NoError(t, err)
|
|
err = sqlStore.GetUserOrgList(context.Background(), &q2)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, q1.Result[0].OrgId, q2.Result[0].OrgId)
|
|
require.Equal(t, string(q1.Result[0].Role), "Viewer")
|
|
})
|
|
})
|
|
|
|
t.Run("Given single org and 2 users inserted", func(t *testing.T) {
|
|
sqlStore = InitTestDB(t)
|
|
sqlStore.Cfg.AutoAssignOrg = true
|
|
sqlStore.Cfg.AutoAssignOrgId = 1
|
|
sqlStore.Cfg.AutoAssignOrgRole = "Viewer"
|
|
|
|
ac1cmd := user.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
|
|
ac2cmd := user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name"}
|
|
|
|
ac1, err := sqlStore.CreateUser(context.Background(), ac1cmd)
|
|
testUser.OrgId = ac1.OrgID
|
|
require.NoError(t, err)
|
|
_, err = sqlStore.CreateUser(context.Background(), ac2cmd)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("Can get organization users paginated with query", func(t *testing.T) {
|
|
query := models.SearchOrgUsersQuery{
|
|
OrgID: ac1.OrgID,
|
|
Page: 1,
|
|
User: testUser,
|
|
}
|
|
err = sqlStore.SearchOrgUsers(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result.OrgUsers), 2)
|
|
})
|
|
|
|
t.Run("Can get organization users paginated and limited", func(t *testing.T) {
|
|
query := models.SearchOrgUsersQuery{
|
|
OrgID: ac1.OrgID,
|
|
Limit: 1,
|
|
Page: 1,
|
|
User: testUser,
|
|
}
|
|
err = sqlStore.SearchOrgUsers(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result.OrgUsers), 1)
|
|
})
|
|
})
|
|
|
|
t.Run("Given two saved users", func(t *testing.T) {
|
|
sqlStore = InitTestDB(t)
|
|
sqlStore.Cfg.AutoAssignOrg = false
|
|
|
|
ac1cmd := user.CreateUserCommand{Login: "ac1", Email: "ac1@test.com", Name: "ac1 name"}
|
|
ac2cmd := user.CreateUserCommand{Login: "ac2", Email: "ac2@test.com", Name: "ac2 name", IsAdmin: true}
|
|
serviceaccountcmd := user.CreateUserCommand{Login: "serviceaccount", Email: "service@test.com", Name: "serviceaccount name", IsAdmin: true, IsServiceAccount: true}
|
|
|
|
ac1, err := sqlStore.CreateUser(context.Background(), ac1cmd)
|
|
require.NoError(t, err)
|
|
ac2, err := sqlStore.CreateUser(context.Background(), ac2cmd)
|
|
require.NoError(t, err)
|
|
// user only used for making sure we filter out the service accounts
|
|
_, err = sqlStore.CreateUser(context.Background(), serviceaccountcmd)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("Should be able to read user info projection", func(t *testing.T) {
|
|
query := models.GetUserProfileQuery{UserId: ac1.ID}
|
|
err = sqlStore.GetUserProfile(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, query.Result.Email, "ac1@test.com")
|
|
require.Equal(t, query.Result.Login, "ac1")
|
|
})
|
|
|
|
t.Run("Can search users", func(t *testing.T) {
|
|
query := models.SearchUsersQuery{Query: "", SignedInUser: &models.SignedInUser{
|
|
OrgId: 1,
|
|
Permissions: map[int64]map[string][]string{
|
|
1: {accesscontrol.ActionUsersRead: {accesscontrol.ScopeGlobalUsersAll}},
|
|
},
|
|
}}
|
|
err := sqlStore.SearchUsers(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Len(t, query.Result.Users, 2)
|
|
require.Equal(t, query.Result.Users[0].Email, "ac1@test.com")
|
|
require.Equal(t, query.Result.Users[1].Email, "ac2@test.com")
|
|
})
|
|
|
|
t.Run("Given an added org user", func(t *testing.T) {
|
|
cmd := models.AddOrgUserCommand{
|
|
OrgId: ac1.OrgID,
|
|
UserId: ac2.ID,
|
|
Role: models.ROLE_VIEWER,
|
|
}
|
|
|
|
err := sqlStore.AddOrgUser(context.Background(), &cmd)
|
|
t.Run("Should have been saved without error", func(t *testing.T) {
|
|
require.NoError(t, err)
|
|
})
|
|
|
|
t.Run("Can update org user role", func(t *testing.T) {
|
|
updateCmd := models.UpdateOrgUserCommand{OrgId: ac1.OrgID, UserId: ac2.ID, Role: models.ROLE_ADMIN}
|
|
err = sqlStore.UpdateOrgUser(context.Background(), &updateCmd)
|
|
require.NoError(t, err)
|
|
|
|
orgUsersQuery := models.GetOrgUsersQuery{
|
|
OrgId: ac1.OrgID,
|
|
User: &models.SignedInUser{
|
|
OrgId: ac1.OrgID,
|
|
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
|
|
},
|
|
}
|
|
err = sqlStore.GetOrgUsers(context.Background(), &orgUsersQuery)
|
|
require.NoError(t, err)
|
|
|
|
require.EqualValues(t, orgUsersQuery.Result[1].Role, models.ROLE_ADMIN)
|
|
})
|
|
|
|
t.Run("Can get logged in user projection", func(t *testing.T) {
|
|
query := models.GetSignedInUserQuery{UserId: ac2.ID}
|
|
err := sqlStore.GetSignedInUser(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, query.Result.Email, "ac2@test.com")
|
|
require.Equal(t, query.Result.OrgId, ac2.OrgID)
|
|
require.Equal(t, query.Result.Name, "ac2 name")
|
|
require.Equal(t, query.Result.Login, "ac2")
|
|
require.EqualValues(t, query.Result.OrgRole, "Admin")
|
|
require.Equal(t, query.Result.OrgName, "ac2@test.com")
|
|
require.Equal(t, query.Result.IsGrafanaAdmin, true)
|
|
})
|
|
|
|
t.Run("Can get user organizations", func(t *testing.T) {
|
|
query := models.GetUserOrgListQuery{UserId: ac2.ID}
|
|
err := sqlStore.GetUserOrgList(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result), 2)
|
|
})
|
|
|
|
t.Run("Can get organization users", func(t *testing.T) {
|
|
query := models.GetOrgUsersQuery{
|
|
OrgId: ac1.OrgID,
|
|
User: &models.SignedInUser{
|
|
OrgId: ac1.OrgID,
|
|
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
|
|
},
|
|
}
|
|
err := sqlStore.GetOrgUsers(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result), 2)
|
|
require.Equal(t, query.Result[0].Role, "Admin")
|
|
})
|
|
|
|
t.Run("Can get organization users with query", func(t *testing.T) {
|
|
query := models.GetOrgUsersQuery{
|
|
OrgId: ac1.OrgID,
|
|
Query: "ac1",
|
|
User: &models.SignedInUser{
|
|
OrgId: ac1.OrgID,
|
|
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
|
|
},
|
|
}
|
|
err := sqlStore.GetOrgUsers(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result), 1)
|
|
require.Equal(t, query.Result[0].Email, ac1.Email)
|
|
})
|
|
|
|
t.Run("Can get organization users with query and limit", func(t *testing.T) {
|
|
query := models.GetOrgUsersQuery{
|
|
OrgId: ac1.OrgID,
|
|
Query: "ac",
|
|
Limit: 1,
|
|
User: &models.SignedInUser{
|
|
OrgId: ac1.OrgID,
|
|
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
|
|
},
|
|
}
|
|
err := sqlStore.GetOrgUsers(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(query.Result), 1)
|
|
require.Equal(t, query.Result[0].Email, ac1.Email)
|
|
})
|
|
|
|
t.Run("Can set using org", func(t *testing.T) {
|
|
cmd := models.SetUsingOrgCommand{UserId: ac2.ID, OrgId: ac1.OrgID}
|
|
err := sqlStore.SetUsingOrg(context.Background(), &cmd)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("SignedInUserQuery with a different org", func(t *testing.T) {
|
|
query := models.GetSignedInUserQuery{UserId: ac2.ID}
|
|
err := sqlStore.GetSignedInUser(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, query.Result.OrgId, ac1.OrgID)
|
|
require.Equal(t, query.Result.Email, "ac2@test.com")
|
|
require.Equal(t, query.Result.Name, "ac2 name")
|
|
require.Equal(t, query.Result.Login, "ac2")
|
|
require.Equal(t, query.Result.OrgName, "ac1@test.com")
|
|
})
|
|
|
|
t.Run("Should set last org as current when removing user from current", func(t *testing.T) {
|
|
remCmd := models.RemoveOrgUserCommand{OrgId: ac1.OrgID, UserId: ac2.ID}
|
|
err := sqlStore.RemoveOrgUser(context.Background(), &remCmd)
|
|
require.NoError(t, err)
|
|
|
|
query := models.GetSignedInUserQuery{UserId: ac2.ID}
|
|
err = sqlStore.GetSignedInUser(context.Background(), &query)
|
|
|
|
require.NoError(t, err)
|
|
require.Equal(t, query.Result.OrgId, ac2.OrgID)
|
|
})
|
|
})
|
|
|
|
t.Run("Removing user from org should delete user completely if in no other org", func(t *testing.T) {
|
|
// make sure ac2 has no org
|
|
err := sqlStore.DeleteOrg(context.Background(), &models.DeleteOrgCommand{Id: ac2.OrgID})
|
|
require.NoError(t, err)
|
|
|
|
// remove ac2 user from ac1 org
|
|
remCmd := models.RemoveOrgUserCommand{OrgId: ac1.OrgID, UserId: ac2.ID, ShouldDeleteOrphanedUser: true}
|
|
err = sqlStore.RemoveOrgUser(context.Background(), &remCmd)
|
|
require.NoError(t, err)
|
|
require.True(t, remCmd.UserWasDeleted)
|
|
|
|
err = sqlStore.GetSignedInUser(context.Background(), &models.GetSignedInUserQuery{UserId: ac2.ID})
|
|
require.Equal(t, err, models.ErrUserNotFound)
|
|
})
|
|
|
|
t.Run("Cannot delete last admin org user", func(t *testing.T) {
|
|
cmd := models.RemoveOrgUserCommand{OrgId: ac1.OrgID, UserId: ac1.ID}
|
|
err := sqlStore.RemoveOrgUser(context.Background(), &cmd)
|
|
require.Equal(t, err, models.ErrLastOrgAdmin)
|
|
})
|
|
|
|
t.Run("Cannot update role so no one is admin user", func(t *testing.T) {
|
|
cmd := models.UpdateOrgUserCommand{OrgId: ac1.OrgID, UserId: ac1.ID, Role: models.ROLE_VIEWER}
|
|
err := sqlStore.UpdateOrgUser(context.Background(), &cmd)
|
|
require.Equal(t, err, models.ErrLastOrgAdmin)
|
|
})
|
|
|
|
t.Run("Given an org user with dashboard permissions", func(t *testing.T) {
|
|
ac3cmd := user.CreateUserCommand{Login: "ac3", Email: "ac3@test.com", Name: "ac3 name", IsAdmin: false}
|
|
ac3, err := sqlStore.CreateUser(context.Background(), ac3cmd)
|
|
require.NoError(t, err)
|
|
|
|
orgUserCmd := models.AddOrgUserCommand{
|
|
OrgId: ac1.OrgID,
|
|
UserId: ac3.ID,
|
|
Role: models.ROLE_VIEWER,
|
|
}
|
|
|
|
err = sqlStore.AddOrgUser(context.Background(), &orgUserCmd)
|
|
require.NoError(t, err)
|
|
|
|
query := models.GetOrgUsersQuery{
|
|
OrgId: ac1.OrgID,
|
|
User: &models.SignedInUser{
|
|
OrgId: ac1.OrgID,
|
|
Permissions: map[int64]map[string][]string{ac1.OrgID: {accesscontrol.ActionOrgUsersRead: {accesscontrol.ScopeUsersAll}}},
|
|
},
|
|
}
|
|
err = sqlStore.GetOrgUsers(context.Background(), &query)
|
|
require.NoError(t, err)
|
|
// require.Equal(t, len(query.Result), 3)
|
|
|
|
dash1 := insertTestDashboard(t, sqlStore, "1 test dash", ac1.OrgID, 0, false, "prod", "webapp")
|
|
dash2 := insertTestDashboard(t, sqlStore, "2 test dash", ac3.OrgID, 0, false, "prod", "webapp")
|
|
|
|
err = updateDashboardAcl(t, sqlStore, dash1.Id, &models.DashboardAcl{
|
|
DashboardID: dash1.Id, OrgID: ac1.OrgID, UserID: ac3.ID, Permission: models.PERMISSION_EDIT,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
err = updateDashboardAcl(t, sqlStore, dash2.Id, &models.DashboardAcl{
|
|
DashboardID: dash2.Id, OrgID: ac3.OrgID, UserID: ac3.ID, Permission: models.PERMISSION_EDIT,
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
t.Run("When org user is deleted", func(t *testing.T) {
|
|
cmdRemove := models.RemoveOrgUserCommand{OrgId: ac1.OrgID, UserId: ac3.ID}
|
|
err := sqlStore.RemoveOrgUser(context.Background(), &cmdRemove)
|
|
require.NoError(t, err)
|
|
|
|
t.Run("Should remove dependent permissions for deleted org user", func(t *testing.T) {
|
|
permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: dash1.Id, OrgID: ac1.OrgID}
|
|
|
|
err = getDashboardAclInfoList(sqlStore, permQuery)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, len(permQuery.Result), 0)
|
|
})
|
|
|
|
t.Run("Should not remove dashboard permissions for same user in another org", func(t *testing.T) {
|
|
permQuery := &models.GetDashboardAclInfoListQuery{DashboardID: dash2.Id, OrgID: ac3.OrgID}
|
|
|
|
err = getDashboardAclInfoList(sqlStore, permQuery)
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, len(permQuery.Result), 1)
|
|
require.Equal(t, permQuery.Result[0].OrgId, ac3.OrgID)
|
|
require.Equal(t, permQuery.Result[0].UserId, ac3.ID)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
//TODO: Use FakeDashboardStore when org has its own service
|
|
func insertTestDashboard(t *testing.T, sqlStore *SQLStore, title string, orgId int64,
|
|
folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
|
|
t.Helper()
|
|
cmd := models.SaveDashboardCommand{
|
|
OrgId: orgId,
|
|
FolderId: folderId,
|
|
IsFolder: isFolder,
|
|
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
|
"id": nil,
|
|
"title": title,
|
|
"tags": tags,
|
|
}),
|
|
}
|
|
|
|
var dash *models.Dashboard
|
|
err := sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
|
|
dash = cmd.GetDashboardModel()
|
|
dash.SetVersion(1)
|
|
dash.Created = time.Now()
|
|
dash.Updated = time.Now()
|
|
dash.Uid = util.GenerateShortUID()
|
|
_, err := sess.Insert(dash)
|
|
return err
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, dash)
|
|
dash.Data.Set("id", dash.Id)
|
|
dash.Data.Set("uid", dash.Uid)
|
|
|
|
err = sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
|
|
dashVersion := &dashver.DashboardVersion{
|
|
DashboardID: dash.Id,
|
|
ParentVersion: dash.Version,
|
|
RestoredFrom: cmd.RestoredFrom,
|
|
Version: dash.Version,
|
|
Created: time.Now(),
|
|
CreatedBy: dash.UpdatedBy,
|
|
Message: cmd.Message,
|
|
Data: dash.Data,
|
|
}
|
|
require.NoError(t, err)
|
|
|
|
if affectedRows, err := sess.Insert(dashVersion); err != nil {
|
|
return err
|
|
} else if affectedRows == 0 {
|
|
return dashboards.ErrDashboardNotFound
|
|
}
|
|
|
|
return nil
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
return dash
|
|
}
|
|
|
|
//TODO: Use FakeDashboardStore when org has its own service
|
|
func updateDashboardAcl(t *testing.T, sqlStore *SQLStore, dashboardID int64, items ...*models.DashboardAcl) error {
|
|
t.Helper()
|
|
|
|
err := sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
|
|
_, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", dashboardID)
|
|
if err != nil {
|
|
return fmt.Errorf("deleting from dashboard_acl failed: %w", err)
|
|
}
|
|
|
|
for _, item := range items {
|
|
item.Created = time.Now()
|
|
item.Updated = time.Now()
|
|
if item.UserID == 0 && item.TeamID == 0 && (item.Role == nil || !item.Role.IsValid()) {
|
|
return models.ErrDashboardAclInfoMissing
|
|
}
|
|
|
|
if item.DashboardID == 0 {
|
|
return models.ErrDashboardPermissionDashboardEmpty
|
|
}
|
|
|
|
sess.Nullable("user_id", "team_id")
|
|
if _, err := sess.Insert(item); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Update dashboard HasAcl flag
|
|
dashboard := models.Dashboard{HasAcl: true}
|
|
_, err = sess.Cols("has_acl").Where("id=?", dashboardID).Update(&dashboard)
|
|
return err
|
|
})
|
|
return err
|
|
}
|
|
|
|
// This function was copied from pkg/services/dashboards/database to circumvent
|
|
// import cycles. When this org-related code is refactored into a service the
|
|
// tests can the real GetDashboardAclInfoList functions
|
|
func getDashboardAclInfoList(s *SQLStore, query *models.GetDashboardAclInfoListQuery) error {
|
|
outerErr := s.WithDbSession(context.Background(), func(dbSession *DBSession) error {
|
|
query.Result = make([]*models.DashboardAclInfoDTO, 0)
|
|
falseStr := dialect.BooleanStr(false)
|
|
|
|
if query.DashboardID == 0 {
|
|
sql := `SELECT
|
|
da.id,
|
|
da.org_id,
|
|
da.dashboard_id,
|
|
da.user_id,
|
|
da.team_id,
|
|
da.permission,
|
|
da.role,
|
|
da.created,
|
|
da.updated,
|
|
'' as user_login,
|
|
'' as user_email,
|
|
'' as team,
|
|
'' as title,
|
|
'' as slug,
|
|
'' as uid,` +
|
|
falseStr + ` AS is_folder,` +
|
|
falseStr + ` AS inherited
|
|
FROM dashboard_acl as da
|
|
WHERE da.dashboard_id = -1`
|
|
return dbSession.SQL(sql).Find(&query.Result)
|
|
}
|
|
|
|
rawSQL := `
|
|
-- get permissions for the dashboard and its parent folder
|
|
SELECT
|
|
da.id,
|
|
da.org_id,
|
|
da.dashboard_id,
|
|
da.user_id,
|
|
da.team_id,
|
|
da.permission,
|
|
da.role,
|
|
da.created,
|
|
da.updated,
|
|
u.login AS user_login,
|
|
u.email AS user_email,
|
|
ug.name AS team,
|
|
ug.email AS team_email,
|
|
d.title,
|
|
d.slug,
|
|
d.uid,
|
|
d.is_folder,
|
|
CASE WHEN (da.dashboard_id = -1 AND d.folder_id > 0) OR da.dashboard_id = d.folder_id THEN ` + dialect.BooleanStr(true) + ` ELSE ` + falseStr + ` END AS inherited
|
|
FROM dashboard as d
|
|
LEFT JOIN dashboard folder on folder.id = d.folder_id
|
|
LEFT JOIN dashboard_acl AS da ON
|
|
da.dashboard_id = d.id OR
|
|
da.dashboard_id = d.folder_id OR
|
|
(
|
|
-- include default permissions -->
|
|
da.org_id = -1 AND (
|
|
(folder.id IS NOT NULL AND folder.has_acl = ` + falseStr + `) OR
|
|
(folder.id IS NULL AND d.has_acl = ` + falseStr + `)
|
|
)
|
|
)
|
|
LEFT JOIN ` + dialect.Quote("user") + ` AS u ON u.id = da.user_id
|
|
LEFT JOIN team ug on ug.id = da.team_id
|
|
WHERE d.org_id = ? AND d.id = ? AND da.id IS NOT NULL
|
|
ORDER BY da.id ASC
|
|
`
|
|
|
|
return dbSession.SQL(rawSQL, query.OrgID, query.DashboardID).Find(&query.Result)
|
|
})
|
|
|
|
if outerErr != nil {
|
|
return outerErr
|
|
}
|
|
|
|
for _, p := range query.Result {
|
|
p.PermissionName = p.Permission.String()
|
|
}
|
|
|
|
return nil
|
|
}
|