2020-04-20 22:20:45 +08:00
package permissions
import (
2020-06-29 20:08:32 +08:00
"strings"
2020-04-20 22:20:45 +08:00
"github.com/grafana/grafana/pkg/models"
2022-03-03 22:05:47 +08:00
"github.com/grafana/grafana/pkg/services/accesscontrol"
2022-03-10 00:57:50 +08:00
"github.com/grafana/grafana/pkg/services/dashboards"
2020-04-20 22:20:45 +08:00
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
2022-03-16 22:07:04 +08:00
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
2020-04-20 22:20:45 +08:00
)
type DashboardPermissionFilter struct {
OrgRole models . RoleType
Dialect migrator . Dialect
UserId int64
OrgId int64
PermissionLevel models . PermissionType
}
func ( d DashboardPermissionFilter ) Where ( ) ( string , [ ] interface { } ) {
if d . OrgRole == models . ROLE_ADMIN {
return "" , nil
}
okRoles := [ ] interface { } { d . OrgRole }
if d . OrgRole == models . ROLE_EDITOR {
okRoles = append ( okRoles , models . ROLE_VIEWER )
}
falseStr := d . Dialect . BooleanStr ( false )
sql := ` (
dashboard . id IN (
SELECT distinct DashboardId from (
SELECT d . id AS DashboardId
FROM dashboard AS d
LEFT JOIN dashboard_acl AS da ON
da . dashboard_id = d . id OR
da . dashboard_id = d . folder_id
WHERE
d . org_id = ? AND
da . permission >= ? AND
(
da . user_id = ? OR
2022-01-04 20:04:02 +08:00
da . team_id IN ( SELECT team_id from team_member AS tm WHERE tm . user_id = ? ) OR
2020-04-20 22:20:45 +08:00
da . role IN ( ? ` + strings.Repeat(",?", len(okRoles)-1) + ` )
)
UNION
SELECT d . id AS DashboardId
FROM dashboard AS d
LEFT JOIN dashboard AS folder on folder . id = d . folder_id
LEFT JOIN dashboard_acl AS da ON
(
-- include default permissions -- >
da . org_id = - 1 AND (
( folder . id IS NOT NULL AND folder . has_acl = ` + falseStr + ` ) OR
2022-03-03 22:05:47 +08:00
( folder . id IS NULL AND d . has_acl = ` + falseStr + ` )
2020-04-20 22:20:45 +08:00
)
)
WHERE
d . org_id = ? AND
da . permission >= ? AND
(
da . user_id = ? OR
da . role IN ( ? ` + strings.Repeat(",?", len(okRoles)-1) + ` )
)
) AS a
)
)
`
params := [ ] interface { } { d . OrgId , d . PermissionLevel , d . UserId , d . UserId }
params = append ( params , okRoles ... )
params = append ( params , d . OrgId , d . PermissionLevel , d . UserId )
params = append ( params , okRoles ... )
return sql , params
}
2022-03-03 22:05:47 +08:00
type AccessControlDashboardPermissionFilter struct {
2022-03-16 22:07:04 +08:00
User * models . SignedInUser
dashboardActions [ ] string
folderActions [ ] string
2022-03-03 22:05:47 +08:00
}
2022-03-16 22:07:04 +08:00
// NewAccessControlDashboardPermissionFilter creates a new AccessControlDashboardPermissionFilter that is configured with specific actions calculated based on the models.PermissionType and query type
func NewAccessControlDashboardPermissionFilter ( user * models . SignedInUser , permissionLevel models . PermissionType , queryType string ) AccessControlDashboardPermissionFilter {
needEdit := permissionLevel > models . PERMISSION_VIEW
2022-03-15 00:11:21 +08:00
folderActions := [ ] string { dashboards . ActionFoldersRead }
2022-03-16 22:07:04 +08:00
var dashboardActions [ ] string
if queryType == searchstore . TypeAlertFolder {
folderActions = append ( folderActions , accesscontrol . ActionAlertingRuleRead )
if needEdit {
folderActions = append ( folderActions , accesscontrol . ActionAlertingRuleUpdate )
}
} else {
dashboardActions = append ( dashboardActions , accesscontrol . ActionDashboardsRead )
if needEdit {
folderActions = append ( folderActions , accesscontrol . ActionDashboardsCreate )
dashboardActions = append ( dashboardActions , accesscontrol . ActionDashboardsWrite )
}
2022-03-08 19:46:49 +08:00
}
2022-03-16 22:07:04 +08:00
return AccessControlDashboardPermissionFilter { User : user , folderActions : folderActions , dashboardActions : dashboardActions }
}
2022-03-08 19:46:49 +08:00
2022-03-16 22:07:04 +08:00
func ( f AccessControlDashboardPermissionFilter ) Where ( ) ( string , [ ] interface { } ) {
2022-03-15 00:11:21 +08:00
var args [ ] interface { }
2022-03-03 22:05:47 +08:00
builder := strings . Builder { }
2022-03-16 22:07:04 +08:00
builder . WriteString ( "(" )
2022-03-03 22:05:47 +08:00
2022-03-16 22:07:04 +08:00
if len ( f . dashboardActions ) > 0 {
builder . WriteString ( "((" )
2022-03-22 00:58:18 +08:00
dashFilter , _ := accesscontrol . Filter ( f . User , "dashboard.id" , "dashboards:id:" , f . dashboardActions ... )
2022-03-16 22:07:04 +08:00
builder . WriteString ( dashFilter . Where )
args = append ( args , dashFilter . Args ... )
2022-03-03 22:05:47 +08:00
2022-03-16 22:07:04 +08:00
builder . WriteString ( " OR " )
2022-03-03 22:05:47 +08:00
2022-03-22 00:58:18 +08:00
dashFolderFilter , _ := accesscontrol . Filter ( f . User , "dashboard.folder_id" , "folders:id:" , f . dashboardActions ... )
2022-03-16 22:07:04 +08:00
builder . WriteString ( dashFolderFilter . Where )
builder . WriteString ( ") AND NOT dashboard.is_folder)" )
args = append ( args , dashFolderFilter . Args ... )
}
2022-03-03 22:05:47 +08:00
2022-03-16 22:07:04 +08:00
if len ( f . folderActions ) > 0 {
if len ( f . dashboardActions ) > 0 {
builder . WriteString ( " OR " )
}
builder . WriteString ( "(" )
2022-03-22 00:58:18 +08:00
folderFilter , _ := accesscontrol . Filter ( f . User , "dashboard.id" , "folders:id:" , f . folderActions ... )
2022-03-16 22:07:04 +08:00
builder . WriteString ( folderFilter . Where )
builder . WriteString ( " AND dashboard.is_folder)" )
args = append ( args , folderFilter . Args ... )
}
2022-03-03 22:05:47 +08:00
2022-03-16 22:07:04 +08:00
builder . WriteString ( ")" )
2022-03-15 00:11:21 +08:00
return builder . String ( ) , args
2022-03-03 22:05:47 +08:00
}