diff --git a/pkg/services/accesscontrol/ossaccesscontrol/permissions_services.go b/pkg/services/accesscontrol/ossaccesscontrol/permissions_services.go index 693efe7053f..5101c049f36 100644 --- a/pkg/services/accesscontrol/ossaccesscontrol/permissions_services.go +++ b/pkg/services/accesscontrol/ossaccesscontrol/permissions_services.go @@ -14,6 +14,7 @@ import ( "github.com/grafana/grafana/pkg/services/auth/identity" "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/dashboards/dashboardaccess" + "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/libraryelements" @@ -280,13 +281,24 @@ func ProvideFolderPermissions( return &FolderPermissionsService{srv}, nil } -func ProvideDatasourcePermissionsService() *DatasourcePermissionsService { - return &DatasourcePermissionsService{} +// DatasourceQueryActions contains permissions to read information +// about a data source and submit arbitrary queries to it. +var DatasourceQueryActions = []string{ + datasources.ActionRead, + datasources.ActionQuery, +} + +func ProvideDatasourcePermissionsService(features featuremgmt.FeatureToggles, db db.DB, actionSetService resourcepermissions.ActionSetService) *DatasourcePermissionsService { + return &DatasourcePermissionsService{ + store: resourcepermissions.NewStore(db, features, &actionSetService), + } } var _ accesscontrol.DatasourcePermissionsService = new(DatasourcePermissionsService) -type DatasourcePermissionsService struct{} +type DatasourcePermissionsService struct { + store resourcepermissions.Store +} func (e DatasourcePermissionsService) GetPermissions(ctx context.Context, user identity.Requester, resourceID string) ([]accesscontrol.ResourcePermission, error) { return nil, nil @@ -304,12 +316,39 @@ func (e DatasourcePermissionsService) SetBuiltInRolePermission(ctx context.Conte return nil, nil } +// SetPermissions sets managed permissions for a datasource in OSS. This ensures that Viewers and Editors maintain query access to a data source +// if an OSS/unlicensed instance is upgraded to Enterprise/licensed. +// https://github.com/grafana/identity-access-team/issues/672 func (e DatasourcePermissionsService) SetPermissions(ctx context.Context, orgID int64, resourceID string, commands ...accesscontrol.SetResourcePermissionCommand) ([]accesscontrol.ResourcePermission, error) { - return nil, nil + var dbCommands []resourcepermissions.SetResourcePermissionsCommand + for _, cmd := range commands { + // Only set query permissions for built-in roles + if cmd.Permission != "Query" || cmd.BuiltinRole == "" { + continue + } + actions := DatasourceQueryActions + + dbCommands = append(dbCommands, resourcepermissions.SetResourcePermissionsCommand{ + BuiltinRole: cmd.BuiltinRole, + SetResourcePermissionCommand: resourcepermissions.SetResourcePermissionCommand{ + Actions: actions, + Resource: datasources.ScopeRoot, + ResourceID: resourceID, + ResourceAttribute: "uid", + Permission: cmd.Permission, + }, + }) + } + + return e.store.SetResourcePermissions(ctx, orgID, dbCommands, resourcepermissions.ResourceHooks{}) } func (e DatasourcePermissionsService) DeleteResourcePermissions(ctx context.Context, orgID int64, resourceID string) error { - return nil + return e.store.DeleteResourcePermissions(ctx, orgID, &resourcepermissions.DeleteResourcePermissionsCmd{ + Resource: datasources.ScopeRoot, + ResourceAttribute: "uid", + ResourceID: resourceID, + }) } func (e DatasourcePermissionsService) MapActions(permission accesscontrol.ResourcePermission) string {