Commit 3fe031d2 by Torkel Ödegaard

refactoring: Dashboard guardian

parent d9dca72e
...@@ -46,13 +46,11 @@ func GetDashboard(c *middleware.Context) Response { ...@@ -46,13 +46,11 @@ func GetDashboard(c *middleware.Context) Response {
} }
dash := query.Result dash := query.Result
guardian := guardian.NewDashboardGuardian(dash, c.SignedInUser)
canView, canEdit, canSave, err := getPermissions(dash, c.OrgRole, c.IsGrafanaAdmin, c.UserId) if canView, err := guardian.CanView(); err != nil {
if err != nil {
return ApiError(500, "Error while checking dashboard permissions", err) return ApiError(500, "Error while checking dashboard permissions", err)
} } else if !canView {
if !canView {
return ApiError(403, "Access denied to this dashboard", nil) return ApiError(403, "Access denied to this dashboard", nil)
} }
...@@ -162,12 +160,11 @@ func DeleteDashboard(c *middleware.Context) Response { ...@@ -162,12 +160,11 @@ func DeleteDashboard(c *middleware.Context) Response {
return ApiError(404, "Dashboard not found", err) return ApiError(404, "Dashboard not found", err)
} }
_, _, canSave, err := getPermissions(query.Result, c.OrgRole, c.IsGrafanaAdmin, c.UserId) guardian := guardian.NewDashboardGuardian(query.Result, c.SignedInUser)
if err != nil {
return ApiError(500, "Error while checking dashboard permissions", err)
}
if !canSave { if canSave, err := guardian.CanSave(); err != nil {
return ApiError(500, "Error while checking dashboard permissions", err)
} else if !canSave {
return ApiError(403, "Does not have permission to delete this dashboard", nil) return ApiError(403, "Does not have permission to delete this dashboard", nil)
} }
...@@ -301,6 +298,8 @@ func GetHomeDashboard(c *middleware.Context) Response { ...@@ -301,6 +298,8 @@ func GetHomeDashboard(c *middleware.Context) Response {
dash := dtos.DashboardFullWithMeta{} dash := dtos.DashboardFullWithMeta{}
dash.Meta.IsHome = true dash.Meta.IsHome = true
dash.Meta.CanEdit = canEditDashboard(c.OrgRole) dash.Meta.CanEdit = canEditDashboard(c.OrgRole)
dash.Meta.FolderTitle = "Root"
jsonParser := json.NewDecoder(file) jsonParser := json.NewDecoder(file)
if err := jsonParser.Decode(&dash.Dashboard); err != nil { if err := jsonParser.Decode(&dash.Dashboard); err != nil {
return ApiError(500, "Failed to load home dashboard", err) return ApiError(500, "Failed to load home dashboard", err)
......
...@@ -54,8 +54,8 @@ type DashboardAclInfoDTO struct { ...@@ -54,8 +54,8 @@ type DashboardAclInfoDTO struct {
UserEmail string `json:"userEmail"` UserEmail string `json:"userEmail"`
UserGroupId int64 `json:"userGroupId"` UserGroupId int64 `json:"userGroupId"`
UserGroup string `json:"userGroup"` UserGroup string `json:"userGroup"`
PermissionType PermissionType `json:"permissionType"` Permissions PermissionType `json:"permissions"`
Permissions string `json:"permissions"` PermissionName string `json:"permissionName"`
} }
// //
......
...@@ -162,6 +162,14 @@ type SignedInUser struct { ...@@ -162,6 +162,14 @@ type SignedInUser struct {
HelpFlags1 HelpFlags1 HelpFlags1 HelpFlags1
} }
func (user *SignedInUser) HasRole(role RoleType) bool {
if user.IsGrafanaAdmin {
return true
}
return user.OrgRole.Includes(role)
}
type UserProfileDTO struct { type UserProfileDTO struct {
Email string `json:"email"` Email string `json:"email"`
Name string `json:"name"` Name string `json:"name"`
......
...@@ -17,7 +17,6 @@ func FilterRestrictedDashboards(dashList []int64, orgId int64, userId int64) ([] ...@@ -17,7 +17,6 @@ func FilterRestrictedDashboards(dashList []int64, orgId int64, userId int64) ([]
} }
filteredList, err := getAllowedDashboards(dashList, orgId, userId) filteredList, err := getAllowedDashboards(dashList, orgId, userId)
return filteredList, err return filteredList, err
} }
...@@ -101,12 +100,12 @@ func checkPermission(minimumPermission m.PermissionType, permissions []*m.Dashbo ...@@ -101,12 +100,12 @@ func checkPermission(minimumPermission m.PermissionType, permissions []*m.Dashbo
} }
for _, p := range permissions { for _, p := range permissions {
if p.UserId == userId && p.PermissionType >= minimumPermission { if p.UserId == userId && p.Permissions >= minimumPermission {
return true, nil return true, nil
} }
for _, ug := range userGroups { for _, ug := range userGroups {
if ug.Id == p.UserGroupId && p.PermissionType >= minimumPermission { if ug.Id == p.UserGroupId && p.Permissions >= minimumPermission {
return true, nil return true, nil
} }
} }
......
package guardian
import (
"github.com/grafana/grafana/pkg/bus"
m "github.com/grafana/grafana/pkg/models"
)
type DashboardGuardian struct {
user *m.SignedInUser
dashboard *m.Dashboard
acl []*m.DashboardAclInfoDTO
groups []*m.UserGroup
}
func NewDashboardGuardian(dash *m.Dashboard, user *m.SignedInUser) *DashboardGuardian {
return &DashboardGuardian{
user: user,
dashboard: dash,
}
}
func (g *DashboardGuardian) CanSave() (bool, error) {
if !g.dashboard.HasAcl {
return g.user.HasRole(m.ROLE_EDITOR), nil
}
return g.HasPermission(m.PERMISSION_EDIT)
}
func (g *DashboardGuardian) CanEdit() (bool, error) {
if !g.dashboard.HasAcl {
return g.user.HasRole(m.ROLE_READ_ONLY_EDITOR), nil
}
return g.HasPermission(m.PERMISSION_READ_ONLY_EDIT)
}
func (g *DashboardGuardian) CanView() (bool, error) {
if !g.dashboard.HasAcl {
return g.user.HasRole(m.ROLE_VIEWER), nil
}
return g.HasPermission(m.PERMISSION_VIEW)
}
func (g *DashboardGuardian) HasPermission(permission m.PermissionType) (bool, error) {
userGroups, err := g.getUserGroups()
if err != nil {
return false, err
}
acl, err := g.getAcl()
if err != nil {
return false, err
}
for _, p := range acl {
if p.UserId == g.user.UserId && p.Permissions >= permission {
return true, nil
}
for _, ug := range userGroups {
if ug.Id == p.UserGroupId && p.Permissions >= permission {
return true, nil
}
}
}
return false, nil
}
func (g *DashboardGuardian) getAcl() ([]*m.DashboardAclInfoDTO, error) {
if g.acl != nil {
return g.acl, nil
}
query := m.GetDashboardPermissionsQuery{DashboardId: g.dashboard.Id}
if err := bus.Dispatch(&query); err != nil {
return nil, err
}
g.acl = query.Result
return g.acl, nil
}
func (g *DashboardGuardian) getUserGroups() ([]*m.UserGroup, error) {
if g.groups == nil {
return g.groups, nil
}
query := m.GetUserGroupsByUserQuery{UserId: g.user.UserId}
err := bus.Dispatch(&query)
g.groups = query.Result
return query.Result, err
}
...@@ -3,8 +3,6 @@ package sqlstore ...@@ -3,8 +3,6 @@ package sqlstore
import ( import (
"time" "time"
"fmt"
"github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/bus"
m "github.com/grafana/grafana/pkg/models" m "github.com/grafana/grafana/pkg/models"
) )
...@@ -94,7 +92,7 @@ func GetDashboardPermissions(query *m.GetDashboardPermissionsQuery) error { ...@@ -94,7 +92,7 @@ func GetDashboardPermissions(query *m.GetDashboardPermissionsQuery) error {
da.dashboard_id, da.dashboard_id,
da.user_id, da.user_id,
da.user_group_id, da.user_group_id,
da.permissions as permission_type, da.permissions,
da.created, da.created,
da.updated, da.updated,
u.login AS user_login, u.login AS user_login,
...@@ -110,7 +108,7 @@ func GetDashboardPermissions(query *m.GetDashboardPermissionsQuery) error { ...@@ -110,7 +108,7 @@ func GetDashboardPermissions(query *m.GetDashboardPermissionsQuery) error {
err := x.SQL(rawSQL, query.DashboardId).Find(&query.Result) err := x.SQL(rawSQL, query.DashboardId).Find(&query.Result)
for _, p := range query.Result { for _, p := range query.Result {
p.Permissions = fmt.Sprint(p.PermissionType) p.PermissionName = p.Permissions.String()
} }
return err return err
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment