mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
dashboard acl work
This commit is contained in:
parent
aab6c98e45
commit
2257c1f874
@ -250,7 +250,7 @@ func (hs *HttpServer) registerRoutes() {
|
|||||||
|
|
||||||
r.Group("/acl", func() {
|
r.Group("/acl", func() {
|
||||||
r.Get("/", wrap(GetDashboardAclList))
|
r.Get("/", wrap(GetDashboardAclList))
|
||||||
r.Post("/", bind(m.SetDashboardAclCommand{}), wrap(PostDashboardAcl))
|
r.Post("/", bind(dtos.UpdateDashboardAclCommand{}), wrap(UpdateDashboardAcl))
|
||||||
r.Delete("/:aclId", wrap(DeleteDashboardAcl))
|
r.Delete("/:aclId", wrap(DeleteDashboardAcl))
|
||||||
})
|
})
|
||||||
}, reqSignedIn)
|
}, reqSignedIn)
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/api/dtos"
|
||||||
"github.com/grafana/grafana/pkg/bus"
|
"github.com/grafana/grafana/pkg/bus"
|
||||||
"github.com/grafana/grafana/pkg/metrics"
|
"github.com/grafana/grafana/pkg/metrics"
|
||||||
"github.com/grafana/grafana/pkg/middleware"
|
"github.com/grafana/grafana/pkg/middleware"
|
||||||
m "github.com/grafana/grafana/pkg/models"
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
"github.com/grafana/grafana/pkg/services/guardian"
|
"github.com/grafana/grafana/pkg/services/guardian"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetDashboardAclList(c *middleware.Context) Response {
|
func GetDashboardAclList(c *middleware.Context) Response {
|
||||||
@ -27,7 +29,7 @@ func GetDashboardAclList(c *middleware.Context) Response {
|
|||||||
return Json(200, list)
|
return Json(200, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PostDashboardAcl(c *middleware.Context, cmd m.SetDashboardAclCommand) Response {
|
func UpdateDashboardAcl(c *middleware.Context, apiCmd dtos.UpdateDashboardAclCommand) Response {
|
||||||
dashId := c.ParamsInt64(":dashboardId")
|
dashId := c.ParamsInt64(":dashboardId")
|
||||||
|
|
||||||
guardian := guardian.NewDashboardGuardian(dashId, c.OrgId, c.SignedInUser)
|
guardian := guardian.NewDashboardGuardian(dashId, c.OrgId, c.SignedInUser)
|
||||||
@ -35,9 +37,22 @@ func PostDashboardAcl(c *middleware.Context, cmd m.SetDashboardAclCommand) Respo
|
|||||||
return dashboardGuardianResponse(err)
|
return dashboardGuardianResponse(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.OrgId = c.OrgId
|
cmd := m.UpdateDashboardAclCommand{}
|
||||||
cmd.DashboardId = dashId
|
cmd.DashboardId = dashId
|
||||||
|
|
||||||
|
for _, item := range apiCmd.Items {
|
||||||
|
cmd.Items = append(cmd.Items, &m.DashboardAcl{
|
||||||
|
OrgId: c.OrgId,
|
||||||
|
DashboardId: dashId,
|
||||||
|
UserId: item.UserId,
|
||||||
|
UserGroupId: item.UserGroupId,
|
||||||
|
Role: item.Role,
|
||||||
|
Permission: item.Permission,
|
||||||
|
Created: time.Now(),
|
||||||
|
Updated: time.Now(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if err := bus.Dispatch(&cmd); err != nil {
|
if err := bus.Dispatch(&cmd); err != nil {
|
||||||
if err == m.ErrDashboardAclInfoMissing || err == m.ErrDashboardPermissionDashboardEmpty {
|
if err == m.ErrDashboardAclInfoMissing || err == m.ErrDashboardPermissionDashboardEmpty {
|
||||||
return ApiError(409, err.Error(), err)
|
return ApiError(409, err.Error(), err)
|
||||||
@ -45,12 +60,8 @@ func PostDashboardAcl(c *middleware.Context, cmd m.SetDashboardAclCommand) Respo
|
|||||||
return ApiError(500, "Failed to create permission", err)
|
return ApiError(500, "Failed to create permission", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics.M_Api_Dashboard_Acl_Create.Inc(1)
|
metrics.M_Api_Dashboard_Acl_Update.Inc(1)
|
||||||
|
return ApiSuccess("Dashboard acl updated")
|
||||||
return Json(200, &util.DynMap{
|
|
||||||
"permissionId": cmd.Result.Id,
|
|
||||||
"message": "Permission created",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteDashboardAcl(c *middleware.Context) Response {
|
func DeleteDashboardAcl(c *middleware.Context) Response {
|
||||||
|
16
pkg/api/dtos/acl.go
Normal file
16
pkg/api/dtos/acl.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package dtos
|
||||||
|
|
||||||
|
import (
|
||||||
|
m "github.com/grafana/grafana/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateDashboardAclCommand struct {
|
||||||
|
Items []DashboardAclUpdateItem `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DashboardAclUpdateItem struct {
|
||||||
|
UserId int64 `json:"userId"`
|
||||||
|
UserGroupId int64 `json:"userGroupId"`
|
||||||
|
Role m.RoleType `json:"role"`
|
||||||
|
Permission m.PermissionType `json:"permission"`
|
||||||
|
}
|
@ -36,7 +36,7 @@ var (
|
|||||||
M_Api_Dashboard_Snapshot_External Counter
|
M_Api_Dashboard_Snapshot_External Counter
|
||||||
M_Api_Dashboard_Snapshot_Get Counter
|
M_Api_Dashboard_Snapshot_Get Counter
|
||||||
M_Api_UserGroup_Create Counter
|
M_Api_UserGroup_Create Counter
|
||||||
M_Api_Dashboard_Acl_Create Counter
|
M_Api_Dashboard_Acl_Update Counter
|
||||||
M_Models_Dashboard_Insert Counter
|
M_Models_Dashboard_Insert Counter
|
||||||
M_Alerting_Result_State_Alerting Counter
|
M_Alerting_Result_State_Alerting Counter
|
||||||
M_Alerting_Result_State_Ok Counter
|
M_Alerting_Result_State_Ok Counter
|
||||||
@ -95,7 +95,7 @@ func initMetricVars(settings *MetricSettings) {
|
|||||||
M_Api_User_SignUpInvite = RegCounter("api.user.signup_invite")
|
M_Api_User_SignUpInvite = RegCounter("api.user.signup_invite")
|
||||||
|
|
||||||
M_Api_UserGroup_Create = RegCounter("api.usergroup.create")
|
M_Api_UserGroup_Create = RegCounter("api.usergroup.create")
|
||||||
M_Api_Dashboard_Acl_Create = RegCounter("api.dashboard.acl.create")
|
M_Api_Dashboard_Acl_Update = RegCounter("api.dashboard.acl.update")
|
||||||
|
|
||||||
M_Api_Dashboard_Save = RegTimer("api.dashboard.save")
|
M_Api_Dashboard_Save = RegTimer("api.dashboard.save")
|
||||||
M_Api_Dashboard_Get = RegTimer("api.dashboard.get")
|
M_Api_Dashboard_Get = RegTimer("api.dashboard.get")
|
||||||
|
@ -36,6 +36,7 @@ type DashboardAcl struct {
|
|||||||
|
|
||||||
UserId int64
|
UserId int64
|
||||||
UserGroupId int64
|
UserGroupId int64
|
||||||
|
Role RoleType
|
||||||
Permission PermissionType
|
Permission PermissionType
|
||||||
|
|
||||||
Created time.Time
|
Created time.Time
|
||||||
@ -64,14 +65,19 @@ type DashboardAclInfoDTO struct {
|
|||||||
// COMMANDS
|
// COMMANDS
|
||||||
//
|
//
|
||||||
|
|
||||||
type SetDashboardAclCommand struct {
|
type UpdateDashboardAclCommand struct {
|
||||||
DashboardId int64 `json:"-"`
|
DashboardId int64
|
||||||
OrgId int64 `json:"-"`
|
Items []*DashboardAcl
|
||||||
UserId int64 `json:"userId"`
|
}
|
||||||
UserGroupId int64 `json:"userGroupId"`
|
|
||||||
Permission PermissionType `json:"permission" binding:"Required"`
|
|
||||||
|
|
||||||
Result DashboardAcl `json:"-"`
|
type SetDashboardAclCommand struct {
|
||||||
|
DashboardId int64
|
||||||
|
OrgId int64
|
||||||
|
UserId int64
|
||||||
|
UserGroupId int64
|
||||||
|
Permission PermissionType
|
||||||
|
|
||||||
|
Result DashboardAcl
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveDashboardAclCommand struct {
|
type RemoveDashboardAclCommand struct {
|
||||||
|
@ -9,11 +9,44 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
bus.AddHandler("sql", SetDashboardAcl)
|
bus.AddHandler("sql", SetDashboardAcl)
|
||||||
|
bus.AddHandler("sql", UpdateDashboardAcl)
|
||||||
bus.AddHandler("sql", RemoveDashboardAcl)
|
bus.AddHandler("sql", RemoveDashboardAcl)
|
||||||
bus.AddHandler("sql", GetDashboardAclInfoList)
|
bus.AddHandler("sql", GetDashboardAclInfoList)
|
||||||
bus.AddHandler("sql", GetInheritedDashboardAcl)
|
bus.AddHandler("sql", GetInheritedDashboardAcl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error {
|
||||||
|
return inTransaction(func(sess *DBSession) error {
|
||||||
|
// delete existing items
|
||||||
|
_, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", cmd.DashboardId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range cmd.Items {
|
||||||
|
if item.UserId == 0 && item.UserGroupId == 0 && !item.Role.IsValid() {
|
||||||
|
return m.ErrDashboardAclInfoMissing
|
||||||
|
}
|
||||||
|
|
||||||
|
if item.DashboardId == 0 {
|
||||||
|
return m.ErrDashboardPermissionDashboardEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
sess.Nullable("user_id", "user_group_id")
|
||||||
|
if _, err := sess.Insert(item); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update dashboard HasAcl flag
|
||||||
|
dashboard := m.Dashboard{HasAcl: true}
|
||||||
|
if _, err := sess.Cols("has_acl").Where("id=? OR parent_id=?", cmd.DashboardId, cmd.DashboardId).Update(&dashboard); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
|
func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
|
||||||
return inTransaction(func(sess *DBSession) error {
|
return inTransaction(func(sess *DBSession) error {
|
||||||
if cmd.UserId == 0 && cmd.UserGroupId == 0 {
|
if cmd.UserId == 0 && cmd.UserGroupId == 0 {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<table class="filter-table gf-form-group">
|
<table class="filter-table gf-form-group">
|
||||||
<tr ng-repeat="acl in ctrl.aclItems">
|
<tr ng-repeat="acl in ctrl.items">
|
||||||
<td style="width: 100%;">
|
<td style="width: 100%;">
|
||||||
<i class="{{acl.icon}}"></i>
|
<i class="{{acl.icon}}"></i>
|
||||||
<span ng-bind-html="acl.nameHtml"></span>
|
<span ng-bind-html="acl.nameHtml"></span>
|
||||||
|
@ -6,7 +6,7 @@ import _ from 'lodash';
|
|||||||
|
|
||||||
export class AclCtrl {
|
export class AclCtrl {
|
||||||
dashboard: any;
|
dashboard: any;
|
||||||
aclItems: DashboardAcl[];
|
items: DashboardAcl[];
|
||||||
permissionOptions = [
|
permissionOptions = [
|
||||||
{value: 1, text: 'View'},
|
{value: 1, text: 'View'},
|
||||||
{value: 2, text: 'Edit'},
|
{value: 2, text: 'Edit'},
|
||||||
@ -19,12 +19,13 @@ export class AclCtrl {
|
|||||||
{value: 'Editor', text: 'Everyone With Editor Role'}
|
{value: 'Editor', text: 'Everyone With Editor Role'}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
dismiss: () => void;
|
||||||
newType: string;
|
newType: string;
|
||||||
canUpdate: boolean;
|
canUpdate: boolean;
|
||||||
|
|
||||||
/** @ngInject */
|
/** @ngInject */
|
||||||
constructor(private backendSrv, private dashboardSrv, private $sce, private $scope) {
|
constructor(private backendSrv, private dashboardSrv, private $sce, private $scope) {
|
||||||
this.aclItems = [];
|
this.items = [];
|
||||||
this.resetNewType();
|
this.resetNewType();
|
||||||
this.dashboard = dashboardSrv.getCurrent();
|
this.dashboard = dashboardSrv.getCurrent();
|
||||||
this.get(this.dashboard.id);
|
this.get(this.dashboard.id);
|
||||||
@ -37,7 +38,7 @@ export class AclCtrl {
|
|||||||
get(dashboardId: number) {
|
get(dashboardId: number) {
|
||||||
return this.backendSrv.get(`/api/dashboards/id/${dashboardId}/acl`)
|
return this.backendSrv.get(`/api/dashboards/id/${dashboardId}/acl`)
|
||||||
.then(result => {
|
.then(result => {
|
||||||
this.aclItems = _.map(result, this.prepareViewModel.bind(this));
|
this.items = _.map(result, this.prepareViewModel.bind(this));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ export class AclCtrl {
|
|||||||
|
|
||||||
update() {
|
update() {
|
||||||
return this.backendSrv.post(`/api/dashboards/id/${this.dashboard.id}/acl`, {
|
return this.backendSrv.post(`/api/dashboards/id/${this.dashboard.id}/acl`, {
|
||||||
acl: this.aclItems.map(item => {
|
items: this.items.map(item => {
|
||||||
return {
|
return {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
userId: item.userId,
|
userId: item.userId,
|
||||||
@ -67,12 +68,14 @@ export class AclCtrl {
|
|||||||
permission: item.permission,
|
permission: item.permission,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
}).then(() => {
|
||||||
|
this.dismiss();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
typeChanged() {
|
typeChanged() {
|
||||||
if (this.newType === 'Viewer' || this.newType === 'Editor') {
|
if (this.newType === 'Viewer' || this.newType === 'Editor') {
|
||||||
this.aclItems.push(this.prepareViewModel({
|
this.items.push(this.prepareViewModel({
|
||||||
permission: 1,
|
permission: 1,
|
||||||
role: this.newType
|
role: this.newType
|
||||||
}));
|
}));
|
||||||
@ -87,7 +90,7 @@ export class AclCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
userPicked(user) {
|
userPicked(user) {
|
||||||
this.aclItems.push(this.prepareViewModel({
|
this.items.push(this.prepareViewModel({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
userLogin: user.login,
|
userLogin: user.login,
|
||||||
permission: 1,
|
permission: 1,
|
||||||
@ -99,7 +102,7 @@ export class AclCtrl {
|
|||||||
|
|
||||||
groupPicked(group) {
|
groupPicked(group) {
|
||||||
console.log(group);
|
console.log(group);
|
||||||
this.aclItems.push(this.prepareViewModel({
|
this.items.push(this.prepareViewModel({
|
||||||
userGroupId: group.id,
|
userGroupId: group.id,
|
||||||
userGroup: group.name,
|
userGroup: group.name,
|
||||||
permission: 1,
|
permission: 1,
|
||||||
@ -110,7 +113,7 @@ export class AclCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removeItem(index) {
|
removeItem(index) {
|
||||||
this.aclItems.splice(index, 1);
|
this.items.splice(index, 1);
|
||||||
this.canUpdate = true;
|
this.canUpdate = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user