2017-04-28 21:22:53 +02:00
package sqlstore
import (
2021-03-17 16:06:10 +01:00
"context"
"fmt"
2017-04-28 21:22:53 +02:00
"github.com/grafana/grafana/pkg/bus"
2020-02-29 13:35:15 +01:00
"github.com/grafana/grafana/pkg/models"
2017-04-28 21:22:53 +02:00
)
2021-09-23 17:43:32 +02:00
func ( ss * SQLStore ) addDashboardACLQueryAndCommandHandlers () {
2021-12-28 16:08:07 +01:00
bus . AddHandler ( "sql" , ss . GetDashboardAclInfoList )
2017-04-28 21:22:53 +02:00
}
2021-12-22 11:02:42 +01:00
func ( ss * SQLStore ) UpdateDashboardACL ( ctx context . Context , dashboardID int64 , items [] * models . DashboardAcl ) error {
return ss . UpdateDashboardACLCtx ( ctx , dashboardID , items )
2021-09-23 17:43:32 +02:00
}
func ( ss * SQLStore ) UpdateDashboardACLCtx ( ctx context . Context , dashboardID int64 , items [] * models . DashboardAcl ) error {
return ss . WithTransactionalDbSession ( ctx , func ( sess * DBSession ) error {
2017-06-21 19:02:03 -04:00
// delete existing items
2021-03-17 16:06:10 +01:00
_ , err := sess . Exec ( "DELETE FROM dashboard_acl WHERE dashboard_id=?" , dashboardID )
2017-06-21 19:02:03 -04:00
if err != nil {
2021-03-17 16:06:10 +01:00
return fmt . Errorf ( "deleting from dashboard_acl failed: %w" , err )
2017-06-21 19:02:03 -04:00
}
2021-03-17 16:06:10 +01:00
for _ , item := range items {
2020-11-17 17:09:14 +01:00
if item . UserID == 0 && item . TeamID == 0 && ( item . Role == nil || ! item . Role . IsValid ()) {
2020-02-29 13:35:15 +01:00
return models . ErrDashboardAclInfoMissing
2017-06-21 19:02:03 -04:00
}
2020-11-17 17:09:14 +01:00
if item . DashboardID == 0 {
2020-02-29 13:35:15 +01:00
return models . ErrDashboardPermissionDashboardEmpty
2017-06-21 19:02:03 -04:00
}
2017-12-08 18:25:45 +03:00
sess . Nullable ( "user_id" , "team_id" )
2017-06-21 19:02:03 -04:00
if _ , err := sess . Insert ( item ); err != nil {
return err
}
}
// Update dashboard HasAcl flag
2020-02-29 13:35:15 +01:00
dashboard := models . Dashboard { HasAcl : true }
2021-03-17 16:06:10 +01:00
_ , err = sess . Cols ( "has_acl" ). Where ( "id=?" , dashboardID ). Update ( & dashboard )
2018-04-16 19:54:23 +02:00
return err
2017-06-21 19:02:03 -04:00
})
}
2018-02-05 13:28:24 +00:00
// GetDashboardAclInfoList returns a list of permissions for a dashboard. They can be fetched from three
// different places.
// 1) Permissions for the dashboard
// 2) permissions for its parent folder
// 3) if no specific permissions have been set for the dashboard or its parent folder then get the default permissions
2021-09-23 17:43:32 +02:00
func ( ss * SQLStore ) GetDashboardAclInfoList ( ctx context . Context , query * models . GetDashboardAclInfoListQuery ) error {
outerErr := ss . WithDbSession ( ctx , func ( dbSession * DBSession ) error {
query . Result = make ([] * models . DashboardAclInfoDTO , 0 )
falseStr := dialect . BooleanStr ( false )
2018-02-14 11:50:58 +01:00
2021-09-23 17:43:32 +02:00
if query . DashboardID == 0 {
sql := `SELECT
2017-06-21 14:11:16 -04:00
da.id,
da.org_id,
da.dashboard_id,
da.user_id,
2017-12-08 18:25:45 +03:00
da.team_id,
2017-06-21 14:11:16 -04:00
da.permission,
da.role,
da.created,
da.updated,
2018-01-31 16:43:21 +01:00
'' as user_login,
'' as user_email,
2018-02-05 13:28:24 +00:00
'' as team,
'' as title,
'' as slug,
'' as uid,` +
2021-09-23 17:43:32 +02:00
falseStr + ` AS is_folder,` +
falseStr + ` AS inherited
2018-01-31 16:43:21 +01:00
FROM dashboard_acl as da
WHERE da.dashboard_id = -1`
2021-09-23 17:43:32 +02:00
return dbSession . SQL ( sql ). Find ( & query . Result )
}
2018-01-31 16:43:21 +01:00
rawSQL := `
2018-02-05 13:28:24 +00:00
-- get permissions for the dashboard and its parent folder
2018-01-31 16:43:21 +01:00
SELECT
da.id,
da.org_id,
da.dashboard_id,
da.user_id,
da.team_id,
da.permission,
da.role,
da.created,
da.updated,
u.login AS user_login,
u.email AS user_email,
2018-02-05 13:28:24 +00:00
ug.name AS team,
2018-02-14 15:02:42 +01:00
ug.email AS team_email,
2018-02-05 13:28:24 +00:00
d.title,
d.slug,
d.uid,
2018-04-23 09:23:14 +02:00
d.is_folder,
CASE WHEN (da.dashboard_id = -1 AND d.folder_id > 0) OR da.dashboard_id = d.folder_id THEN ` + dialect . BooleanStr ( true ) + ` ELSE ` + falseStr + ` END AS inherited
2018-02-14 11:50:58 +01:00
FROM dashboard as d
LEFT JOIN dashboard folder on folder.id = d.folder_id
LEFT JOIN dashboard_acl AS da ON
da.dashboard_id = d.id OR
da.dashboard_id = d.folder_id OR
(
-- include default permissions -->
da.org_id = -1 AND (
(folder.id IS NOT NULL AND folder.has_acl = ` + falseStr + `) OR
(folder.id IS NULL AND d.has_acl = ` + falseStr + `)
)
)
LEFT JOIN ` + dialect . Quote ( "user" ) + ` AS u ON u.id = da.user_id
LEFT JOIN team ug on ug.id = da.team_id
WHERE d.org_id = ? AND d.id = ? AND da.id IS NOT NULL
2019-04-24 10:05:35 -04:00
ORDER BY da.id ASC
2018-01-31 16:43:21 +01:00
`
2021-09-23 17:43:32 +02:00
return dbSession . SQL ( rawSQL , query . OrgID , query . DashboardID ). Find ( & query . Result )
})
if outerErr != nil {
return outerErr
2018-01-31 16:43:21 +01:00
}
2017-05-08 15:35:34 +02:00
2017-06-08 10:39:17 +02:00
for _ , p := range query . Result {
2017-06-21 14:11:16 -04:00
p . PermissionName = p . Permission . String ()
2017-06-08 10:39:17 +02:00
}
2021-09-23 17:43:32 +02:00
return nil
2017-04-28 21:22:53 +02:00
}