2017-04-29 03:22:53 +08:00
package sqlstore
import (
2017-06-23 03:16:41 +08:00
"fmt"
2017-04-29 03:22:53 +08:00
"time"
"github.com/grafana/grafana/pkg/bus"
m "github.com/grafana/grafana/pkg/models"
)
func init ( ) {
2017-06-20 05:15:25 +08:00
bus . AddHandler ( "sql" , SetDashboardAcl )
2017-06-22 07:02:03 +08:00
bus . AddHandler ( "sql" , UpdateDashboardAcl )
2017-06-20 05:15:25 +08:00
bus . AddHandler ( "sql" , RemoveDashboardAcl )
2017-06-20 05:30:54 +08:00
bus . AddHandler ( "sql" , GetDashboardAclInfoList )
2017-04-29 03:22:53 +08:00
}
2017-06-22 07:02:03 +08:00
func UpdateDashboardAcl ( cmd * m . UpdateDashboardAclCommand ) error {
return inTransaction ( func ( sess * DBSession ) error {
// delete existing items
_ , err := sess . Exec ( "DELETE FROM dashboard_acl WHERE dashboard_id=?" , cmd . DashboardId )
if err != nil {
return err
}
for _ , item := range cmd . Items {
2017-12-08 23:25:45 +08:00
if item . UserId == 0 && item . TeamId == 0 && ! item . Role . IsValid ( ) {
2017-06-22 07:02:03 +08:00
return m . ErrDashboardAclInfoMissing
}
if item . DashboardId == 0 {
return m . ErrDashboardPermissionDashboardEmpty
}
2017-12-08 23:25:45 +08:00
sess . Nullable ( "user_id" , "team_id" )
2017-06-22 07:02:03 +08:00
if _ , err := sess . Insert ( item ) ; err != nil {
return err
}
}
// Update dashboard HasAcl flag
dashboard := m . Dashboard { HasAcl : true }
2017-06-24 04:00:26 +08:00
if _ , err := sess . Cols ( "has_acl" ) . Where ( "id=? OR folder_id=?" , cmd . DashboardId , cmd . DashboardId ) . Update ( & dashboard ) ; err != nil {
2017-06-22 07:02:03 +08:00
return err
}
return nil
} )
}
2017-06-20 05:15:25 +08:00
func SetDashboardAcl ( cmd * m . SetDashboardAclCommand ) error {
2017-05-24 22:19:21 +08:00
return inTransaction ( func ( sess * DBSession ) error {
2017-12-08 23:25:45 +08:00
if cmd . UserId == 0 && cmd . TeamId == 0 {
2017-06-20 06:19:58 +08:00
return m . ErrDashboardAclInfoMissing
2017-06-15 05:45:30 +08:00
}
2017-06-20 06:34:25 +08:00
if cmd . DashboardId == 0 {
return m . ErrDashboardPermissionDashboardEmpty
}
2017-12-08 23:25:45 +08:00
if res , err := sess . Query ( "SELECT 1 from " + dialect . Quote ( "dashboard_acl" ) + " WHERE dashboard_id =? and (team_id=? or user_id=?)" , cmd . DashboardId , cmd . TeamId , cmd . UserId ) ; err != nil {
2017-04-29 03:22:53 +08:00
return err
} else if len ( res ) == 1 {
2017-06-22 02:11:16 +08:00
2017-04-29 03:22:53 +08:00
entity := m . DashboardAcl {
2017-06-22 02:11:16 +08:00
Permission : cmd . Permission ,
Updated : time . Now ( ) ,
2017-04-29 03:22:53 +08:00
}
2017-06-22 02:11:16 +08:00
2017-12-08 23:25:45 +08:00
if _ , err := sess . Cols ( "updated" , "permission" ) . Where ( "dashboard_id =? and (team_id=? or user_id=?)" , cmd . DashboardId , cmd . TeamId , cmd . UserId ) . Update ( & entity ) ; err != nil {
2017-04-29 03:22:53 +08:00
return err
}
return nil
}
entity := m . DashboardAcl {
OrgId : cmd . OrgId ,
2017-12-12 00:46:05 +08:00
TeamId : cmd . TeamId ,
2017-04-29 03:22:53 +08:00
UserId : cmd . UserId ,
Created : time . Now ( ) ,
Updated : time . Now ( ) ,
DashboardId : cmd . DashboardId ,
2017-06-22 02:11:16 +08:00
Permission : cmd . Permission ,
2017-04-29 03:22:53 +08:00
}
2017-06-22 02:11:16 +08:00
cols := [ ] string { "org_id" , "created" , "updated" , "dashboard_id" , "permission" }
2017-04-29 03:22:53 +08:00
if cmd . UserId != 0 {
cols = append ( cols , "user_id" )
}
2017-12-08 23:25:45 +08:00
if cmd . TeamId != 0 {
cols = append ( cols , "team_id" )
2017-04-29 03:22:53 +08:00
}
2017-06-22 02:11:16 +08:00
_ , err := sess . Cols ( cols ... ) . Insert ( & entity )
2017-04-29 03:22:53 +08:00
if err != nil {
return err
}
2017-06-22 02:11:16 +08:00
2017-06-10 03:56:13 +08:00
cmd . Result = entity
2017-04-29 03:22:53 +08:00
2017-06-10 03:56:13 +08:00
// Update dashboard HasAcl flag
2017-04-29 03:22:53 +08:00
dashboard := m . Dashboard {
HasAcl : true ,
}
2017-06-18 06:24:38 +08:00
2017-06-24 04:00:26 +08:00
if _ , err := sess . Cols ( "has_acl" ) . Where ( "id=? OR folder_id=?" , cmd . DashboardId , cmd . DashboardId ) . Update ( & dashboard ) ; err != nil {
2017-04-29 03:22:53 +08:00
return err
}
return nil
} )
}
2018-02-05 21:28:24 +08:00
// RemoveDashboardAcl removes a specified permission from the dashboard acl
2017-06-20 05:15:25 +08:00
func RemoveDashboardAcl ( cmd * m . RemoveDashboardAclCommand ) error {
2017-05-24 22:19:21 +08:00
return inTransaction ( func ( sess * DBSession ) error {
2017-06-20 06:11:30 +08:00
var rawSQL = "DELETE FROM " + dialect . Quote ( "dashboard_acl" ) + " WHERE org_id =? and id=?"
_ , err := sess . Exec ( rawSQL , cmd . OrgId , cmd . AclId )
2017-05-03 17:32:21 +08:00
if err != nil {
return err
}
return err
} )
}
2018-02-05 21:28:24 +08: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
2017-06-20 05:30:54 +08:00
func GetDashboardAclInfoList ( query * m . GetDashboardAclInfoListQuery ) error {
2018-01-31 23:43:21 +08:00
var err error
if query . DashboardId == 0 {
sql := ` SELECT
2017-06-22 02:11:16 +08:00
da . id ,
da . org_id ,
da . dashboard_id ,
da . user_id ,
2017-12-08 23:25:45 +08:00
da . team_id ,
2017-06-22 02:11:16 +08:00
da . permission ,
da . role ,
da . created ,
da . updated ,
2018-01-31 23:43:21 +08:00
' ' as user_login ,
' ' as user_email ,
2018-02-05 21:28:24 +08:00
' ' as team ,
' ' as title ,
' ' as slug ,
' ' as uid , ` +
dialect . BooleanStr ( false ) + ` AS is_folder
2018-01-31 23:43:21 +08:00
FROM dashboard_acl as da
WHERE da . dashboard_id = - 1 `
query . Result = make ( [ ] * m . DashboardAclInfoDTO , 0 )
err = x . SQL ( sql ) . Find ( & query . Result )
} else {
dashboardFilter := fmt . Sprintf ( ` IN (
SELECT % d
UNION
SELECT folder_id from dashboard where id = % d
) ` , query . DashboardId , query . DashboardId )
rawSQL := `
2018-02-05 21:28:24 +08:00
-- get permissions for the dashboard and its parent folder
2018-01-31 23:43:21 +08: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 21:28:24 +08:00
ug . name AS team ,
d . title ,
d . slug ,
d . uid ,
d . is_folder
2018-01-31 23:43:21 +08:00
FROM ` + dialect.Quote("dashboard_acl") + ` as da
LEFT OUTER JOIN ` + dialect.Quote("user") + ` AS u ON u . id = da . user_id
LEFT OUTER JOIN team ug on ug . id = da . team_id
2018-02-05 21:28:24 +08:00
LEFT OUTER JOIN dashboard d on da . dashboard_id = d . id
2018-01-31 23:43:21 +08:00
WHERE dashboard_id ` + dashboardFilter + ` AND da . org_id = ?
2018-02-05 21:28:24 +08:00
-- Also include default permissions if folder or dashboard field "has_acl" is false
2018-01-31 23:43:21 +08:00
UNION
SELECT
da . id ,
da . org_id ,
da . dashboard_id ,
da . user_id ,
da . team_id ,
da . permission ,
da . role ,
da . created ,
da . updated ,
' ' as user_login ,
' ' as user_email ,
2018-02-05 21:28:24 +08:00
' ' as team ,
folder . title ,
folder . slug ,
folder . uid ,
folder . is_folder
FROM dashboard_acl as da ,
2018-01-31 23:43:21 +08:00
dashboard as dash
2018-02-05 21:28:24 +08:00
LEFT OUTER JOIN dashboard folder on dash . folder_id = folder . id
2018-01-31 23:43:21 +08:00
WHERE
dash . id = ? AND (
dash . has_acl = ` + dialect.BooleanStr(false) + ` or
folder . has_acl = ` + dialect.BooleanStr(false) + `
) AND
da . dashboard_id = - 1
ORDER BY 1 ASC
`
query . Result = make ( [ ] * m . DashboardAclInfoDTO , 0 )
err = x . SQL ( rawSQL , query . OrgId , query . DashboardId ) . Find ( & query . Result )
}
2017-05-08 21:35:34 +08:00
2017-06-08 16:39:17 +08:00
for _ , p := range query . Result {
2017-06-22 02:11:16 +08:00
p . PermissionName = p . Permission . String ( )
2017-06-08 16:39:17 +08:00
}
2017-05-08 21:35:34 +08:00
return err
2017-04-29 03:22:53 +08:00
}