mirror of https://github.com/grafana/grafana
commit
d7688241c6
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,256 @@ |
|||||||
|
package guardian |
||||||
|
|
||||||
|
import ( |
||||||
|
"bytes" |
||||||
|
"fmt" |
||||||
|
"strings" |
||||||
|
"testing" |
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/bus" |
||||||
|
m "github.com/grafana/grafana/pkg/models" |
||||||
|
. "github.com/smartystreets/goconvey/convey" |
||||||
|
) |
||||||
|
|
||||||
|
type scenarioContext struct { |
||||||
|
t *testing.T |
||||||
|
orgRoleScenario string |
||||||
|
permissionScenario string |
||||||
|
g DashboardGuardian |
||||||
|
givenUser *m.SignedInUser |
||||||
|
givenDashboardID int64 |
||||||
|
givenPermissions []*m.DashboardAclInfoDTO |
||||||
|
givenTeams []*m.Team |
||||||
|
updatePermissions []*m.DashboardAcl |
||||||
|
expectedFlags permissionFlags |
||||||
|
callerFile string |
||||||
|
callerLine int |
||||||
|
} |
||||||
|
|
||||||
|
type scenarioFunc func(c *scenarioContext) |
||||||
|
|
||||||
|
func orgRoleScenario(desc string, t *testing.T, role m.RoleType, fn scenarioFunc) { |
||||||
|
user := &m.SignedInUser{ |
||||||
|
UserId: userID, |
||||||
|
OrgId: orgID, |
||||||
|
OrgRole: role, |
||||||
|
} |
||||||
|
guard := New(dashboardID, orgID, user) |
||||||
|
sc := &scenarioContext{ |
||||||
|
t: t, |
||||||
|
orgRoleScenario: desc, |
||||||
|
givenUser: user, |
||||||
|
givenDashboardID: dashboardID, |
||||||
|
g: guard, |
||||||
|
} |
||||||
|
|
||||||
|
Convey(desc, func() { |
||||||
|
fn(sc) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
func permissionScenario(desc string, dashboardID int64, sc *scenarioContext, permissions []*m.DashboardAclInfoDTO, fn scenarioFunc) { |
||||||
|
bus.ClearBusHandlers() |
||||||
|
|
||||||
|
bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error { |
||||||
|
if query.OrgId != sc.givenUser.OrgId { |
||||||
|
sc.reportFailure("Invalid organization id for GetDashboardAclInfoListQuery", sc.givenUser.OrgId, query.OrgId) |
||||||
|
} |
||||||
|
if query.DashboardId != sc.givenDashboardID { |
||||||
|
sc.reportFailure("Invalid dashboard id for GetDashboardAclInfoListQuery", sc.givenDashboardID, query.DashboardId) |
||||||
|
} |
||||||
|
|
||||||
|
query.Result = permissions |
||||||
|
return nil |
||||||
|
}) |
||||||
|
|
||||||
|
teams := []*m.Team{} |
||||||
|
|
||||||
|
for _, p := range permissions { |
||||||
|
if p.TeamId > 0 { |
||||||
|
teams = append(teams, &m.Team{Id: p.TeamId}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error { |
||||||
|
if query.OrgId != sc.givenUser.OrgId { |
||||||
|
sc.reportFailure("Invalid organization id for GetTeamsByUserQuery", sc.givenUser.OrgId, query.OrgId) |
||||||
|
} |
||||||
|
if query.UserId != sc.givenUser.UserId { |
||||||
|
sc.reportFailure("Invalid user id for GetTeamsByUserQuery", sc.givenUser.UserId, query.UserId) |
||||||
|
} |
||||||
|
|
||||||
|
query.Result = teams |
||||||
|
return nil |
||||||
|
}) |
||||||
|
|
||||||
|
sc.permissionScenario = desc |
||||||
|
sc.g = New(dashboardID, sc.givenUser.OrgId, sc.givenUser) |
||||||
|
sc.givenDashboardID = dashboardID |
||||||
|
sc.givenPermissions = permissions |
||||||
|
sc.givenTeams = teams |
||||||
|
|
||||||
|
Convey(desc, func() { |
||||||
|
fn(sc) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
type permissionType uint8 |
||||||
|
|
||||||
|
const ( |
||||||
|
USER permissionType = 1 << iota |
||||||
|
TEAM |
||||||
|
EDITOR |
||||||
|
VIEWER |
||||||
|
) |
||||||
|
|
||||||
|
func (p permissionType) String() string { |
||||||
|
names := map[uint8]string{ |
||||||
|
uint8(USER): "user", |
||||||
|
uint8(TEAM): "team", |
||||||
|
uint8(EDITOR): "editor role", |
||||||
|
uint8(VIEWER): "viewer role", |
||||||
|
} |
||||||
|
return names[uint8(p)] |
||||||
|
} |
||||||
|
|
||||||
|
type permissionFlags uint8 |
||||||
|
|
||||||
|
const ( |
||||||
|
NO_ACCESS permissionFlags = 1 << iota |
||||||
|
CAN_ADMIN |
||||||
|
CAN_EDIT |
||||||
|
CAN_SAVE |
||||||
|
CAN_VIEW |
||||||
|
FULL_ACCESS = CAN_ADMIN | CAN_EDIT | CAN_SAVE | CAN_VIEW |
||||||
|
EDITOR_ACCESS = CAN_EDIT | CAN_SAVE | CAN_VIEW |
||||||
|
VIEWER_ACCESS = CAN_VIEW |
||||||
|
) |
||||||
|
|
||||||
|
func (flag permissionFlags) canAdmin() bool { |
||||||
|
return flag&CAN_ADMIN != 0 |
||||||
|
} |
||||||
|
|
||||||
|
func (flag permissionFlags) canEdit() bool { |
||||||
|
return flag&CAN_EDIT != 0 |
||||||
|
} |
||||||
|
|
||||||
|
func (flag permissionFlags) canSave() bool { |
||||||
|
return flag&CAN_SAVE != 0 |
||||||
|
} |
||||||
|
|
||||||
|
func (flag permissionFlags) canView() bool { |
||||||
|
return flag&CAN_VIEW != 0 |
||||||
|
} |
||||||
|
|
||||||
|
func (flag permissionFlags) noAccess() bool { |
||||||
|
return flag&(CAN_ADMIN|CAN_EDIT|CAN_SAVE|CAN_VIEW) == 0 |
||||||
|
} |
||||||
|
|
||||||
|
func (f permissionFlags) String() string { |
||||||
|
r := []string{} |
||||||
|
|
||||||
|
if f.canAdmin() { |
||||||
|
r = append(r, "admin") |
||||||
|
} |
||||||
|
|
||||||
|
if f.canEdit() { |
||||||
|
r = append(r, "edit") |
||||||
|
} |
||||||
|
|
||||||
|
if f.canSave() { |
||||||
|
r = append(r, "save") |
||||||
|
} |
||||||
|
|
||||||
|
if f.canView() { |
||||||
|
r = append(r, "view") |
||||||
|
} |
||||||
|
|
||||||
|
if f.noAccess() { |
||||||
|
r = append(r, "<no access>") |
||||||
|
} |
||||||
|
|
||||||
|
return strings.Join(r[:], ", ") |
||||||
|
} |
||||||
|
|
||||||
|
func (sc *scenarioContext) reportSuccess() { |
||||||
|
So(true, ShouldBeTrue) |
||||||
|
} |
||||||
|
|
||||||
|
func (sc *scenarioContext) reportFailure(desc string, expected interface{}, actual interface{}) { |
||||||
|
var buf bytes.Buffer |
||||||
|
buf.WriteString("\n") |
||||||
|
buf.WriteString(sc.orgRoleScenario) |
||||||
|
buf.WriteString(" ") |
||||||
|
buf.WriteString(sc.permissionScenario) |
||||||
|
buf.WriteString("\n ") |
||||||
|
buf.WriteString(desc) |
||||||
|
buf.WriteString("\n") |
||||||
|
buf.WriteString(fmt.Sprintf("Source test: %s:%d\n", sc.callerFile, sc.callerLine)) |
||||||
|
buf.WriteString(fmt.Sprintf("Expected: %v\n", expected)) |
||||||
|
buf.WriteString(fmt.Sprintf("Actual: %v\n", actual)) |
||||||
|
buf.WriteString("Context:") |
||||||
|
buf.WriteString(fmt.Sprintf("\n Given user: orgRole=%s, id=%d, orgId=%d", sc.givenUser.OrgRole, sc.givenUser.UserId, sc.givenUser.OrgId)) |
||||||
|
buf.WriteString(fmt.Sprintf("\n Given dashboard id: %d", sc.givenDashboardID)) |
||||||
|
|
||||||
|
for i, p := range sc.givenPermissions { |
||||||
|
r := "<nil>" |
||||||
|
if p.Role != nil { |
||||||
|
r = string(*p.Role) |
||||||
|
} |
||||||
|
buf.WriteString(fmt.Sprintf("\n Given permission (%d): dashboardId=%d, userId=%d, teamId=%d, role=%v, permission=%s", i, p.DashboardId, p.UserId, p.TeamId, r, p.Permission.String())) |
||||||
|
} |
||||||
|
|
||||||
|
for i, t := range sc.givenTeams { |
||||||
|
buf.WriteString(fmt.Sprintf("\n Given team (%d): id=%d", i, t.Id)) |
||||||
|
} |
||||||
|
|
||||||
|
for i, p := range sc.updatePermissions { |
||||||
|
r := "<nil>" |
||||||
|
if p.Role != nil { |
||||||
|
r = string(*p.Role) |
||||||
|
} |
||||||
|
buf.WriteString(fmt.Sprintf("\n Update permission (%d): dashboardId=%d, userId=%d, teamId=%d, role=%v, permission=%s", i, p.DashboardId, p.UserId, p.TeamId, r, p.Permission.String())) |
||||||
|
} |
||||||
|
|
||||||
|
sc.t.Fatalf(buf.String()) |
||||||
|
} |
||||||
|
|
||||||
|
func newCustomUserPermission(dashboardID int64, userID int64, permission m.PermissionType) *m.DashboardAcl { |
||||||
|
return &m.DashboardAcl{OrgId: orgID, DashboardId: dashboardID, UserId: userID, Permission: permission} |
||||||
|
} |
||||||
|
|
||||||
|
func newDefaultUserPermission(dashboardID int64, permission m.PermissionType) *m.DashboardAcl { |
||||||
|
return newCustomUserPermission(dashboardID, userID, permission) |
||||||
|
} |
||||||
|
|
||||||
|
func newCustomTeamPermission(dashboardID int64, teamID int64, permission m.PermissionType) *m.DashboardAcl { |
||||||
|
return &m.DashboardAcl{OrgId: orgID, DashboardId: dashboardID, TeamId: teamID, Permission: permission} |
||||||
|
} |
||||||
|
|
||||||
|
func newDefaultTeamPermission(dashboardID int64, permission m.PermissionType) *m.DashboardAcl { |
||||||
|
return newCustomTeamPermission(dashboardID, teamID, permission) |
||||||
|
} |
||||||
|
|
||||||
|
func newAdminRolePermission(dashboardID int64, permission m.PermissionType) *m.DashboardAcl { |
||||||
|
return &m.DashboardAcl{OrgId: orgID, DashboardId: dashboardID, Role: &adminRole, Permission: permission} |
||||||
|
} |
||||||
|
|
||||||
|
func newEditorRolePermission(dashboardID int64, permission m.PermissionType) *m.DashboardAcl { |
||||||
|
return &m.DashboardAcl{OrgId: orgID, DashboardId: dashboardID, Role: &editorRole, Permission: permission} |
||||||
|
} |
||||||
|
|
||||||
|
func newViewerRolePermission(dashboardID int64, permission m.PermissionType) *m.DashboardAcl { |
||||||
|
return &m.DashboardAcl{OrgId: orgID, DashboardId: dashboardID, Role: &viewerRole, Permission: permission} |
||||||
|
} |
||||||
|
|
||||||
|
func toDto(acl *m.DashboardAcl) *m.DashboardAclInfoDTO { |
||||||
|
return &m.DashboardAclInfoDTO{ |
||||||
|
OrgId: acl.OrgId, |
||||||
|
DashboardId: acl.DashboardId, |
||||||
|
UserId: acl.UserId, |
||||||
|
TeamId: acl.TeamId, |
||||||
|
Role: acl.Role, |
||||||
|
Permission: acl.Permission, |
||||||
|
PermissionName: acl.Permission.String(), |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue