permissions: refactoring of acl api and query

This commit is contained in:
Torkel Ödegaard
2018-02-14 14:31:20 +01:00
parent db89ac4134
commit ec6f0f94b8
14 changed files with 40 additions and 385 deletions
+1 -31
View File
@@ -79,11 +79,6 @@ func saveDashboard(sess *DBSession, cmd *m.SaveDashboardCommand) error {
dash.Data.Set("uid", uid)
}
err = setHasAcl(sess, dash)
if err != nil {
return err
}
parentVersion := dash.Version
affectedRows := int64(0)
@@ -100,7 +95,7 @@ func saveDashboard(sess *DBSession, cmd *m.SaveDashboardCommand) error {
dash.Updated = cmd.UpdatedAt
}
affectedRows, err = sess.MustCols("folder_id", "has_acl").ID(dash.Id).Update(dash)
affectedRows, err = sess.MustCols("folder_id").ID(dash.Id).Update(dash)
}
if err != nil {
@@ -233,31 +228,6 @@ func generateNewDashboardUid(sess *DBSession, orgId int64) (string, error) {
return "", m.ErrDashboardFailedGenerateUniqueUid
}
func setHasAcl(sess *DBSession, dash *m.Dashboard) error {
// check if parent has acl
if dash.FolderId > 0 {
var parent m.Dashboard
if hasParent, err := sess.Where("folder_id=?", dash.FolderId).Get(&parent); err != nil {
return err
} else if hasParent && parent.HasAcl {
dash.HasAcl = true
}
}
// check if dash has its own acl
if dash.Id > 0 {
if res, err := sess.Query("SELECT 1 from dashboard_acl WHERE dashboard_id =?", dash.Id); err != nil {
return err
} else {
if len(res) > 0 {
dash.HasAcl = true
}
}
}
return nil
}
func GetDashboard(query *m.GetDashboardQuery) error {
dashboard := m.Dashboard{Slug: query.Slug, OrgId: query.OrgId, Id: query.Id, Uid: query.Uid}
has, err := x.Get(&dashboard)
+1 -84
View File
@@ -1,16 +1,12 @@
package sqlstore
import (
"time"
"github.com/grafana/grafana/pkg/bus"
m "github.com/grafana/grafana/pkg/models"
)
func init() {
bus.AddHandler("sql", SetDashboardAcl)
bus.AddHandler("sql", UpdateDashboardAcl)
bus.AddHandler("sql", RemoveDashboardAcl)
bus.AddHandler("sql", GetDashboardAclInfoList)
}
@@ -23,7 +19,7 @@ func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error {
}
for _, item := range cmd.Items {
if item.UserId == 0 && item.TeamId == 0 && !item.Role.IsValid() {
if item.UserId == 0 && item.TeamId == 0 && (item.Role == nil || !item.Role.IsValid()) {
return m.ErrDashboardAclInfoMissing
}
@@ -46,85 +42,6 @@ func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error {
})
}
func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
return inTransaction(func(sess *DBSession) error {
if cmd.UserId == 0 && cmd.TeamId == 0 {
return m.ErrDashboardAclInfoMissing
}
if cmd.DashboardId == 0 {
return m.ErrDashboardPermissionDashboardEmpty
}
if res, err := sess.Query("SELECT 1 from "+dialect.Quote("dashboard_acl")+" WHERE dashboard_id =? and (team_id=? or user_id=?)", cmd.DashboardId, cmd.TeamId, cmd.UserId); err != nil {
return err
} else if len(res) == 1 {
entity := m.DashboardAcl{
Permission: cmd.Permission,
Updated: time.Now(),
}
if _, err := sess.Cols("updated", "permission").Where("dashboard_id =? and (team_id=? or user_id=?)", cmd.DashboardId, cmd.TeamId, cmd.UserId).Update(&entity); err != nil {
return err
}
return nil
}
entity := m.DashboardAcl{
OrgId: cmd.OrgId,
TeamId: cmd.TeamId,
UserId: cmd.UserId,
Created: time.Now(),
Updated: time.Now(),
DashboardId: cmd.DashboardId,
Permission: cmd.Permission,
}
cols := []string{"org_id", "created", "updated", "dashboard_id", "permission"}
if cmd.UserId != 0 {
cols = append(cols, "user_id")
}
if cmd.TeamId != 0 {
cols = append(cols, "team_id")
}
_, err := sess.Cols(cols...).Insert(&entity)
if err != nil {
return err
}
cmd.Result = entity
// Update dashboard HasAcl flag
dashboard := m.Dashboard{
HasAcl: true,
}
if _, err := sess.Cols("has_acl").Where("id=? OR folder_id=?", cmd.DashboardId, cmd.DashboardId).Update(&dashboard); err != nil {
return err
}
return nil
})
}
// RemoveDashboardAcl removes a specified permission from the dashboard acl
func RemoveDashboardAcl(cmd *m.RemoveDashboardAclCommand) error {
return inTransaction(func(sess *DBSession) error {
var rawSQL = "DELETE FROM " + dialect.Quote("dashboard_acl") + " WHERE org_id =? and id=?"
_, err := sess.Exec(rawSQL, cmd.OrgId, cmd.AclId)
if err != nil {
return err
}
return err
})
}
// GetDashboardAclInfoList returns a list of permissions for a dashboard. They can be fetched from three
// different places.
// 1) Permissions for the dashboard
+10 -64
View File
@@ -17,7 +17,7 @@ func TestDashboardAclDataAccess(t *testing.T) {
childDash := insertTestDashboard("2 test dash", 1, savedFolder.Id, false, "prod", "webapp")
Convey("When adding dashboard permission with userId and teamId set to 0", func() {
err := SetDashboardAcl(&m.SetDashboardAclCommand{
err := testHelperUpdateDashboardAcl(savedFolder.Id, m.DashboardAcl{
OrgId: 1,
DashboardId: savedFolder.Id,
Permission: m.PERMISSION_EDIT,
@@ -59,7 +59,7 @@ func TestDashboardAclDataAccess(t *testing.T) {
})
Convey("Given dashboard folder permission", func() {
err := SetDashboardAcl(&m.SetDashboardAclCommand{
err := testHelperUpdateDashboardAcl(savedFolder.Id, m.DashboardAcl{
OrgId: 1,
UserId: currentUser.Id,
DashboardId: savedFolder.Id,
@@ -78,7 +78,7 @@ func TestDashboardAclDataAccess(t *testing.T) {
})
Convey("Given child dashboard permission", func() {
err := SetDashboardAcl(&m.SetDashboardAclCommand{
err := testHelperUpdateDashboardAcl(childDash.Id, m.DashboardAcl{
OrgId: 1,
UserId: currentUser.Id,
DashboardId: childDash.Id,
@@ -100,7 +100,7 @@ func TestDashboardAclDataAccess(t *testing.T) {
})
Convey("Given child dashboard permission in folder with no permissions", func() {
err := SetDashboardAcl(&m.SetDashboardAclCommand{
err := testHelperUpdateDashboardAcl(childDash.Id, m.DashboardAcl{
OrgId: 1,
UserId: currentUser.Id,
DashboardId: childDash.Id,
@@ -125,17 +125,12 @@ func TestDashboardAclDataAccess(t *testing.T) {
})
Convey("Should be able to add dashboard permission", func() {
setDashAclCmd := m.SetDashboardAclCommand{
err := testHelperUpdateDashboardAcl(savedFolder.Id, m.DashboardAcl{
OrgId: 1,
UserId: currentUser.Id,
DashboardId: savedFolder.Id,
Permission: m.PERMISSION_EDIT,
}
err := SetDashboardAcl(&setDashAclCmd)
So(err, ShouldBeNil)
So(setDashAclCmd.Result.Id, ShouldEqual, 3)
})
q1 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1}
err = GetDashboardAclInfoList(q1)
@@ -147,42 +142,9 @@ func TestDashboardAclDataAccess(t *testing.T) {
So(q1.Result[0].UserId, ShouldEqual, currentUser.Id)
So(q1.Result[0].UserLogin, ShouldEqual, currentUser.Login)
So(q1.Result[0].UserEmail, ShouldEqual, currentUser.Email)
So(q1.Result[0].Id, ShouldEqual, setDashAclCmd.Result.Id)
Convey("Should update hasAcl field to true for dashboard folder and its children", func() {
q2 := &m.GetDashboardsQuery{DashboardIds: []int64{savedFolder.Id, childDash.Id}}
err := GetDashboards(q2)
So(err, ShouldBeNil)
So(q2.Result[0].HasAcl, ShouldBeTrue)
So(q2.Result[1].HasAcl, ShouldBeTrue)
})
Convey("Should be able to update an existing permission", func() {
err := SetDashboardAcl(&m.SetDashboardAclCommand{
OrgId: 1,
UserId: 1,
DashboardId: savedFolder.Id,
Permission: m.PERMISSION_ADMIN,
})
So(err, ShouldBeNil)
q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1}
err = GetDashboardAclInfoList(q3)
So(err, ShouldBeNil)
So(len(q3.Result), ShouldEqual, 1)
So(q3.Result[0].DashboardId, ShouldEqual, savedFolder.Id)
So(q3.Result[0].Permission, ShouldEqual, m.PERMISSION_ADMIN)
So(q3.Result[0].UserId, ShouldEqual, 1)
})
Convey("Should be able to delete an existing permission", func() {
err := RemoveDashboardAcl(&m.RemoveDashboardAclCommand{
OrgId: 1,
AclId: setDashAclCmd.Result.Id,
})
err := testHelperUpdateDashboardAcl(savedFolder.Id)
So(err, ShouldBeNil)
q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1}
@@ -198,14 +160,12 @@ func TestDashboardAclDataAccess(t *testing.T) {
So(err, ShouldBeNil)
Convey("Should be able to add a user permission for a team", func() {
setDashAclCmd := m.SetDashboardAclCommand{
err := testHelperUpdateDashboardAcl(savedFolder.Id, m.DashboardAcl{
OrgId: 1,
TeamId: group1.Result.Id,
DashboardId: savedFolder.Id,
Permission: m.PERMISSION_EDIT,
}
err := SetDashboardAcl(&setDashAclCmd)
})
So(err, ShouldBeNil)
q1 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1}
@@ -214,23 +174,10 @@ func TestDashboardAclDataAccess(t *testing.T) {
So(q1.Result[0].DashboardId, ShouldEqual, savedFolder.Id)
So(q1.Result[0].Permission, ShouldEqual, m.PERMISSION_EDIT)
So(q1.Result[0].TeamId, ShouldEqual, group1.Result.Id)
Convey("Should be able to delete an existing permission for a team", func() {
err := RemoveDashboardAcl(&m.RemoveDashboardAclCommand{
OrgId: 1,
AclId: setDashAclCmd.Result.Id,
})
So(err, ShouldBeNil)
q3 := &m.GetDashboardAclInfoListQuery{DashboardId: savedFolder.Id, OrgId: 1}
err = GetDashboardAclInfoList(q3)
So(err, ShouldBeNil)
So(len(q3.Result), ShouldEqual, 0)
})
})
Convey("Should be able to update an existing permission for a team", func() {
err := SetDashboardAcl(&m.SetDashboardAclCommand{
err := testHelperUpdateDashboardAcl(savedFolder.Id, m.DashboardAcl{
OrgId: 1,
TeamId: group1.Result.Id,
DashboardId: savedFolder.Id,
@@ -246,7 +193,6 @@ func TestDashboardAclDataAccess(t *testing.T) {
So(q3.Result[0].Permission, ShouldEqual, m.PERMISSION_ADMIN)
So(q3.Result[0].TeamId, ShouldEqual, group1.Result.Id)
})
})
})
+12 -17
View File
@@ -41,7 +41,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
Convey("and acl is set for dashboard folder", func() {
var otherUser int64 = 999
updateTestDashboardWithAcl(folder.Id, otherUser, m.PERMISSION_EDIT)
testHelperUpdateDashboardAcl(folder.Id, m.DashboardAcl{DashboardId: folder.Id, OrgId: 1, UserId: otherUser, Permission: m.PERMISSION_EDIT})
Convey("should not return folder", func() {
query := &search.FindPersistedDashboardsQuery{
@@ -55,7 +55,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
})
Convey("when the user is given permission", func() {
updateTestDashboardWithAcl(folder.Id, currentUser.Id, m.PERMISSION_EDIT)
testHelperUpdateDashboardAcl(folder.Id, m.DashboardAcl{DashboardId: folder.Id, OrgId: 1, UserId: currentUser.Id, Permission: m.PERMISSION_EDIT})
Convey("should be able to access folder", func() {
query := &search.FindPersistedDashboardsQuery{
@@ -93,9 +93,8 @@ func TestDashboardFolderDataAccess(t *testing.T) {
Convey("and acl is set for dashboard child and folder has all permissions removed", func() {
var otherUser int64 = 999
aclId := updateTestDashboardWithAcl(folder.Id, otherUser, m.PERMISSION_EDIT)
removeAcl(aclId)
updateTestDashboardWithAcl(childDash.Id, otherUser, m.PERMISSION_EDIT)
testHelperUpdateDashboardAcl(folder.Id)
testHelperUpdateDashboardAcl(childDash.Id, m.DashboardAcl{DashboardId: folder.Id, OrgId: 1, UserId: otherUser, Permission: m.PERMISSION_EDIT})
Convey("should not return folder or child", func() {
query := &search.FindPersistedDashboardsQuery{SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}}
@@ -106,7 +105,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
})
Convey("when the user is given permission to child", func() {
updateTestDashboardWithAcl(childDash.Id, currentUser.Id, m.PERMISSION_EDIT)
testHelperUpdateDashboardAcl(childDash.Id, m.DashboardAcl{DashboardId: childDash.Id, OrgId: 1, UserId: currentUser.Id, Permission: m.PERMISSION_EDIT})
Convey("should be able to search for child dashboard but not folder", func() {
query := &search.FindPersistedDashboardsQuery{SignedInUser: &m.SignedInUser{UserId: currentUser.Id, OrgId: 1, OrgRole: m.ROLE_VIEWER}, OrgId: 1, DashboardIds: []int64{folder.Id, childDash.Id, dashInRoot.Id}}
@@ -165,11 +164,10 @@ func TestDashboardFolderDataAccess(t *testing.T) {
Convey("and acl is set for one dashboard folder", func() {
var otherUser int64 = 999
updateTestDashboardWithAcl(folder1.Id, otherUser, m.PERMISSION_EDIT)
testHelperUpdateDashboardAcl(folder1.Id, m.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: otherUser, Permission: m.PERMISSION_EDIT})
Convey("and a dashboard is moved from folder without acl to the folder with an acl", func() {
movedDash := moveDashboard(1, childDash2.Data, folder1.Id)
So(movedDash.HasAcl, ShouldBeTrue)
moveDashboard(1, childDash2.Data, folder1.Id)
Convey("should not return folder with acl or its children", func() {
query := &search.FindPersistedDashboardsQuery{
@@ -184,9 +182,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
})
})
Convey("and a dashboard is moved from folder with acl to the folder without an acl", func() {
movedDash := moveDashboard(1, childDash1.Data, folder2.Id)
So(movedDash.HasAcl, ShouldBeFalse)
moveDashboard(1, childDash1.Data, folder2.Id)
Convey("should return folder without acl and its children", func() {
query := &search.FindPersistedDashboardsQuery{
@@ -205,9 +201,8 @@ func TestDashboardFolderDataAccess(t *testing.T) {
})
Convey("and a dashboard with an acl is moved to the folder without an acl", func() {
updateTestDashboardWithAcl(childDash1.Id, otherUser, m.PERMISSION_EDIT)
movedDash := moveDashboard(1, childDash1.Data, folder2.Id)
So(movedDash.HasAcl, ShouldBeTrue)
testHelperUpdateDashboardAcl(childDash1.Id, m.DashboardAcl{DashboardId: childDash1.Id, OrgId: 1, UserId: otherUser, Permission: m.PERMISSION_EDIT})
moveDashboard(1, childDash1.Data, folder2.Id)
Convey("should return folder without acl but not the dashboard with acl", func() {
query := &search.FindPersistedDashboardsQuery{
@@ -308,7 +303,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
})
Convey("Should have write access to one dashboard folder if default role changed to view for one folder", func() {
updateTestDashboardWithAcl(folder1.Id, editorUser.Id, m.PERMISSION_VIEW)
testHelperUpdateDashboardAcl(folder1.Id, m.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: editorUser.Id, Permission: m.PERMISSION_VIEW})
err := SearchDashboards(&query)
So(err, ShouldBeNil)
@@ -352,7 +347,7 @@ func TestDashboardFolderDataAccess(t *testing.T) {
})
Convey("Should be able to get one dashboard folder if default role changed to edit for one folder", func() {
updateTestDashboardWithAcl(folder1.Id, viewerUser.Id, m.PERMISSION_EDIT)
testHelperUpdateDashboardAcl(folder1.Id, m.DashboardAcl{DashboardId: folder1.Id, OrgId: 1, UserId: viewerUser.Id, Permission: m.PERMISSION_EDIT})
err := SearchDashboards(&query)
So(err, ShouldBeNil)
-19
View File
@@ -663,25 +663,6 @@ func createUser(name string, role string, isAdmin bool) m.User {
return currentUserCmd.Result
}
func updateTestDashboardWithAcl(dashId int64, userId int64, permissions m.PermissionType) int64 {
cmd := &m.SetDashboardAclCommand{
OrgId: 1,
UserId: userId,
DashboardId: dashId,
Permission: permissions,
}
err := SetDashboardAcl(cmd)
So(err, ShouldBeNil)
return cmd.Result.Id
}
func removeAcl(aclId int64) {
err := RemoveDashboardAcl(&m.RemoveDashboardAclCommand{AclId: aclId, OrgId: 1})
So(err, ShouldBeNil)
}
func moveDashboard(orgId int64, dashboard *simplejson.Json, newFolderId int64) *m.Dashboard {
cmd := m.SaveDashboardCommand{
OrgId: orgId,
+1 -1
View File
@@ -99,7 +99,7 @@ func TestTeamCommandsAndQueries(t *testing.T) {
So(err, ShouldBeNil)
err = AddTeamMember(&m.AddTeamMemberCommand{OrgId: testOrgId, TeamId: groupId, UserId: userIds[2]})
So(err, ShouldBeNil)
err = SetDashboardAcl(&m.SetDashboardAclCommand{DashboardId: 1, OrgId: testOrgId, Permission: m.PERMISSION_EDIT, TeamId: groupId})
err = testHelperUpdateDashboardAcl(1, m.DashboardAcl{DashboardId: 1, OrgId: testOrgId, Permission: m.PERMISSION_EDIT, TeamId: groupId})
err = DeleteTeam(&m.DeleteTeamCommand{OrgId: testOrgId, Id: groupId})
So(err, ShouldBeNil)
+1 -1
View File
@@ -99,7 +99,7 @@ func TestUserDataAccess(t *testing.T) {
err = AddOrgUser(&m.AddOrgUserCommand{LoginOrEmail: users[0].Login, Role: m.ROLE_VIEWER, OrgId: users[0].OrgId})
So(err, ShouldBeNil)
err = SetDashboardAcl(&m.SetDashboardAclCommand{DashboardId: 1, OrgId: users[0].OrgId, UserId: users[0].Id, Permission: m.PERMISSION_EDIT})
testHelperUpdateDashboardAcl(1, m.DashboardAcl{DashboardId: 1, OrgId: users[0].OrgId, UserId: users[0].Id, Permission: m.PERMISSION_EDIT})
So(err, ShouldBeNil)
err = SavePreferences(&m.SavePreferencesCommand{UserId: users[0].Id, OrgId: users[0].OrgId, HomeDashboardId: 1, Theme: "dark"})