dashboard_acl.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package sqlstore
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/grafana/grafana/pkg/bus"
  6. m "github.com/grafana/grafana/pkg/models"
  7. )
  8. func init() {
  9. bus.AddHandler("sql", SetDashboardAcl)
  10. bus.AddHandler("sql", UpdateDashboardAcl)
  11. bus.AddHandler("sql", RemoveDashboardAcl)
  12. bus.AddHandler("sql", GetDashboardAclInfoList)
  13. }
  14. func UpdateDashboardAcl(cmd *m.UpdateDashboardAclCommand) error {
  15. return inTransaction(func(sess *DBSession) error {
  16. // delete existing items
  17. _, err := sess.Exec("DELETE FROM dashboard_acl WHERE dashboard_id=?", cmd.DashboardId)
  18. if err != nil {
  19. return err
  20. }
  21. for _, item := range cmd.Items {
  22. if item.UserId == 0 && item.TeamId == 0 && !item.Role.IsValid() {
  23. return m.ErrDashboardAclInfoMissing
  24. }
  25. if item.DashboardId == 0 {
  26. return m.ErrDashboardPermissionDashboardEmpty
  27. }
  28. sess.Nullable("user_id", "team_id")
  29. if _, err := sess.Insert(item); err != nil {
  30. return err
  31. }
  32. }
  33. // Update dashboard HasAcl flag
  34. dashboard := m.Dashboard{HasAcl: true}
  35. if _, err := sess.Cols("has_acl").Where("id=? OR folder_id=?", cmd.DashboardId, cmd.DashboardId).Update(&dashboard); err != nil {
  36. return err
  37. }
  38. return nil
  39. })
  40. }
  41. func SetDashboardAcl(cmd *m.SetDashboardAclCommand) error {
  42. return inTransaction(func(sess *DBSession) error {
  43. if cmd.UserId == 0 && cmd.TeamId == 0 {
  44. return m.ErrDashboardAclInfoMissing
  45. }
  46. if cmd.DashboardId == 0 {
  47. return m.ErrDashboardPermissionDashboardEmpty
  48. }
  49. 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 {
  50. return err
  51. } else if len(res) == 1 {
  52. entity := m.DashboardAcl{
  53. Permission: cmd.Permission,
  54. Updated: time.Now(),
  55. }
  56. 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 {
  57. return err
  58. }
  59. return nil
  60. }
  61. entity := m.DashboardAcl{
  62. OrgId: cmd.OrgId,
  63. TeamId: cmd.TeamId,
  64. UserId: cmd.UserId,
  65. Created: time.Now(),
  66. Updated: time.Now(),
  67. DashboardId: cmd.DashboardId,
  68. Permission: cmd.Permission,
  69. }
  70. cols := []string{"org_id", "created", "updated", "dashboard_id", "permission"}
  71. if cmd.UserId != 0 {
  72. cols = append(cols, "user_id")
  73. }
  74. if cmd.TeamId != 0 {
  75. cols = append(cols, "team_id")
  76. }
  77. _, err := sess.Cols(cols...).Insert(&entity)
  78. if err != nil {
  79. return err
  80. }
  81. cmd.Result = entity
  82. // Update dashboard HasAcl flag
  83. dashboard := m.Dashboard{
  84. HasAcl: true,
  85. }
  86. if _, err := sess.Cols("has_acl").Where("id=? OR folder_id=?", cmd.DashboardId, cmd.DashboardId).Update(&dashboard); err != nil {
  87. return err
  88. }
  89. return nil
  90. })
  91. }
  92. // RemoveDashboardAcl removes a specified permission from the dashboard acl
  93. func RemoveDashboardAcl(cmd *m.RemoveDashboardAclCommand) error {
  94. return inTransaction(func(sess *DBSession) error {
  95. var rawSQL = "DELETE FROM " + dialect.Quote("dashboard_acl") + " WHERE org_id =? and id=?"
  96. _, err := sess.Exec(rawSQL, cmd.OrgId, cmd.AclId)
  97. if err != nil {
  98. return err
  99. }
  100. return err
  101. })
  102. }
  103. // GetDashboardAclInfoList returns a list of permissions for a dashboard. They can be fetched from three
  104. // different places.
  105. // 1) Permissions for the dashboard
  106. // 2) permissions for its parent folder
  107. // 3) if no specific permissions have been set for the dashboard or its parent folder then get the default permissions
  108. func GetDashboardAclInfoList(query *m.GetDashboardAclInfoListQuery) error {
  109. var err error
  110. if query.DashboardId == 0 {
  111. sql := `SELECT
  112. da.id,
  113. da.org_id,
  114. da.dashboard_id,
  115. da.user_id,
  116. da.team_id,
  117. da.permission,
  118. da.role,
  119. da.created,
  120. da.updated,
  121. '' as user_login,
  122. '' as user_email,
  123. '' as team,
  124. '' as title,
  125. '' as slug,
  126. '' as uid,` +
  127. dialect.BooleanStr(false) + ` AS is_folder
  128. FROM dashboard_acl as da
  129. WHERE da.dashboard_id = -1`
  130. query.Result = make([]*m.DashboardAclInfoDTO, 0)
  131. err = x.SQL(sql).Find(&query.Result)
  132. } else {
  133. dashboardFilter := fmt.Sprintf(`IN (
  134. SELECT %d
  135. UNION
  136. SELECT folder_id from dashboard where id = %d
  137. )`, query.DashboardId, query.DashboardId)
  138. rawSQL := `
  139. -- get permissions for the dashboard and its parent folder
  140. SELECT
  141. da.id,
  142. da.org_id,
  143. da.dashboard_id,
  144. da.user_id,
  145. da.team_id,
  146. da.permission,
  147. da.role,
  148. da.created,
  149. da.updated,
  150. u.login AS user_login,
  151. u.email AS user_email,
  152. ug.name AS team,
  153. d.title,
  154. d.slug,
  155. d.uid,
  156. d.is_folder
  157. FROM` + dialect.Quote("dashboard_acl") + ` as da
  158. LEFT OUTER JOIN ` + dialect.Quote("user") + ` AS u ON u.id = da.user_id
  159. LEFT OUTER JOIN team ug on ug.id = da.team_id
  160. LEFT OUTER JOIN dashboard d on da.dashboard_id = d.id
  161. WHERE dashboard_id ` + dashboardFilter + ` AND da.org_id = ?
  162. -- Also include default permissions if folder or dashboard field "has_acl" is false
  163. UNION
  164. SELECT
  165. da.id,
  166. da.org_id,
  167. da.dashboard_id,
  168. da.user_id,
  169. da.team_id,
  170. da.permission,
  171. da.role,
  172. da.created,
  173. da.updated,
  174. '' as user_login,
  175. '' as user_email,
  176. '' as team,
  177. folder.title,
  178. folder.slug,
  179. folder.uid,
  180. folder.is_folder
  181. FROM dashboard_acl as da,
  182. dashboard as dash
  183. LEFT OUTER JOIN dashboard folder on dash.folder_id = folder.id
  184. WHERE
  185. dash.id = ? AND (
  186. dash.has_acl = ` + dialect.BooleanStr(false) + ` or
  187. folder.has_acl = ` + dialect.BooleanStr(false) + `
  188. ) AND
  189. da.dashboard_id = -1
  190. ORDER BY 1 ASC
  191. `
  192. query.Result = make([]*m.DashboardAclInfoDTO, 0)
  193. err = x.SQL(rawSQL, query.OrgId, query.DashboardId).Find(&query.Result)
  194. }
  195. for _, p := range query.Result {
  196. p.PermissionName = p.Permission.String()
  197. }
  198. return err
  199. }