sqlbuilder_test.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. package sqlstore
  2. import (
  3. "context"
  4. "math/rand"
  5. "testing"
  6. "time"
  7. "github.com/grafana/grafana/pkg/components/simplejson"
  8. "github.com/grafana/grafana/pkg/models"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func TestSqlBuilder(t *testing.T) {
  12. t.Run("writeDashboardPermissionFilter", func(t *testing.T) {
  13. t.Run("user ACL", func(t *testing.T) {
  14. test(t,
  15. DashboardProps{},
  16. &DashboardPermission{User: true, Permission: models.PERMISSION_VIEW},
  17. Search{UserFromACL: true, RequiredPermission: models.PERMISSION_VIEW},
  18. shouldFind,
  19. )
  20. test(t,
  21. DashboardProps{},
  22. &DashboardPermission{User: true, Permission: models.PERMISSION_VIEW},
  23. Search{UserFromACL: true, RequiredPermission: models.PERMISSION_EDIT},
  24. shouldNotFind,
  25. )
  26. test(t,
  27. DashboardProps{},
  28. &DashboardPermission{User: true, Permission: models.PERMISSION_EDIT},
  29. Search{UserFromACL: true, RequiredPermission: models.PERMISSION_EDIT},
  30. shouldFind,
  31. )
  32. test(t,
  33. DashboardProps{},
  34. &DashboardPermission{User: true, Permission: models.PERMISSION_VIEW},
  35. Search{RequiredPermission: models.PERMISSION_VIEW},
  36. shouldNotFind,
  37. )
  38. })
  39. t.Run("role ACL", func(t *testing.T) {
  40. test(t,
  41. DashboardProps{},
  42. &DashboardPermission{Role: models.ROLE_VIEWER, Permission: models.PERMISSION_VIEW},
  43. Search{UsersOrgRole: models.ROLE_VIEWER, RequiredPermission: models.PERMISSION_VIEW},
  44. shouldFind,
  45. )
  46. test(t,
  47. DashboardProps{},
  48. &DashboardPermission{Role: models.ROLE_VIEWER, Permission: models.PERMISSION_VIEW},
  49. Search{UsersOrgRole: models.ROLE_VIEWER, RequiredPermission: models.PERMISSION_EDIT},
  50. shouldNotFind,
  51. )
  52. test(t,
  53. DashboardProps{},
  54. &DashboardPermission{Role: models.ROLE_EDITOR, Permission: models.PERMISSION_VIEW},
  55. Search{UsersOrgRole: models.ROLE_VIEWER, RequiredPermission: models.PERMISSION_VIEW},
  56. shouldNotFind,
  57. )
  58. test(t,
  59. DashboardProps{},
  60. &DashboardPermission{Role: models.ROLE_EDITOR, Permission: models.PERMISSION_VIEW},
  61. Search{UsersOrgRole: models.ROLE_VIEWER, RequiredPermission: models.PERMISSION_VIEW},
  62. shouldNotFind,
  63. )
  64. })
  65. t.Run("team ACL", func(t *testing.T) {
  66. test(t,
  67. DashboardProps{},
  68. &DashboardPermission{Team: true, Permission: models.PERMISSION_VIEW},
  69. Search{UserFromACL: true, RequiredPermission: models.PERMISSION_VIEW},
  70. shouldFind,
  71. )
  72. test(t,
  73. DashboardProps{},
  74. &DashboardPermission{Team: true, Permission: models.PERMISSION_VIEW},
  75. Search{UserFromACL: true, RequiredPermission: models.PERMISSION_EDIT},
  76. shouldNotFind,
  77. )
  78. test(t,
  79. DashboardProps{},
  80. &DashboardPermission{Team: true, Permission: models.PERMISSION_EDIT},
  81. Search{UserFromACL: true, RequiredPermission: models.PERMISSION_EDIT},
  82. shouldFind,
  83. )
  84. test(t,
  85. DashboardProps{},
  86. &DashboardPermission{Team: true, Permission: models.PERMISSION_EDIT},
  87. Search{UserFromACL: false, RequiredPermission: models.PERMISSION_EDIT},
  88. shouldNotFind,
  89. )
  90. })
  91. t.Run("defaults for user ACL", func(t *testing.T) {
  92. test(t,
  93. DashboardProps{},
  94. nil,
  95. Search{OrgId: -1, UsersOrgRole: models.ROLE_VIEWER, RequiredPermission: models.PERMISSION_VIEW},
  96. shouldNotFind,
  97. )
  98. test(t,
  99. DashboardProps{OrgId: -1},
  100. nil,
  101. Search{OrgId: -1, UsersOrgRole: models.ROLE_VIEWER, RequiredPermission: models.PERMISSION_VIEW},
  102. shouldFind,
  103. )
  104. test(t,
  105. DashboardProps{OrgId: -1},
  106. nil,
  107. Search{OrgId: -1, UsersOrgRole: models.ROLE_EDITOR, RequiredPermission: models.PERMISSION_EDIT},
  108. shouldFind,
  109. )
  110. test(t,
  111. DashboardProps{OrgId: -1},
  112. nil,
  113. Search{OrgId: -1, UsersOrgRole: models.ROLE_VIEWER, RequiredPermission: models.PERMISSION_EDIT},
  114. shouldNotFind,
  115. )
  116. })
  117. })
  118. }
  119. var shouldFind = true
  120. var shouldNotFind = false
  121. type DashboardProps struct {
  122. OrgId int64
  123. }
  124. type DashboardPermission struct {
  125. User bool
  126. Team bool
  127. Role models.RoleType
  128. Permission models.PermissionType
  129. }
  130. type Search struct {
  131. UsersOrgRole models.RoleType
  132. UserFromACL bool
  133. RequiredPermission models.PermissionType
  134. OrgId int64
  135. }
  136. type dashboardResponse struct {
  137. Id int64
  138. }
  139. func test(t *testing.T, dashboardProps DashboardProps, dashboardPermission *DashboardPermission, search Search, shouldFind bool) {
  140. // Will also cleanup the db
  141. sqlStore := InitTestDB(t)
  142. dashboard, err := createDummyDashboard(dashboardProps)
  143. if !assert.Equal(t, nil, err) {
  144. return
  145. }
  146. var aclUserId int64
  147. if dashboardPermission != nil {
  148. aclUserId, err = createDummyAcl(dashboardPermission, search, dashboard.Id)
  149. if !assert.Equal(t, nil, err) {
  150. return
  151. }
  152. }
  153. dashboards, err := getDashboards(sqlStore, search, aclUserId)
  154. if !assert.Equal(t, nil, err) {
  155. return
  156. }
  157. if shouldFind {
  158. if assert.Equal(t, 1, len(dashboards), "Should return one dashboard") {
  159. assert.Equal(t, dashboards[0].Id, dashboard.Id, "Should return created dashboard")
  160. }
  161. } else {
  162. assert.Equal(t, 0, len(dashboards), "Should node return any dashboard")
  163. }
  164. }
  165. func createDummyUser() (*models.User, error) {
  166. uid := rand.Intn(9999999)
  167. createUserCmd := &models.CreateUserCommand{
  168. Email: string(uid) + "@example.com",
  169. Login: string(uid),
  170. Name: string(uid),
  171. Company: "",
  172. OrgName: "",
  173. Password: string(uid),
  174. EmailVerified: true,
  175. IsAdmin: false,
  176. SkipOrgSetup: false,
  177. DefaultOrgRole: string(models.ROLE_VIEWER),
  178. }
  179. err := CreateUser(context.Background(), createUserCmd)
  180. if err != nil {
  181. return nil, err
  182. }
  183. return &createUserCmd.Result, nil
  184. }
  185. func createDummyTeam() (*models.Team, error) {
  186. cmd := &models.CreateTeamCommand{
  187. // Does not matter in this tests actually
  188. OrgId: 1,
  189. Name: "test",
  190. Email: "test@example.com",
  191. }
  192. err := CreateTeam(cmd)
  193. if err != nil {
  194. return nil, err
  195. }
  196. return &cmd.Result, nil
  197. }
  198. func createDummyDashboard(dashboardProps DashboardProps) (*models.Dashboard, error) {
  199. json, _ := simplejson.NewJson([]byte(`{"schemaVersion":17,"title":"gdev dashboards","uid":"","version":1}`))
  200. saveDashboardCmd := &models.SaveDashboardCommand{
  201. Dashboard: json,
  202. UserId: 0,
  203. Overwrite: false,
  204. Message: "",
  205. RestoredFrom: 0,
  206. PluginId: "",
  207. FolderId: 0,
  208. IsFolder: false,
  209. UpdatedAt: time.Time{},
  210. }
  211. if dashboardProps.OrgId != 0 {
  212. saveDashboardCmd.OrgId = dashboardProps.OrgId
  213. } else {
  214. saveDashboardCmd.OrgId = 1
  215. }
  216. err := SaveDashboard(saveDashboardCmd)
  217. if err != nil {
  218. return nil, err
  219. }
  220. return saveDashboardCmd.Result, nil
  221. }
  222. func createDummyAcl(dashboardPermission *DashboardPermission, search Search, dashboardId int64) (int64, error) {
  223. acl := &models.DashboardAcl{
  224. OrgId: 1,
  225. Created: time.Now(),
  226. Updated: time.Now(),
  227. Permission: dashboardPermission.Permission,
  228. DashboardId: dashboardId,
  229. }
  230. var user *models.User
  231. var err error
  232. if dashboardPermission.User {
  233. user, err = createDummyUser()
  234. if err != nil {
  235. return 0, err
  236. }
  237. acl.UserId = user.Id
  238. }
  239. if dashboardPermission.Team {
  240. team, err := createDummyTeam()
  241. if err != nil {
  242. return 0, err
  243. }
  244. if search.UserFromACL {
  245. user, err = createDummyUser()
  246. if err != nil {
  247. return 0, err
  248. }
  249. addTeamMemberCmd := &models.AddTeamMemberCommand{
  250. UserId: user.Id,
  251. OrgId: 1,
  252. TeamId: team.Id,
  253. }
  254. err = AddTeamMember(addTeamMemberCmd)
  255. if err != nil {
  256. return 0, err
  257. }
  258. }
  259. acl.TeamId = team.Id
  260. }
  261. if len(string(dashboardPermission.Role)) > 0 {
  262. acl.Role = &dashboardPermission.Role
  263. }
  264. updateAclCmd := &models.UpdateDashboardAclCommand{
  265. DashboardId: dashboardId,
  266. Items: []*models.DashboardAcl{acl},
  267. }
  268. err = UpdateDashboardAcl(updateAclCmd)
  269. if user != nil {
  270. return user.Id, err
  271. }
  272. return 0, err
  273. }
  274. func getDashboards(sqlStore *SqlStore, search Search, aclUserId int64) ([]*dashboardResponse, error) {
  275. builder := &SqlBuilder{}
  276. signedInUser := &models.SignedInUser{
  277. UserId: 9999999999,
  278. }
  279. if search.OrgId == 0 {
  280. signedInUser.OrgId = 1
  281. } else {
  282. signedInUser.OrgId = search.OrgId
  283. }
  284. if len(string(search.UsersOrgRole)) > 0 {
  285. signedInUser.OrgRole = search.UsersOrgRole
  286. } else {
  287. signedInUser.OrgRole = models.ROLE_VIEWER
  288. }
  289. if search.UserFromACL {
  290. signedInUser.UserId = aclUserId
  291. }
  292. var res []*dashboardResponse
  293. builder.Write("SELECT * FROM dashboard WHERE true")
  294. builder.writeDashboardPermissionFilter(signedInUser, search.RequiredPermission)
  295. err := sqlStore.engine.SQL(builder.GetSqlString(), builder.params...).Find(&res)
  296. return res, err
  297. }