package database import ( "context" "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/services/sqlstore" ) // 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 func (d *DashboardStore) GetDashboardAclInfoList(ctx context.Context, query *models.GetDashboardAclInfoListQuery) error { outerErr := d.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error { query.Result = make([]*models.DashboardAclInfoDTO, 0) falseStr := d.dialect.BooleanStr(false) if query.DashboardID == 0 { sql := `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, '' as team, '' as title, '' as slug, '' as uid,` + falseStr + ` AS is_folder,` + falseStr + ` AS inherited FROM dashboard_acl as da WHERE da.dashboard_id = -1` return dbSession.SQL(sql).Find(&query.Result) } rawSQL := ` -- get permissions for the dashboard and its parent folder 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, ug.name AS team, ug.email AS team_email, d.title, d.slug, d.uid, d.is_folder, CASE WHEN (da.dashboard_id = -1 AND d.folder_id > 0) OR da.dashboard_id = d.folder_id THEN ` + d.dialect.BooleanStr(true) + ` ELSE ` + falseStr + ` END AS inherited 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 ` + d.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 ORDER BY da.id ASC ` return dbSession.SQL(rawSQL, query.OrgID, query.DashboardID).Find(&query.Result) }) if outerErr != nil { return outerErr } for _, p := range query.Result { p.PermissionName = p.Permission.String() } return nil } // HasEditPermissionInFolders validates that an user have access to a certain folder func (d *DashboardStore) HasEditPermissionInFolders(ctx context.Context, query *models.HasEditPermissionInFoldersQuery) error { return d.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error { if query.SignedInUser.HasRole(models.ROLE_EDITOR) { query.Result = true return nil } builder := &sqlstore.SQLBuilder{} builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ? AND dashboard.is_folder = ?", query.SignedInUser.OrgId, d.dialect.BooleanStr(true)) builder.WriteDashboardPermissionFilter(query.SignedInUser, models.PERMISSION_EDIT) type folderCount struct { Count int64 } resp := make([]*folderCount, 0) if err := dbSession.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&resp); err != nil { return err } query.Result = len(resp) > 0 && resp[0].Count > 0 return nil }) } func (d *DashboardStore) HasAdminPermissionInFolders(ctx context.Context, query *models.HasAdminPermissionInFoldersQuery) error { return d.sqlStore.WithDbSession(ctx, func(dbSession *sqlstore.DBSession) error { if query.SignedInUser.HasRole(models.ROLE_ADMIN) { query.Result = true return nil } builder := &sqlstore.SQLBuilder{} builder.Write("SELECT COUNT(dashboard.id) AS count FROM dashboard WHERE dashboard.org_id = ? AND dashboard.is_folder = ?", query.SignedInUser.OrgId, d.dialect.BooleanStr(true)) builder.WriteDashboardPermissionFilter(query.SignedInUser, models.PERMISSION_ADMIN) type folderCount struct { Count int64 } resp := make([]*folderCount, 0) if err := dbSession.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&resp); err != nil { return err } query.Result = len(resp) > 0 && resp[0].Count > 0 return nil }) }