2022-03-09 10:57:50 -06:00
package dashboards
2022-03-10 11:19:50 -06:00
import (
"context"
"strings"
2022-06-07 04:02:20 -05:00
"github.com/grafana/grafana/pkg/models"
2022-03-10 11:19:50 -06:00
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
)
2022-03-09 10:57:50 -06:00
const (
2022-03-30 08:14:26 -05:00
ScopeFoldersRoot = "folders"
ScopeFoldersPrefix = "folders:uid:"
2022-03-09 10:57:50 -06:00
ActionFoldersCreate = "folders:create"
ActionFoldersRead = "folders:read"
ActionFoldersWrite = "folders:write"
ActionFoldersDelete = "folders:delete"
ActionFoldersPermissionsRead = "folders.permissions:read"
ActionFoldersPermissionsWrite = "folders.permissions:write"
2022-03-30 08:14:26 -05:00
ScopeDashboardsRoot = "dashboards"
ScopeDashboardsPrefix = "dashboards:uid:"
2022-05-04 09:12:09 -05:00
ActionDashboardsCreate = "dashboards:create"
ActionDashboardsRead = "dashboards:read"
ActionDashboardsWrite = "dashboards:write"
ActionDashboardsDelete = "dashboards:delete"
ActionDashboardsPermissionsRead = "dashboards.permissions:read"
ActionDashboardsPermissionsWrite = "dashboards.permissions:write"
2022-09-07 16:29:01 -05:00
ActionDashboardsPublicWrite = "dashboards.public:write"
2022-03-09 10:57:50 -06:00
)
var (
2022-05-04 09:12:09 -05:00
ScopeFoldersProvider = ac . NewScopeProvider ( ScopeFoldersRoot )
ScopeFoldersAll = ScopeFoldersProvider . GetResourceAllScope ( )
ScopeDashboardsProvider = ac . NewScopeProvider ( ScopeDashboardsRoot )
ScopeDashboardsAll = ScopeDashboardsProvider . GetResourceAllScope ( )
2022-03-09 10:57:50 -06:00
)
2022-03-10 11:19:50 -06:00
2022-05-02 02:29:30 -05:00
// NewFolderNameScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "folders:name:" into an uid based scope.
func NewFolderNameScopeResolver ( db Store ) ( string , ac . ScopeAttributeResolver ) {
2022-03-10 11:19:50 -06:00
prefix := ScopeFoldersProvider . GetResourceScopeName ( "" )
2022-05-02 02:29:30 -05:00
return prefix , ac . ScopeAttributeResolverFunc ( func ( ctx context . Context , orgID int64 , scope string ) ( [ ] string , error ) {
2022-03-10 11:19:50 -06:00
if ! strings . HasPrefix ( scope , prefix ) {
2022-05-02 02:29:30 -05:00
return nil , ac . ErrInvalidScope
2022-03-10 11:19:50 -06:00
}
nsName := scope [ len ( prefix ) : ]
if len ( nsName ) == 0 {
2022-05-02 02:29:30 -05:00
return nil , ac . ErrInvalidScope
2022-03-10 11:19:50 -06:00
}
2022-03-14 10:21:42 -05:00
folder , err := db . GetFolderByTitle ( ctx , orgID , nsName )
2022-03-10 11:19:50 -06:00
if err != nil {
2022-05-02 02:29:30 -05:00
return nil , err
2022-03-10 11:19:50 -06:00
}
2022-11-11 07:28:24 -06:00
return [ ] string { ScopeFoldersProvider . GetResourceScopeUID ( folder . UID ) } , nil
2022-05-02 02:29:30 -05:00
} )
2022-03-10 11:19:50 -06:00
}
2022-03-15 09:37:16 -05:00
2022-05-02 02:29:30 -05:00
// NewFolderIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "folders:id:" into an uid based scope.
func NewFolderIDScopeResolver ( db Store ) ( string , ac . ScopeAttributeResolver ) {
2022-03-30 08:14:26 -05:00
prefix := ScopeFoldersProvider . GetResourceScope ( "" )
2022-05-02 02:29:30 -05:00
return prefix , ac . ScopeAttributeResolverFunc ( func ( ctx context . Context , orgID int64 , scope string ) ( [ ] string , error ) {
2022-03-15 09:37:16 -05:00
if ! strings . HasPrefix ( scope , prefix ) {
2022-05-02 02:29:30 -05:00
return nil , ac . ErrInvalidScope
2022-03-15 09:37:16 -05:00
}
2022-03-30 08:14:26 -05:00
2022-06-07 04:02:20 -05:00
id , err := ac . ParseScopeID ( scope )
2022-03-30 08:14:26 -05:00
if err != nil {
2022-06-07 04:02:20 -05:00
return nil , err
2022-03-15 09:37:16 -05:00
}
2022-03-30 08:14:26 -05:00
if id == 0 {
2022-05-02 02:29:30 -05:00
return [ ] string { ScopeFoldersProvider . GetResourceScopeUID ( ac . GeneralFolderUID ) } , nil
2022-03-30 08:14:26 -05:00
}
folder , err := db . GetFolderByID ( ctx , orgID , id )
2022-03-15 09:37:16 -05:00
if err != nil {
2022-05-02 02:29:30 -05:00
return nil , err
2022-03-15 09:37:16 -05:00
}
2022-03-30 08:14:26 -05:00
2022-11-11 07:28:24 -06:00
return [ ] string { ScopeFoldersProvider . GetResourceScopeUID ( folder . UID ) } , nil
2022-05-02 02:29:30 -05:00
} )
2022-03-15 09:37:16 -05:00
}
2022-06-07 04:02:20 -05:00
// NewDashboardIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "dashboards:id:"
// into uid based scopes for both dashboard and folder
func NewDashboardIDScopeResolver ( db Store ) ( string , ac . ScopeAttributeResolver ) {
prefix := ScopeDashboardsProvider . GetResourceScope ( "" )
return prefix , ac . ScopeAttributeResolverFunc ( func ( ctx context . Context , orgID int64 , scope string ) ( [ ] string , error ) {
if ! strings . HasPrefix ( scope , prefix ) {
return nil , ac . ErrInvalidScope
}
id , err := ac . ParseScopeID ( scope )
if err != nil {
return nil , err
}
dashboard , err := db . GetDashboard ( ctx , & models . GetDashboardQuery { Id : id , OrgId : orgID } )
if err != nil {
return nil , err
}
return resolveDashboardScope ( ctx , db , orgID , dashboard )
} )
}
// NewDashboardUIDScopeResolver provides an ScopeAttributeResolver that is able to convert a scope prefixed with "dashboards:uid:"
// into uid based scopes for both dashboard and folder
func NewDashboardUIDScopeResolver ( db Store ) ( string , ac . ScopeAttributeResolver ) {
prefix := ScopeDashboardsProvider . GetResourceScopeUID ( "" )
return prefix , ac . ScopeAttributeResolverFunc ( func ( ctx context . Context , orgID int64 , scope string ) ( [ ] string , error ) {
if ! strings . HasPrefix ( scope , prefix ) {
return nil , ac . ErrInvalidScope
}
uid , err := ac . ParseScopeUID ( scope )
if err != nil {
return nil , err
}
dashboard , err := db . GetDashboard ( ctx , & models . GetDashboardQuery { Uid : uid , OrgId : orgID } )
if err != nil {
return nil , err
}
return resolveDashboardScope ( ctx , db , orgID , dashboard )
} )
}
func resolveDashboardScope ( ctx context . Context , db Store , orgID int64 , dashboard * models . Dashboard ) ( [ ] string , error ) {
var folderUID string
2022-08-09 03:14:08 -05:00
if dashboard . FolderId < 0 {
return [ ] string { ScopeDashboardsProvider . GetResourceScopeUID ( dashboard . Uid ) } , nil
}
2022-06-07 04:02:20 -05:00
if dashboard . FolderId == 0 {
folderUID = ac . GeneralFolderUID
} else {
folder , err := db . GetFolderByID ( ctx , orgID , dashboard . FolderId )
if err != nil {
return nil , err
}
2022-11-11 07:28:24 -06:00
folderUID = folder . UID
2022-06-07 04:02:20 -05:00
}
2022-08-09 03:14:08 -05:00
2022-06-07 04:02:20 -05:00
return [ ] string {
ScopeDashboardsProvider . GetResourceScopeUID ( dashboard . Uid ) ,
ScopeFoldersProvider . GetResourceScopeUID ( folderUID ) ,
} , nil
}