2022-02-22 01:47:42 -06:00
|
|
|
package commentmodel
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/models"
|
2022-04-12 11:30:50 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
2022-02-22 01:47:42 -06:00
|
|
|
"github.com/grafana/grafana/pkg/services/annotations"
|
2022-05-17 13:52:22 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
2022-02-22 01:47:42 -06:00
|
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
|
|
"github.com/grafana/grafana/pkg/services/guardian"
|
2022-04-12 11:30:50 -05:00
|
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
2022-02-22 01:47:42 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
type PermissionChecker struct {
|
2022-05-17 13:52:22 -05:00
|
|
|
sqlStore *sqlstore.SQLStore
|
|
|
|
features featuremgmt.FeatureToggles
|
|
|
|
accessControl accesscontrol.AccessControl
|
|
|
|
dashboardService dashboards.DashboardService
|
2022-02-22 01:47:42 -06:00
|
|
|
}
|
|
|
|
|
2022-05-17 13:52:22 -05:00
|
|
|
func NewPermissionChecker(sqlStore *sqlstore.SQLStore, features featuremgmt.FeatureToggles,
|
|
|
|
accessControl accesscontrol.AccessControl, dashboardService dashboards.DashboardService,
|
|
|
|
) *PermissionChecker {
|
2022-04-12 11:30:50 -05:00
|
|
|
return &PermissionChecker{sqlStore: sqlStore, features: features, accessControl: accessControl}
|
2022-02-22 01:47:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PermissionChecker) getDashboardByUid(ctx context.Context, orgID int64, uid string) (*models.Dashboard, error) {
|
|
|
|
query := models.GetDashboardQuery{Uid: uid, OrgId: orgID}
|
2022-05-17 13:52:22 -05:00
|
|
|
if err := c.dashboardService.GetDashboard(ctx, &query); err != nil {
|
2022-02-22 01:47:42 -06:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return query.Result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PermissionChecker) getDashboardById(ctx context.Context, orgID int64, id int64) (*models.Dashboard, error) {
|
|
|
|
query := models.GetDashboardQuery{Id: id, OrgId: orgID}
|
2022-05-17 13:52:22 -05:00
|
|
|
if err := c.dashboardService.GetDashboard(ctx, &query); err != nil {
|
2022-02-22 01:47:42 -06:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return query.Result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PermissionChecker) CheckReadPermissions(ctx context.Context, orgId int64, signedInUser *models.SignedInUser, objectType string, objectID string) (bool, error) {
|
|
|
|
switch objectType {
|
|
|
|
case ObjectTypeOrg:
|
|
|
|
return false, nil
|
|
|
|
case ObjectTypeDashboard:
|
|
|
|
if !c.features.IsEnabled(featuremgmt.FlagDashboardComments) {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
dash, err := c.getDashboardByUid(ctx, orgId, objectID)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
guard := guardian.New(ctx, dash.Id, orgId, signedInUser)
|
|
|
|
if ok, err := guard.CanView(); err != nil || !ok {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
case ObjectTypeAnnotation:
|
|
|
|
if !c.features.IsEnabled(featuremgmt.FlagAnnotationComments) {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
repo := annotations.GetRepository()
|
|
|
|
annotationID, err := strconv.ParseInt(objectID, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
2022-04-11 07:18:38 -05:00
|
|
|
items, err := repo.Find(ctx, &annotations.ItemQuery{AnnotationId: annotationID, OrgId: orgId, SignedInUser: signedInUser})
|
2022-02-22 01:47:42 -06:00
|
|
|
if err != nil || len(items) != 1 {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
dashboardID := items[0].DashboardId
|
|
|
|
if dashboardID == 0 {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
dash, err := c.getDashboardById(ctx, orgId, dashboardID)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
guard := guardian.New(ctx, dash.Id, orgId, signedInUser)
|
|
|
|
if ok, err := guard.CanView(); err != nil || !ok {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PermissionChecker) CheckWritePermissions(ctx context.Context, orgId int64, signedInUser *models.SignedInUser, objectType string, objectID string) (bool, error) {
|
|
|
|
switch objectType {
|
|
|
|
case ObjectTypeOrg:
|
|
|
|
return false, nil
|
|
|
|
case ObjectTypeDashboard:
|
|
|
|
if !c.features.IsEnabled(featuremgmt.FlagDashboardComments) {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
dash, err := c.getDashboardByUid(ctx, orgId, objectID)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
guard := guardian.New(ctx, dash.Id, orgId, signedInUser)
|
|
|
|
if ok, err := guard.CanEdit(); err != nil || !ok {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
case ObjectTypeAnnotation:
|
|
|
|
if !c.features.IsEnabled(featuremgmt.FlagAnnotationComments) {
|
|
|
|
return false, nil
|
|
|
|
}
|
2022-04-25 03:42:09 -05:00
|
|
|
if !c.accessControl.IsDisabled() {
|
2022-04-12 11:30:50 -05:00
|
|
|
evaluator := accesscontrol.EvalPermission(accesscontrol.ActionAnnotationsWrite, accesscontrol.ScopeAnnotationsTypeDashboard)
|
|
|
|
if canEdit, err := c.accessControl.Evaluate(ctx, signedInUser, evaluator); err != nil || !canEdit {
|
|
|
|
return canEdit, err
|
|
|
|
}
|
|
|
|
}
|
2022-02-22 01:47:42 -06:00
|
|
|
repo := annotations.GetRepository()
|
|
|
|
annotationID, err := strconv.ParseInt(objectID, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
2022-04-11 07:18:38 -05:00
|
|
|
items, err := repo.Find(ctx, &annotations.ItemQuery{AnnotationId: annotationID, OrgId: orgId, SignedInUser: signedInUser})
|
2022-02-22 01:47:42 -06:00
|
|
|
if err != nil || len(items) != 1 {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
dashboardID := items[0].DashboardId
|
|
|
|
if dashboardID == 0 {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
dash, err := c.getDashboardById(ctx, orgId, dashboardID)
|
|
|
|
if err != nil {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
guard := guardian.New(ctx, dash.Id, orgId, signedInUser)
|
|
|
|
if ok, err := guard.CanEdit(); err != nil || !ok {
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
return true, nil
|
|
|
|
}
|